Commit 38efa482 authored by Robert Foss's avatar Robert Foss
Browse files

Merge remote-tracking branch 'upstream/dev' into dev

parents d2fc8782 340edbbe
......@@ -18,13 +18,13 @@
** Hence even when the load factor reaches 100%, performance remains good.
*/
#include "c_math.h"
#include "c_string.h"
#define ltable_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_MATH
#include C_HEADER_STRING
#include "ldebug.h"
#include "ldo.h"
......
......@@ -5,10 +5,9 @@
*/
#include "c_stddef.h"
#define ltablib_c
#define LUA_LIB
#define LUAC_CROSS_FILE
#include "lua.h"
......
......@@ -5,12 +5,12 @@
*/
#include "c_string.h"
#define ltm_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include "lobject.h"
#include "lstate.h"
......
......@@ -22,22 +22,12 @@
#include "os_type.h"
os_timer_t lua_timer;
LOCAL os_timer_t readline_timer;
lua_State *globalL = NULL;
lua_Load gLoad;
static const char *progname = LUA_PROGNAME;
#ifdef DEVKIT_VERSION_0_9
static int key_press_count = 0;
int led_high_count = LED_HIGH_COUNT_DEFAULT;
int led_low_count = LED_LOW_COUNT_DEFAULT;
static int led_count = 0;
#endif
#if 0
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
......@@ -135,9 +125,13 @@ static int docall (lua_State *L, int narg, int clear) {
}
static void print_version (void) {
// l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT);
l_message(NULL, "\n" NODE_VERSION " " BUILD_DATE " powered by " LUA_RELEASE);
static void print_version (lua_State *L) {
lua_pushliteral (L, "\n" NODE_VERSION " build " BUILD_DATE " powered by " LUA_RELEASE " on SDK ");
lua_pushstring (L, SDK_VERSION);
lua_concat (L, 2);
const char *msg = lua_tostring (L, -1);
l_message (NULL, msg);
lua_pop (L, 1);
}
......@@ -399,7 +393,7 @@ static int pmain (lua_State *L) {
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L); /* open libraries */
lua_gc(L, LUA_GCRESTART, 0);
print_version();
print_version(L);
s->status = handle_luainit(L);
#if 0
if (s->status != 0) return 0;
......@@ -432,8 +426,8 @@ static int pmain (lua_State *L) {
return 0;
}
void dojob(lua_Load *load);
void readline(lua_Load *load);
static void dojob(lua_Load *load);
static bool readline(lua_Load *load);
char line_buffer[LUA_MAXINPUT];
#ifdef LUA_RPC
......@@ -461,10 +455,7 @@ int lua_main (int argc, char **argv) {
gLoad.line_position = 0;
gLoad.prmt = get_prompt(L, 1);
// dojob(&gLoad);
os_timer_disarm(&lua_timer);
os_timer_setfn(&lua_timer, (os_timer_func_t *)dojob, &gLoad);
os_timer_arm(&lua_timer, READLINE_INTERVAL, 0); // no repeat
dojob(&gLoad);
NODE_DBG("Heap size::%d.\n",system_get_free_heap_size());
legc_set_mode( L, EGC_ALWAYS, 4096 );
......@@ -473,16 +464,17 @@ int lua_main (int argc, char **argv) {
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
}
void lua_handle_input (bool force)
{
if (force || readline (&gLoad))
dojob (&gLoad);
}
void donejob(lua_Load *load){
lua_close(load->L);
}
#if 0
int log_fd = -1;
int noparse = 0;
#endif
void dojob(lua_Load *load){
static void dojob(lua_Load *load){
size_t l, rs;
int status;
char *b = load->line;
......@@ -538,53 +530,8 @@ void dojob(lua_Load *load){
load->done = 0;
load->line_position = 0;
c_memset(load->line, 0, load->len);
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
c_puts(load->prmt);
// NODE_DBG("dojob() is called with firstline.\n");
}
#ifdef DEVKIT_VERSION_0_9
extern void key_long_press(void *arg);
extern void key_short_press(void *arg);
static bool key_short_pressed = false;
static bool key_long_pressed = false;
void update_key_led(){
uint8_t temp = 1, level = 1;
led_count++;
if(led_count>led_low_count+led_high_count){
led_count = 0; // reset led_count, the level still high
} else if(led_count>led_low_count && led_count <=led_high_count+led_low_count){
level = 1; // output high level
} else if(led_count<=led_low_count){
level = 0; // output low level
}
temp = platform_key_led(level);
if(temp == 0){ // key is pressed
key_press_count++;
if(key_press_count>=KEY_LONG_COUNT){
// key_long_press(NULL);
key_long_pressed = true;
key_short_pressed = false;
// key_press_count = 0;
} else if(key_press_count>=KEY_SHORT_COUNT){ // < KEY_LONG_COUNT
// key_short_press(NULL);
key_short_pressed = true;
}
}else{ // key is released
key_press_count = 0;
if(key_long_pressed){
key_long_press(NULL);
key_long_pressed = false;
}
if(key_short_pressed){
key_short_press(NULL);
key_short_pressed = false;
}
}
}
#endif
#ifndef uart_putc
#define uart_putc uart0_putc
......@@ -594,11 +541,9 @@ extern bool uart0_echo;
extern bool run_input;
extern uint16_t need_len;
extern int16_t end_char;
void readline(lua_Load *load){
static bool readline(lua_Load *load){
// NODE_DBG("readline() is called.\n");
#ifdef DEVKIT_VERSION_0_9
update_key_led();
#endif
bool need_dojob = false;
char ch;
while (uart_getc(&ch))
{
......@@ -644,14 +589,9 @@ void readline(lua_Load *load){
{
/* Get a empty line, then go to get a new line */
c_puts(load->prmt);
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
} else {
load->done = 1;
os_timer_disarm(&lua_timer);
os_timer_setfn(&lua_timer, (os_timer_func_t *)dojob, load);
os_timer_arm(&lua_timer, READLINE_INTERVAL, 0); // no repeat
need_dojob = true;
}
continue;
}
......@@ -693,8 +633,6 @@ void readline(lua_Load *load){
uart_on_data_cb(load->line, load->line_position);
load->line_position = 0;
}
// if there is no input from user, repeat readline()
os_timer_disarm(&readline_timer);
os_timer_setfn(&readline_timer, (os_timer_func_t *)readline, load);
os_timer_arm(&readline_timer, READLINE_INTERVAL, 0); // no repeat
return need_dojob;
}
......@@ -8,10 +8,18 @@
#ifndef lua_h
#define lua_h
#ifdef LUAC_CROSS_FILE
#include "luac_cross.h"
#endif
#ifdef LUA_CROSS_COMPILER
#include <stdarg.h>
#include <stddef.h>
#include <ctype.h>
#else
#include "c_stdarg.h"
#include "c_stddef.h"
#include "c_types.h"
#endif
#include "luaconf.h"
......@@ -94,6 +102,9 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
#include LUA_USER_H
#endif
#if defined(LUA_OPTIMIZE_DEBUG) && LUA_OPTIMIZE_DEBUG == 0
#undef LUA_OPTIMIZE_DEBUG
#endif
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
......@@ -250,7 +261,7 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
/*
/*
** ===============================================================
** some useful macros
** ===============================================================
......@@ -382,6 +393,10 @@ typedef struct __lua_load{
int lua_main( int argc, char **argv );
#ifndef LUA_CROSS_COMPILER
void lua_handle_input (bool force);
#endif
/******************************************************************************
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
*
......
/*
** Header to allow luac.cross compile within NodeMCU
** See Copyright Notice in lua.h
*/
#ifndef luac_cross_h
#define luac_cross_h
#ifdef LUA_CROSS_COMPILER
#define C_HEADER_ASSERT <assert.h>
#define C_HEADER_CTYPE <ctype.h>
#define C_HEADER_ERRNO <errno.h>
#define C_HEADER_FCNTL <fcntl.h>
#define C_HEADER_LOCALE <locale.h>
#define C_HEADER_MATH <math.h>
#define C_HEADER_STDIO <stdio.h>
#define C_HEADER_STDLIB <stdlib.h>
#define C_HEADER_STRING <string.h>
#define C_HEADER_TIME <time.h>
#define ICACHE_RODATA_ATTR
#define c_abs abs
#define c_exit exit
#define c_fclose fclose
#define c_feof feof
#define c_ferror ferror
#define c_fopen fopen
#define c_fread fread
#define c_free free
#define c_freopen freopen
#define c_getc getc
#define c_getenv getenv
#define c_memcmp memcmp
#define c_memcpy memcpy
#define c_printf printf
#define c_puts puts
#define c_reader reader
#define c_realloc realloc
#define c_sprintf sprintf
#define c_stderr stderr
#define c_stdin stdin
#define c_stdout stdout
#define c_strcat strcat
#define c_strchr strchr
#define c_strcmp strcmp
#define c_strcoll strcoll
#define c_strcpy strcpy
#define c_strcspn strcspn
#define c_strerror strerror
#define c_strlen strlen
#define c_strncat strncat
#define c_strncmp strncmp
#define c_strncpy strncpy
#define c_strpbrk strpbrk
#define c_strrchr strrchr
#define c_strstr strstr
double c_strtod(const char *__n, char **__end_PTR);
#define c_strtoul strtoul
#define c_ungetc ungetc
#else
#define C_HEADER_ASSERT "c_assert.h"
#define C_HEADER_CTYPE "c_ctype.h"
#define C_HEADER_ERRNO "c_errno.h"
#define C_HEADER_FCNTL "c_fcntl.h"
#define C_HEADER_LOCALE "c_locale.h"
#define C_HEADER_MATH "c_math.h"
#define C_HEADER_STDIO "c_stdio.h"
#define C_HEADER_STDLIB "c_stdlib.h"
#define C_HEADER_STRING "c_string.h"
#define C_HEADER_TIME "c_time.h"
#endif /* LUA_CROSS_COMPILER */
#endif /* luac_cross_h */
......@@ -4,12 +4,14 @@
** See Copyright Notice in lua.h
*/
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_ERRNO
#include C_HEADER_LOCALE
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#include C_HEADER_TIME
#define loslib_c
#define LUA_LIB
......
......@@ -4,10 +4,13 @@
** See Copyright Notice in lua.h
*/
#include "c_errno.h"
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_ERRNO
#include C_HEADER_STDIO
#include C_HEADER_STDLIB
#include C_HEADER_STRING
#define luac_c
#define LUA_CORE
......
......@@ -4,8 +4,11 @@
** See Copyright Notice in lua.h
*/
#include "c_ctype.h"
#include "c_stdio.h"
#define LUAC_CROSS_FILE
#include "luac_cross.h"
#include C_HEADER_CTYPE
#include C_HEADER_STDIO
#define luac_c
#define LUA_CORE
......
......@@ -8,8 +8,13 @@
#ifndef lconfig_h
#define lconfig_h
#ifdef LUA_CROSS_COMPILER
#include <limits.h>
#include <stddef.h>
#else
#include "c_limits.h"
#include "c_stddef.h"
#endif
#include "user_config.h"
/*
......@@ -252,7 +257,12 @@
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#ifdef LUA_CROSS_COMPILER
#include <stdio.h>
else
#include "c_stdio.h"
#endif
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
......@@ -294,8 +304,8 @@
** GNU readline and history facilities).
*/
#if defined(LUA_USE_STDIO)
#if defined(LUA_USE_READLINE)
#include "c_stdio.h"
#if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
......@@ -303,7 +313,7 @@
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
#define lua_freeline(L,b) ((void)L, c_free(b))
#else // #if defined(LUA_USE_READLINE)
#else // #if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
#define lua_readline(L,b,p) \
((void)L, c_fputs(p, c_stdout), c_fflush(c_stdout), /* show prompt */ \
c_fgets(b, LUA_MAXINPUT, c_stdin) != NULL) /* get line */
......@@ -623,7 +633,11 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
@@ The luai_num* macros define the primitive operations over numbers.
*/
#if defined(LUA_CORE)
#ifdef LUA_CROSS_COMPILER
#include <math.h>
#else
#include "c_math.h"
#endif
#define luai_numadd(a,b) ((a)+(b))
#define luai_numsub(a,b) ((a)-(b))
#define luai_nummul(a,b) ((a)*(b))
......@@ -866,7 +880,10 @@ union luai_Cast { double l_d; long l_l; };
#define LUA_INTFRMLEN "l"
#define LUA_INTFRM_T long
#ifndef LUA_CROSS_COMPILER
typedef short int16_t;
typedef long int32_t;
#endif
#endif
......
......@@ -4,13 +4,12 @@
** See Copyright Notice in lua.h
*/
#include "c_string.h"
#include "c_types.h"
#define lundump_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include "ldebug.h"
#include "ldo.h"
......@@ -236,6 +235,20 @@ static void LoadDebug(LoadState* S, Proto* f)
int i,n;
n=LoadInt(S);
Align4(S);
#ifdef LUA_OPTIMIZE_DEBUG
if(n) {
if (!luaZ_direct_mode(S->Z)) {
f->packedlineinfo=luaM_newvector(S->L,n,unsigned char);
LoadBlock(S,f->packedlineinfo,n);
} else {
f->packedlineinfo=(unsigned char*)luaZ_get_crt_address(S->Z);
LoadBlock(S,NULL,n);
}
} else {
f->packedlineinfo=NULL;
}
#else
if (!luaZ_direct_mode(S->Z)) {
f->lineinfo=luaM_newvector(S->L,n,int);
LoadVector(S,f->lineinfo,n,sizeof(int));
......@@ -244,6 +257,7 @@ static void LoadDebug(LoadState* S, Proto* f)
LoadVector(S,NULL,n,sizeof(int));
}
f->sizelineinfo=n;
#endif
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n;
......
......@@ -7,7 +7,11 @@
#ifndef lundump_h
#define lundump_h
#ifdef LUA_CROSS_COMPILER
#include <stdint.h>
#else
#include "c_stdint.h"
#endif
#include "lobject.h"
#include "lzio.h"
......
......@@ -5,15 +5,14 @@
*/
#include "c_stdio.h"
#include "c_stdlib.h"
#include "c_string.h"
#include "c_math.h"
#define lvm_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STDIO
#include C_HEADER_STRING
#include C_HEADER_MATH
#include "ldebug.h"
#include "ldo.h"
......
......@@ -5,12 +5,12 @@
*/
#include "c_string.h"
#define lzio_c
#define LUA_CORE
#define LUAC_CROSS_FILE
#include "lua.h"
#include C_HEADER_STRING
#include "llimits.h"
#include "lmem.h"
......
#############################################################
# 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 = liblwip.a
COMPONENTS_liblwip = api/liblwipapi.a \
app/liblwipapp.a \
core/liblwipcore.a \
core/ipv4/liblwipipv4.a \
netif/liblwipnetif.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
#############################################################
# 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 = liblwip.a
COMPONENTS_liblwip = api/liblwipapi.a \
app/liblwipapp.a \
core/liblwipcore.a \
core/ipv4/liblwipipv4.a \
netif/liblwipnetif.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
#############################################################
# 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 = liblwipapi.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
#############################################################
# 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 = liblwipapi.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
#############################################################
# 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 = liblwipapp.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
#############################################################
# 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 = liblwipapp.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
#include "lwip/inet.h"
#include "lwip/inet.h"
#include "lwip/err.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
//#include "crypto/common.h"
#include "osapi.h"
#include "lwip/app/dhcpserver.h"
#ifndef LWIP_OPEN_SRC
#include "net80211/ieee80211_var.h"
#endif
#include "user_interface.h"
////////////////////////////////////////////////////////////////////////////////////
static uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
static u8_t old_xid[4] = {0};
static const uint8_t magic_cookie[4] = {99, 130, 83, 99};
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_msg msg_dhcps;
struct dhcps_state s;
static struct dhcps_lease dhcps_lease;
static bool dhcps_lease_flag = true;
static list_node *plist = NULL;
/******************************************************************************
* FunctionName : node_insert_to_list
* Description : insert the node to the list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/mem.h"
//#include "crypto/common.h"
#include "osapi.h"
#include "lwip/app/dhcpserver.h"
#ifndef LWIP_OPEN_SRC
#include "net80211/ieee80211_var.h"
#endif
#include "user_interface.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////////////
//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
//static u8_t old_xid[4] = {0};
static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
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;
static list_node *plist = NULL;
static uint8 offer = 0xFF;
static bool renew = false;
#define DHCPS_LEASE_TIME_DEF (120)
uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
/******************************************************************************
* FunctionName : node_insert_to_list
* Description : insert the node to the list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
{
list_node *plist = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
struct dhcps_pool *pdhcps_node = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
pdhcps_node = pinsert->pnode;
pdhcps_pool = plist->pnode;
if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
pinsert->pnext = plist;
*phead = pinsert;
} else {
while (plist->pnext != NULL) {
pdhcps_pool = plist->pnext->pnode;
if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
pinsert->pnext = plist->pnext;
plist->pnext = pinsert;
break;
}
plist = plist->pnext;
}
if(plist->pnext == NULL) {
plist->pnext = pinsert;
}
}
}
// pinsert->pnext = NULL;
}
/******************************************************************************
* FunctionName : node_delete_from_list
* Description : remove the node from list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
{
list_node *plist = NULL;
plist = *phead;
if (plist == NULL){
*phead = NULL;
} else {
if (plist == pdelete){
*phead = plist->pnext;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
}
plist = plist->pnext;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg��Ϣ�ṹ����������
*
* @param optptr -- DHCP msg��Ϣλ��
* @param type -- Ҫ��ӵ�����option
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
{
*optptr++ = DHCP_OPTION_MSG_TYPE;
*optptr++ = 1;
*optptr++ = type;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg�ṹ������offerӦ������
*
* @param optptr -- DHCP msg��Ϣλ��
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
{
struct ip_addr ipadd;
ipadd.addr = *( (uint32_t *) &server_address);
#ifdef USE_CLASS_B_NET
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = 4; //length
*optptr++ = 255;
*optptr++ = 240;
*optptr++ = 0;
*optptr++ = 0;
#else
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = 4;
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 0;
#endif
*optptr++ = DHCP_OPTION_LEASE_TIME;
*optptr++ = 4;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF;
*optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF;
*optptr++ = DHCP_OPTION_SERVER_ID;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
if (dhcps_router_enabled(offer)){
struct ip_info if_ip;
os_bzero(&if_ip, sizeof(struct ip_info));
wifi_get_ip_info(SOFTAP_IF, &if_ip);
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &if_ip.gw);
*optptr++ = ip4_addr2( &if_ip.gw);
*optptr++ = ip4_addr3( &if_ip.gw);
*optptr++ = ip4_addr4( &if_ip.gw);
}
#ifdef USE_DNS
*optptr++ = DHCP_OPTION_DNS_SERVER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
#endif
#ifdef CLASS_B_NET
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 255;
#else
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = 255;
#endif
*optptr++ = DHCP_OPTION_INTERFACE_MTU;
*optptr++ = 2;
#ifdef CLASS_B_NET
*optptr++ = 0x05;
*optptr++ = 0xdc;
#else
*optptr++ = 0x02;
*optptr++ = 0x40;
#endif
*optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
*optptr++ = 1;
*optptr++ = 0x00;
*optptr++ = 43;
*optptr++ = 6;
*optptr++ = 0x01;
*optptr++ = 4;
*optptr++ = 0x00;
*optptr++ = 0x00;
*optptr++ = 0x00;
*optptr++ = 0x02;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg�ṹ����ӽ����־����
*
* @param optptr -- DHCP msg��Ϣλ��
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_END;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
{
struct ip_addr client;
client.addr = *( (uint32_t *) &client_address);
m->op = DHCP_REPLY;
m->htype = DHCP_HTYPE_ETHERNET;
m->hlen = 6;
m->hops = 0;
// os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
m->secs = 0;
m->flags = htons(BOOTP_BROADCAST);
os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
os_memset((char *) m->sname, 0, sizeof(m->sname));
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));
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��OFFER
*
* @param -- m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m)
{
uint8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendOffer_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPOFFER);
end = add_offer_options(end);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
#endif
return;
}
SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_offer>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��NAK��Ϣ
*
* @param m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m)
{
u8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendNak_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPNAK);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
#endif
return;
}
SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_nak>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��ACK��DHCP�ͻ���
*
* @param m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m)
{
u8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendAck_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPACK);
end = add_offer_options(end);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
#endif
return;
}
SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_ack>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ��
*
* @param optptr DHCP msg���������
* @param len ��������Ĵ��?(byte)
*
* @return uint8_t ���ش�����DHCP Server״ֵ̬
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
{
struct ip_addr client;
bool is_dhcp_parse_end = false;
struct dhcps_state s;
client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
u8_t *end = optptr + len;
u16_t type = 0;
s.state = DHCPS_STATE_IDLE;
while (optptr < end) {
#if DHCPS_DEBUG
os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
#endif
switch ((sint16_t) *optptr) {
case DHCP_OPTION_MSG_TYPE: //53
type = *(optptr + 2);
break;
case DHCP_OPTION_REQ_IPADDR://50
if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
#if DHCPS_DEBUG
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
#endif
s.state = DHCPS_STATE_ACK;
}else {
#if DHCPS_DEBUG
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
#endif
s.state = DHCPS_STATE_NAK;
}
break;
case DHCP_OPTION_END:
{
is_dhcp_parse_end = true;
}
break;
}
if(is_dhcp_parse_end){
break;
}
optptr += optptr[1] + 2;
}
switch (type){
case DHCPDISCOVER://1
s.state = DHCPS_STATE_OFFER;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_OFFER\n");
#endif
break;
case DHCPREQUEST://3
if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
if(renew == true) {
s.state = DHCPS_STATE_ACK;
} else {
s.state = DHCPS_STATE_NAK;
}
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_NAK\n");
#endif
}
break;
case DHCPDECLINE://4
s.state = DHCPS_STATE_IDLE;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_IDLE\n");
#endif
break;
case DHCPRELEASE://7
s.state = DHCPS_STATE_RELEASE;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_IDLE\n");
#endif
break;
}
#if DHCPS_DEBUG
os_printf("dhcps: return s.state = %d\n", s.state);
#endif
return s.state;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
{
list_node *plist = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
while (plist->pnext != NULL) {
plist = plist->pnext;
}
plist->pnext = pinsert;
}
pinsert->pnext = NULL;
}
/******************************************************************************
* FunctionName : node_delete_from_list
* Description : remove the node from list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
{
list_node *plist = NULL;
plist = *phead;
if (plist == NULL){
*phead = NULL;
} else {
if (plist == pdelete){
*phead = plist->pnext;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
}
plist = plist->pnext;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg��Ϣ�ṹ����������
*
* @param optptr -- DHCP msg��Ϣλ��
* @param type -- Ҫ��ӵ�����option
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
{
*optptr++ = DHCP_OPTION_MSG_TYPE;
*optptr++ = 1;
*optptr++ = type;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg�ṹ������offerӦ������
*
* @param optptr -- DHCP msg��Ϣλ��
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
{
struct ip_addr ipadd;
ipadd.addr = *( (uint32_t *) &server_address);
#ifdef USE_CLASS_B_NET
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = 4; //length
*optptr++ = 255;
*optptr++ = 240;
*optptr++ = 0;
*optptr++ = 0;
#else
*optptr++ = DHCP_OPTION_SUBNET_MASK;
*optptr++ = 4;
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 0;
#endif
*optptr++ = DHCP_OPTION_LEASE_TIME;
*optptr++ = 4;
*optptr++ = 0x00;
*optptr++ = 0x01;
*optptr++ = 0x51;
*optptr++ = 0x80;
*optptr++ = DHCP_OPTION_SERVER_ID;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
#if USE_DNS
*optptr++ = DHCP_OPTION_DNS_SERVER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = ip4_addr4( &ipadd);
#endif
#ifdef USE_CLASS_B_NET
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = 255;
*optptr++ = 255;
*optptr++ = 255;
#else
*optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
*optptr++ = 4;
*optptr++ = ip4_addr1( &ipadd);
*optptr++ = ip4_addr2( &ipadd);
*optptr++ = ip4_addr3( &ipadd);
*optptr++ = 255;
#endif
*optptr++ = DHCP_OPTION_INTERFACE_MTU;
*optptr++ = 2;
#ifdef USE_CLASS_B_NET
*optptr++ = 0x05;
*optptr++ = 0xdc;
#else
*optptr++ = 0x02;
*optptr++ = 0x40;
#endif
*optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
*optptr++ = 1;
*optptr++ = 0x00;
*optptr++ = 43;
*optptr++ = 6;
*optptr++ = 0x01;
*optptr++ = 4;
*optptr++ = 0x00;
*optptr++ = 0x00;
*optptr++ = 0x00;
*optptr++ = 0x02;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ��DHCP msg�ṹ����ӽ����־����
*
* @param optptr -- DHCP msg��Ϣλ��
*
* @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
{
*optptr++ = DHCP_OPTION_END;
return optptr;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��DHCP msg�ṹ��
*
* @param -- m ָ�򴴽���DHCP msg�ṹ�����?
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
{
struct ip_addr client;
client.addr = *( (uint32_t *) &client_address);
m->op = DHCP_REPLY;
m->htype = DHCP_HTYPE_ETHERNET;
m->hlen = 6;
m->hops = 0;
os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
m->secs = 0;
m->flags = htons(BOOTP_BROADCAST);
os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
os_memset((char *) m->sname, 0, sizeof(m->sname));
os_memset((char *) m->file, 0, sizeof(m->file));
os_memset((char *) m->options, 0, sizeof(m->options));
os_memcpy((char *) m->options, (char *) magic_cookie, sizeof(magic_cookie));
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��OFFER
*
* @param -- m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m)
{
uint8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendOffer_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPOFFER);
end = add_offer_options(end);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
#endif
return;
}
SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_offer>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��NAK��Ϣ
*
* @param m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m)
{
u8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendNak_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPNAK);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
#endif
return;
}
SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_nak>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����һ��ACK��DHCP�ͻ���
*
* @param m ָ����Ҫ���͵�DHCP msg����
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m)
{
u8_t *end;
struct pbuf *p, *q;
u8_t *data;
u16_t cnt=0;
u16_t i;
err_t SendAck_err_t;
create_msg(m);
end = add_msg_type(&m->options[4], DHCPACK);
end = add_offer_options(end);
end = add_end(end);
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
#if DHCPS_DEBUG
os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
#endif
if(p != NULL){
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
#endif
q = p;
while(q != NULL){
data = (u8_t *)q->payload;
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;
}
}else{
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
#endif
return;
}
SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
#if DHCPS_DEBUG
os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
#endif
if(p->ref != 0){
#if DHCPS_DEBUG
os_printf("udhcp: send_ack>>free pbuf\n");
#endif
pbuf_free(p);
}
}
///////////////////////////////////////////////////////////////////////////////////
/*
* ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ��
*
* @param optptr DHCP msg���������
* @param len ��������Ĵ��?(byte)
*
* @return uint8_t ���ش�����DHCP Server״ֵ̬
*/
///////////////////////////////////////////////////////////////////////////////////
static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
{
struct ip_addr client;
bool is_dhcp_parse_end = false;
client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
u8_t *end = optptr + len;
u16_t type = 0;
s.state = DHCPS_STATE_IDLE;
while (optptr < end) {
#if DHCPS_DEBUG
os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
#endif
switch ((sint16_t) *optptr) {
case DHCP_OPTION_MSG_TYPE: //53
type = *(optptr + 2);
break;
case DHCP_OPTION_REQ_IPADDR://50
if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
#if DHCPS_DEBUG
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
#endif
s.state = DHCPS_STATE_ACK;
}else {
#if DHCPS_DEBUG
os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
#endif
s.state = DHCPS_STATE_NAK;
}
break;
case DHCP_OPTION_END:
{
is_dhcp_parse_end = true;
}
break;
}
if(is_dhcp_parse_end){
break;
}
optptr += optptr[1] + 2;
}
switch (type){
case DHCPDISCOVER://1
s.state = DHCPS_STATE_OFFER;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_OFFER\n");
#endif
break;
case DHCPREQUEST://3
if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
s.state = DHCPS_STATE_NAK;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_NAK\n");
#endif
}
break;
case DHCPDECLINE://4
s.state = DHCPS_STATE_IDLE;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_IDLE\n");
#endif
break;
case DHCPRELEASE://7
s.state = DHCPS_STATE_IDLE;
#if DHCPS_DEBUG
os_printf("dhcps: DHCPD_STATE_IDLE\n");
#endif
break;
}
#if DHCPS_DEBUG
os_printf("dhcps: return s.state = %d\n", s.state);
#endif
return s.state;
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
{
if(os_memcmp((char *)m->options,
(char *)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;
POOL_START:
client_address.addr = client_address_plus.addr;
// 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");
client_address.addr = pdhcps_pool->ip.addr;
pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
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;
}
}
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;
node_insert_to_list(&plist,pnode);
POOL_CHECK:
if ((client_address_plus.addr > dhcps_lease.end_ip) || (ip_addr_isany(&client_address))){
client_address_plus.addr = dhcps_lease.start_ip;
goto POOL_START;
}
if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) {
return 0;
}
}
#if DHCPS_DEBUG
os_printf("dhcps: xid changed\n");
os_printf("dhcps: client_address.addr = %x\n", client_address.addr);
#endif
// }
// }
return parse_options(&m->options[4], len);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������
* ��Ҫ����udp_recv()������LWIP����ע��.
*
* @param arg
* @param pcb ���յ�UDP��Ŀ��ƿ�?
* @param p ���յ���UDP�е��������?
* @param addr ���ʹ�UDP���Դ�����IP��ַ
* @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں�
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
struct udp_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr,
uint16_t port)
{
sint16_t tlen;
u16_t i;
u16_t dhcps_msg_cnt=0;
u8_t *p_dhcps_msg = (u8_t *)&msg_dhcps;
u8_t *data;
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> receive a packet\n");
#endif
if (p==NULL) return;
tlen = p->tot_len;
data = p->payload;
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
#endif
os_memset(&msg_dhcps, 0, sizeof(dhcps_msg));
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) {
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
#endif
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
}
}
/*
* DHCP �ͻ���������Ϣ����
*/
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
#endif
switch(parse_msg(&msg_dhcps, tlen - 240)) {
case DHCPS_STATE_OFFER://1
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
#endif
send_offer(&msg_dhcps);
break;
case DHCPS_STATE_ACK://3
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
#endif
send_ack(&msg_dhcps);
break;
case DHCPS_STATE_NAK://4
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
#endif
send_nak(&msg_dhcps);
break;
default :
break;
}
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
#endif
pbuf_free(p);
}
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
{
uint32 softap_ip = 0,local_ip = 0;
if (dhcps_lease_flag) {
local_ip = softap_ip = htonl(ip);
softap_ip &= 0xFFFFFF00;
local_ip &= 0xFF;
if (local_ip >= 0x80)
local_ip -= DHCPS_MAX_LEASE;
else
local_ip ++;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
dhcps_lease.start_ip = softap_ip | local_ip;
dhcps_lease.end_ip = softap_ip | (local_ip + DHCPS_MAX_LEASE);
}
dhcps_lease.start_ip = htonl(dhcps_lease.start_ip);
dhcps_lease.end_ip= htonl(dhcps_lease.end_ip);
// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
}
///////////////////////////////////////////////////////////////////////////////////
void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
{
os_memset(&msg_dhcps, 0, sizeof(dhcps_msg));
pcb_dhcps = udp_new();
if (pcb_dhcps == NULL || info ==NULL) {
os_printf("dhcps_start(): could not obtain pcb\n");
}
IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
server_address = info->ip;
wifi_softap_init_dhcps_lease(server_address.addr);
client_address_plus.addr = dhcps_lease.start_ip;
udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
udp_recv(pcb_dhcps, handle_dhcp, NULL);
#if DHCPS_DEBUG
os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
#endif
}
void ICACHE_FLASH_ATTR dhcps_stop(void)
{
udp_disconnect(pcb_dhcps);
udp_remove(pcb_dhcps);
list_node *pnode = NULL;
list_node *pback_node = NULL;
pnode = plist;
while (pnode != NULL) {
pback_node = pnode;
pnode = pback_node->pnext;
node_remove_from_list(&plist, pback_node);
os_free(pback_node->pnode);
pback_node->pnode = NULL;
os_free(pback_node);
pback_node = NULL;
}
}
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
{
struct ip_info info;
uint32 softap_ip = 0;
if (please == NULL)
return false;
os_bzero(&info, sizeof(struct ip_info));
wifi_get_ip_info(SOFTAP_IF, &info);
softap_ip = htonl(info.ip.addr);
please->start_ip = htonl(please->start_ip);
please->end_ip = htonl(please->end_ip);
/*config ip information can't contain local ip*/
if ((please->start_ip <= softap_ip) && (softap_ip <= please->end_ip))
return false;
/*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8;
if ((please->start_ip >> 8 != softap_ip)
|| (please->end_ip >> 8 != softap_ip)) {
return false;
}
if (please->end_ip - please->start_ip > DHCPS_MAX_LEASE)
return false;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
dhcps_lease.start_ip = please->start_ip;
dhcps_lease.end_ip = please->end_ip;
dhcps_lease_flag = false;
return true;
}
void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
{
list_node *pback_node = NULL;
list_node *pnode = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
pnode = plist;
while (pnode != NULL) {
pdhcps_pool = pnode->pnode;
pdhcps_pool->lease_timer --;
if (pdhcps_pool->lease_timer == 0){
pback_node = pnode;
pnode = pback_node->pnext;
node_remove_from_list(&plist,pback_node);
os_free(pback_node->pnode);
pback_node->pnode = NULL;
os_free(pback_node);
pback_node = NULL;
} else {
pnode = pnode ->pnext;
}
}
}
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 DHCPS_DEBUG
os_printf("dhcps: xid changed\n");
os_printf("dhcps: client_address.addr = %x\n", client_address.addr);
#endif
// }
// }
return ret;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
/*
* DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������
* ��Ҫ����udp_recv()������LWIP����ע��.
*
* @param arg
* @param pcb ���յ�UDP��Ŀ��ƿ�?
* @param p ���յ���UDP�е��������?
* @param addr ���ʹ�UDP���Դ�����IP��ַ
* @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں�
*/
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
struct udp_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr,
uint16_t port)
{
struct dhcps_msg *pmsg_dhcps = NULL;
sint16_t tlen = 0;
u16_t i = 0;
u16_t dhcps_msg_cnt = 0;
u8_t *p_dhcps_msg = NULL;
u8_t *data = NULL;
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> receive a packet\n");
#endif
if (p==NULL) return;
pmsg_dhcps = (struct dhcps_msg *)os_zalloc(sizeof(struct dhcps_msg));
if (NULL == pmsg_dhcps){
pbuf_free(p);
return;
}
p_dhcps_msg = (u8_t *)pmsg_dhcps;
tlen = p->tot_len;
data = p->payload;
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
#endif
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) {
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
#endif
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
}
}
/*
* DHCP �ͻ���������Ϣ����
*/
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
#endif
switch(parse_msg(pmsg_dhcps, tlen - 240)) {
case DHCPS_STATE_OFFER://1
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
#endif
send_offer(pmsg_dhcps);
break;
case DHCPS_STATE_ACK://3
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
#endif
send_ack(pmsg_dhcps);
break;
case DHCPS_STATE_NAK://4
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
#endif
send_nak(pmsg_dhcps);
break;
default :
break;
}
#if DHCPS_DEBUG
os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
#endif
pbuf_free(p);
os_free(pmsg_dhcps);
pmsg_dhcps = NULL;
}
///////////////////////////////////////////////////////////////////////////////////
static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
{
uint32 softap_ip = 0,local_ip = 0;
uint32 start_ip = 0;
uint32 end_ip = 0;
// if (dhcps_lease_flag) {
if (dhcps_lease.enable == TRUE) {
softap_ip = htonl(ip);
start_ip = htonl(dhcps_lease.start_ip.addr);
end_ip = htonl(dhcps_lease.end_ip.addr);
/*config ip information can't contain local ip*/
if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
dhcps_lease.enable = FALSE;
} else {
/*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8;
if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
|| (end_ip - start_ip > DHCPS_MAX_LEASE)) {
dhcps_lease.enable = FALSE;
}
}
}
if (dhcps_lease.enable == FALSE) {
local_ip = softap_ip = htonl(ip);
softap_ip &= 0xFFFFFF00;
local_ip &= 0xFF;
if (local_ip >= 0x80)
local_ip -= DHCPS_MAX_LEASE;
else
local_ip ++;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
dhcps_lease.start_ip.addr = softap_ip | local_ip;
dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
}
// dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
// dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
// os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
}
///////////////////////////////////////////////////////////////////////////////////
void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
{
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
if(apnetif->dhcps_pcb != NULL) {
udp_remove(apnetif->dhcps_pcb);
}
pcb_dhcps = udp_new();
if (pcb_dhcps == NULL || info ==NULL) {
os_printf("dhcps_start(): could not obtain pcb\n");
}
apnetif->dhcps_pcb = pcb_dhcps;
IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
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);
#if DHCPS_DEBUG
os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
#endif
}
void ICACHE_FLASH_ATTR dhcps_stop(void)
{
struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
udp_disconnect(pcb_dhcps);
// dhcps_lease_flag = true;
if(apnetif->dhcps_pcb != NULL) {
udp_remove(apnetif->dhcps_pcb);
apnetif->dhcps_pcb = NULL;
}
//udp_remove(pcb_dhcps);
list_node *pnode = NULL;
list_node *pback_node = NULL;
pnode = plist;
while (pnode != NULL) {
pback_node = pnode;
pnode = pback_node->pnext;
node_remove_from_list(&plist, pback_node);
os_free(pback_node->pnode);
pback_node->pnode = NULL;
os_free(pback_node);
pback_node = NULL;
}
}
/******************************************************************************
* FunctionName : wifi_softap_set_dhcps_lease
* Description : set the lease information of DHCP server
* Parameters : please -- Additional argument to set the lease information,
* Little-Endian.
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
{
struct ip_info info;
uint32 softap_ip = 0;
uint32 start_ip = 0;
uint32 end_ip = 0;
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
return false;
if(please->enable) {
os_bzero(&info, sizeof(struct ip_info));
wifi_get_ip_info(SOFTAP_IF, &info);
softap_ip = htonl(info.ip.addr);
start_ip = htonl(please->start_ip.addr);
end_ip = htonl(please->end_ip.addr);
/*config ip information can't contain local ip*/
if ((start_ip <= softap_ip) && (softap_ip <= end_ip))
return false;
/*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8;
if ((start_ip >> 8 != softap_ip)
|| (end_ip >> 8 != softap_ip)) {
return false;
}
if (end_ip - start_ip > DHCPS_MAX_LEASE)
return false;
os_bzero(&dhcps_lease, sizeof(dhcps_lease));
// dhcps_lease.start_ip.addr = start_ip;
// dhcps_lease.end_ip.addr = end_ip;
dhcps_lease.start_ip.addr = please->start_ip.addr;
dhcps_lease.end_ip.addr = please->end_ip.addr;
}
dhcps_lease.enable = please->enable;
// dhcps_lease_flag = false;
return true;
}
/******************************************************************************
* FunctionName : wifi_softap_get_dhcps_lease
* Description : get the lease information of DHCP server
* Parameters : please -- Additional argument to get the lease information,
* Little-Endian.
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (NULL == please)
return false;
// if (dhcps_lease_flag){
if (dhcps_lease.enable == FALSE){
if (wifi_softap_dhcps_status() == DHCP_STOPPED)
return false;
} else {
// os_bzero(please, sizeof(dhcps_lease));
// if (wifi_softap_dhcps_status() == DHCP_STOPPED){
// please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
// please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
// }
}
// if (wifi_softap_dhcps_status() == DHCP_STARTED){
// os_bzero(please, sizeof(dhcps_lease));
// please->start_ip.addr = dhcps_lease.start_ip.addr;
// please->end_ip.addr = dhcps_lease.end_ip.addr;
// }
please->start_ip.addr = dhcps_lease.start_ip.addr;
please->end_ip.addr = dhcps_lease.end_ip.addr;
return true;
}
static void ICACHE_FLASH_ATTR kill_oldest_dhcps_pool(void)
{
list_node *pre = NULL, *p = NULL;
list_node *minpre = NULL, *minp = NULL;
struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
pre = plist;
p = pre->pnext;
minpre = pre;
minp = p;
while (p != NULL){
pdhcps_pool = p->pnode;
pmin_pool = minp->pnode;
if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
minp = p;
minpre = pre;
}
pre = p;
p = p->pnext;
}
minpre->pnext = minp->pnext;
os_free(minp->pnode);
minp->pnode = NULL;
os_free(minp);
minp = NULL;
}
void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
{
uint8 num_dhcps_pool = 0;
list_node *pback_node = NULL;
list_node *pnode = NULL;
struct dhcps_pool *pdhcps_pool = NULL;
pnode = plist;
while (pnode != NULL) {
pdhcps_pool = pnode->pnode;
pdhcps_pool->lease_timer --;
if (pdhcps_pool->lease_timer == 0){
pback_node = pnode;
pnode = pback_node->pnext;
node_remove_from_list(&plist,pback_node);
os_free(pback_node->pnode);
pback_node->pnode = NULL;
os_free(pback_node);
pback_node = NULL;
} else {
pnode = pnode ->pnext;
num_dhcps_pool ++;
}
}
if (num_dhcps_pool >= MAX_STATION_NUM)
kill_oldest_dhcps_pool();
}
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
{
bool offer_flag = true;
uint8 option = 0;
if (optarg == NULL && wifi_softap_dhcps_status() == false)
return false;
if (level <= OFFER_START || level >= OFFER_END)
return false;
switch (level){
case OFFER_ROUTER:
offer = (*(uint8 *)optarg) & 0x01;
offer_flag = true;
break;
default :
offer_flag = false;
break;
}
return offer_flag;
}
bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease_time(uint32 minute)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
return false;
}
if(minute == 0) {
return false;
}
dhcps_lease_time = minute;
return true;
}
bool ICACHE_FLASH_ATTR wifi_softap_reset_dhcps_lease_time(void)
{
uint8 opmode = wifi_get_opmode();
if (opmode == STATION_MODE || opmode == NULL_MODE) {
return false;
}
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
return false;
}
dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
return true;
}
uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
{
return dhcps_lease_time;
}
/******************************************************************************
* FunctionName : espconn_init
* Description : dummy the espconn_init
* Parameters : none
* Returns : none
*******************************************************************************/
void espconn_init()
{
// dummy function, do nothing.
}
......@@ -23,14 +23,19 @@
#include "lwip/app/espconn_tcp.h"
#include "lwip/app/espconn_udp.h"
#include "lwip/app/espconn.h"
#include "user_interface.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
espconn_msg *plink_active = NULL;
espconn_msg *pserver_list = NULL;
remot_info premot[5];
uint32 link_timer = 0;
remot_info premot[linkMax];
struct espconn_packet pktinfo[2];
static uint8 espconn_tcp_get_buf_count(espconn_buf *pesp_buf);
/******************************************************************************
* FunctionName : espconn_copy_partial
* Description : reconnect with host
......@@ -122,38 +127,127 @@ void ICACHE_FLASH_ATTR espconn_list_delete(espconn_msg **phead, espconn_msg* pde
}*/
}
/******************************************************************************
* FunctionName : espconn_pbuf_create
* Description : insert the node to the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_create(espconn_buf **phead, espconn_buf* pinsert)
{
espconn_buf *plist = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
while (plist->pnext != NULL) {
plist = plist->pnext;
}
plist->pnext = pinsert;
}
pinsert->pnext = NULL;
}
/******************************************************************************
* FunctionName : espconn_pbuf_delete
* Description : remove the node from the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_delete(espconn_buf **phead, espconn_buf* pdelete)
{
espconn_buf *plist = NULL;
plist = *phead;
if (plist == NULL){
*phead = NULL;
} else {
if (plist == pdelete){
*phead = plist->pnext;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
}
plist = plist->pnext;
}
}
}
}
/******************************************************************************
* FunctionName : espconn_find_connection
* Description : Initialize the server: set up a listening PCB and bind it to
* the defined port
* Parameters : espconn -- the espconn used to build server
* Returns : none
* Returns : true or false
*******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode)
{
espconn_msg *plist = NULL;
struct ip_addr ip_remot;
struct ip_addr ip_list;
plist = plink_active;
while(plist != NULL){
if (pespconn == plist->pespconn){
if (pespconn == NULL)
return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (pespconn == plist->pespconn) {
*pnode = plist;
return true;
} else {
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0], pespconn->proto.tcp->remote_ip[1],
pespconn->proto.tcp->remote_ip[2], pespconn->proto.tcp->remote_ip[3]);
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0], plist->pcommon.remote_ip[1],
plist->pcommon.remote_ip[2], plist->pcommon.remote_ip[3]);
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)){
*pnode = plist;
return true;
}
}
/*find the active server node*/
for (plist = pserver_list; plist != NULL; plist = plist->pnext){
if (pespconn == plist->pespconn) {
if (pespconn->proto.tcp == NULL)
return false;
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0],
pespconn->proto.tcp->remote_ip[1],
pespconn->proto.tcp->remote_ip[2],
pespconn->proto.tcp->remote_ip[3]);
if ((ip_remot.addr == IPADDR_ANY) || (pespconn->proto.tcp->remote_port == 0))
return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0],
plist->pcommon.remote_ip[1], plist->pcommon.remote_ip[2],
plist->pcommon.remote_ip[3]);
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)) {
*pnode = plist;
return true;
}
}
return false;
}
plist = plist ->pnext;
}
return false;
return false;
}
/******************************************************************************
* FunctionName : espconn_get_acticve_num
* Description : get the count of simulatenously active connections
* Parameters : type -- the type
* Returns : the count of simulatenously active connections
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR
espconn_get_acticve_num(uint8 type)
{
espconn_msg *plist = NULL;
uint8 num_tcp_active = 0;
for (plist = plink_active; plist != NULL; plist = plist->pnext) {
if (plist->pespconn != NULL && plist->pespconn->type == type) {
num_tcp_active++;
}
}
return num_tcp_active;
}
/******************************************************************************
......@@ -170,12 +264,18 @@ espconn_connect(struct espconn *espconn)
uint8 connect_status = 0;
sint8 value = ESPCONN_OK;
espconn_msg *plist = NULL;
remot_info *pinfo = NULL;
if (espconn == NULL) {
return ESPCONN_ARG;
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Check the active node count whether is the limit or not*/
if (espconn_get_acticve_num(ESPCONN_TCP) >= espconn_tcp_get_max_con())
return ESPCONN_ISCONN;
/*Check the IP address whether is zero or not in different mode*/
if (wifi_get_opmode() == ESPCONN_STA){
wifi_get_ip_info(STA_NETIF,&ipinfo);
if (ipinfo.ip.addr == 0){
......@@ -202,14 +302,17 @@ espconn_connect(struct espconn *espconn)
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;
}
}
}
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN;
}
......@@ -239,8 +342,9 @@ espconn_create(struct espconn *espconn)
return ESPCONN_ARG;
}
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_UDP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
if (espconn->proto.udp->local_port == plist->pespconn->proto.udp->local_port){
return ESPCONN_ISCONN;
}
......@@ -265,32 +369,154 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
if (espconn == NULL) {
err_t error = ESPCONN_OK;
if (espconn == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG;
}
espconn ->state = ESPCONN_WRITE;
value = espconn_find_connection(espconn, &pnode);
switch (espconn ->type) {
case ESPCONN_TCP:
// if (value && (pnode->pcommon.write_len == pnode->pcommon.write_total)){
if (value && (pnode->pcommon.cntr == 0)){
espconn_tcp_sent(pnode, psent, length);
}else
return ESPCONN_ARG;
break;
case ESPCONN_UDP: {
if (value)
espconn_udp_sent(pnode, psent, length);
else
return ESPCONN_ARG;
break;
}
default :
break;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
espconn ->state = ESPCONN_WRITE;
switch (espconn ->type) {
case ESPCONN_TCP:
/* calling sent function frequently,make sure last packet has been backup or sent fully*/
if (pnode->pcommon.write_flag){
espconn_buf *pbuf = NULL;
/*If total number of espconn_buf on the unsent lists exceeds the set maximum, return an error */
if (espconn_copy_enabled(pnode)){
if (espconn_tcp_get_buf_count(pnode->pcommon.pbuf) >= pnode ->pcommon.pbuf_num)
return ESPCONN_MAXNUM;
} else {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (pcb->snd_queuelen >= TCP_SND_QUEUELEN)
return ESPCONN_MAXNUM;
}
pbuf = (espconn_buf*) os_zalloc(sizeof(espconn_buf));
if (pbuf == NULL)
return ESPCONN_MEM;
else {
/*Backup the application packet information for send more data*/
pbuf->payload = psent;
pbuf->punsent = pbuf->payload;
pbuf->unsent = length;
pbuf->len = length;
/*insert the espconn_pbuf to the list*/
espconn_pbuf_create(&pnode->pcommon.pbuf, pbuf);
if (pnode->pcommon.ptail == NULL)
pnode->pcommon.ptail = pbuf;
}
/*when set the data copy option. change the flag for next packet*/
if (espconn_copy_disabled(pnode))
pnode->pcommon.write_flag = false;
error = espconn_tcp_write(pnode);
// if (error != ESPCONN_OK){
// /*send the application packet fail,
// * ensure that each allocated is deleted*/
// espconn_pbuf_delete(&pnode->pcommon.pbuf, pbuf);
// os_free(pbuf);
// pbuf = NULL;
// }
return error;
} else
return ESPCONN_ARG;
break;
case ESPCONN_UDP:
return espconn_udp_sent(pnode, psent, length);
break;
default :
break;
}
}
return ESPCONN_OK;
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_sendto
* Description : send data for UDP
* Parameters : espconn -- espconn to set for UDP
* psent -- data to send
* length -- length of data to send
* Returns : error
*******************************************************************************/
sint16 ICACHE_FLASH_ATTR
espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length)
{
espconn_msg *pnode = NULL;
bool value = false;
err_t error = ESPCONN_OK;
if (espconn == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG;
}
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn->type == ESPCONN_UDP)
return espconn_udp_sendto(pnode, psent, length);
else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_send
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_sent")));
/******************************************************************************
* FunctionName : espconn_tcp_get_wnd
* Description : get the window size of simulatenously active TCP connections
* Parameters : none
* Returns : the number of TCP_MSS active TCP connections
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_wnd(void)
{
uint8 tcp_num = 0;
tcp_num = (TCP_WND / TCP_MSS);
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_con
* Description : set the window size simulatenously active TCP connections
* Parameters : num -- the number of TCP_MSS
* Returns : ESPCONN_ARG -- Illegal argument
* ESPCONN_OK -- No error
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_wnd(uint8 num)
{
if (num == 0 || num > linkMax)
return ESPCONN_ARG;
TCP_WND = (num * TCP_MSS);
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_mss
* Description : get the mss size of simulatenously active TCP connections
* Parameters : none
* Returns : the size of TCP_MSS active TCP connections
*******************************************************************************/
uint16 ICACHE_FLASH_ATTR espconn_tcp_get_mss(void)
{
uint16 tcp_num = 0;
tcp_num = TCP_MSS;
return tcp_num;
}
/******************************************************************************
......@@ -316,13 +542,73 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void)
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num)
{
if (num == 0)
if (num == 0 || num > linkMax)
return ESPCONN_ARG;
MEMP_NUM_TCP_PCB = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_retran
* Description : get the Maximum number of retransmissions of data active TCP connections
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_retran(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_MAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_retran
* Description : set the Maximum number of retransmissions of data active TCP connections
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_retran(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_MAXRTX = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_syn
* Description : get the Maximum number of retransmissions of SYN segments
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_syn(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_SYNMAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_syn
* Description : set the Maximum number of retransmissions of SYN segments
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_syn(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_SYNMAXRTX = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_con_allow
* Description : get the count of simulatenously active connections on the server
......@@ -368,6 +654,51 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, u
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_buf_count
* Description : set the total number of espconn_buf on the unsent lists for one
* activate connection
* Parameters : espconn -- espconn to set the count
* num -- the total number of espconn_buf
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num)
{
espconn_msg *plist = NULL;
if (espconn == NULL || (num > TCP_SND_QUEUELEN))
return ESPCONN_ARG;
/*find the node from the active connection list*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn && plist->pespconn == espconn && espconn->type == ESPCONN_TCP){
plist->pcommon.pbuf_num = num;
return ESPCONN_OK;
}
}
if (plist == NULL)
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_buf_count
* Description : get the count of the current node which has espconn_buf
* Parameters : pesp_buf -- the list head of espconn_buf type
* Returns : the count of the current node which has espconn_buf
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR espconn_tcp_get_buf_count(espconn_buf *pesp_buf)
{
espconn_buf *pbuf_list = pesp_buf;
uint8 pbuf_num = 0;
/*polling the list get the count of the current node*/
while (pbuf_list != NULL){
pbuf_list = pbuf_list->pnext;
pbuf_num ++;
}
return pbuf_num;
}
/******************************************************************************
* FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data
......@@ -388,6 +719,26 @@ espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb)
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data
* has been successfully delivered to the remote host.
* Parameters : espconn -- espconn to set the sent callback
* sent_cb -- sent callback function to call for this espconn
* when data is successfully sent
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn)
{
if (espconn == NULL || espconn ->proto.tcp == NULL || espconn->type == ESPCONN_UDP) {
return ESPCONN_ARG;
}
espconn ->proto.tcp->write_finish_fn = write_finish_fn;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_regist_connectcb
* Description : used to specify the function that should be called when
......@@ -484,27 +835,11 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui
switch (pespconn->type){
case ESPCONN_TCP:
while(plist != NULL){
if ((plist->pespconn->type == ESPCONN_TCP) && (plist->preverse == pespconn)){
switch (typeflags){
case ESPCONN_SSL:
if (plist->pssl != NULL){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
case ESPCONN_NORM:
if (plist->pssl == NULL){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
default:
break;
}
if (plist->preverse == pespconn){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
plist = plist->pnext;
}
......@@ -512,7 +847,7 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui
break;
case ESPCONN_UDP:
while(plist != NULL){
if (plist->pespconn->type == ESPCONN_UDP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
......@@ -545,8 +880,9 @@ espconn_accept(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){
if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN;
}
......@@ -567,11 +903,13 @@ espconn_accept(struct espconn *espconn)
sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag)
{
espconn_msg *pnode = NULL;
espconn_msg *ptime_msg = NULL;
bool value = false;
if ((espconn == NULL) || (type_flag > 0x01))
return ESPCONN_ARG;
if (type_flag == 0x01){
/*set the timeout time for one active connection of the server*/
value = espconn_find_connection(espconn, &pnode);
if (value){
pnode->pcommon.timeout = interval;
......@@ -579,10 +917,17 @@ sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 inte
} else
return ESPCONN_ARG;
} else {
link_timer = interval;
os_printf("espconn_regist_time %d\n", link_timer);
return ESPCONN_OK;
/*set the timeout time for all active connection of the server*/
ptime_msg = pserver_list;
while (ptime_msg != NULL){
if (ptime_msg->pespconn == espconn){
ptime_msg->pcommon.timeout = interval;
return ESPCONN_OK;
}
ptime_msg = ptime_msg->pnext;
}
}
return ESPCONN_ARG;
}
/******************************************************************************
......@@ -602,41 +947,233 @@ espconn_disconnect(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
/*protect for redisconnection*/
if (espconn->state == ESPCONN_CLOSE)
return ESPCONN_INPROGRESS;
espconn_tcp_disconnect(pnode);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_get_packet_info
* Description : get the packet info with host
* Parameters : espconn -- the espconn used to disconnect the connection
* infoarg -- the packet info
* Returns : the errur code
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg)
{
espconn_msg *pnode = NULL;
err_t err;
bool value = false;
if (espconn == NULL || infoarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (pcb == NULL)
return ESPCONN_ARG;
pnode->pcommon.packet_info.packseq_nxt = pcb->rcv_nxt;
pnode->pcommon.packet_info.packseqno = pcb->snd_nxt;
pnode->pcommon.packet_info.snd_buf_size = pcb->snd_buf;
pnode->pcommon.packet_info.total_queuelen = TCP_SND_QUEUELEN;
pnode->pcommon.packet_info.snd_queuelen = pnode->pcommon.packet_info.total_queuelen - pcb->snd_queuelen;
os_memcpy(infoarg,(void*)&pnode->pcommon.packet_info, sizeof(struct espconn_packet));
return ESPCONN_OK;
} else {
switch (espconn->state){
case ESPCONN_CLOSE:
os_memcpy(infoarg,(void*)&pktinfo[0], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
case ESPCONN_NONE:
os_memcpy(infoarg,(void*)&pktinfo[1], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
default:
err = ESPCONN_ARG;
break;
}
return err;
}
}
/******************************************************************************
* FunctionName : espconn_set_opt
* Description : access port value for client so that we don't end up bouncing
* Description : set the option for connections so that we don't end up bouncing
* all connections at the same time .
* Parameters : none
* Returns : access port value
* Parameters : espconn -- the espconn used to set the connection
* opt -- the option for set
* Returns : the result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_set_opt(struct espconn *espconn, uint8 opt)
{
espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false;
if (espconn == NULL || opt > ESPCONN_END) {
if (espconn == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
pnode->pcommon.espconn_opt = opt;
pnode->pcommon.espconn_opt |= opt;
tpcb = pnode->pcommon.pcb;
if (espconn_delay_disabled(pnode))
tcp_nagle_disable(tpcb);
if (espconn_keepalive_disabled(pnode))
espconn_keepalive_enable(tpcb);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_clear_opt
* Description : clear the option for connections so that we don't end up bouncing
* all connections at the same time .
* Parameters : espconn -- the espconn used to set the connection
* opt -- the option for clear
* Returns : the result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_clear_opt(struct espconn *espconn, uint8 opt)
{
espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false;
if (espconn == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
pnode->pcommon.espconn_opt &= ~opt;
tpcb = pnode->pcommon.pcb;
if (espconn_keepalive_enabled(pnode))
espconn_keepalive_disable(tpcb);
if (espconn_delay_enabled(pnode))
tcp_nagle_enable(tpcb);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_set_keepalive
* Description : access level value for connection so that we set the value for
* keep alive
* Parameters : espconn -- the espconn used to set the connection
* level -- the connection's level
* value -- the value of time(s)
* Returns : access port value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level){
case ESPCONN_KEEPIDLE:
pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
pcb->keep_intvl = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
pcb->keep_cnt = (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_get_keepalive
* Description : access level value for connection so that we get the value for
* keep alive
* Parameters : espconn -- the espconn used to get the connection
* level -- the connection's level
* Returns : access keep alive value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level) {
case ESPCONN_KEEPIDLE:
*(int*)optarg = (int)(pcb->keep_idle/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
*(int*)optarg = (int)(pcb->keep_intvl/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
*(int*)optarg = (int)(pcb->keep_cnt);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_delete
* Description : disconnect with host
......@@ -654,6 +1191,7 @@ espconn_delete(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_UDP)
return espconn_tcp_delete(espconn);
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value){
......@@ -670,7 +1208,8 @@ espconn_delete(struct espconn *espconn)
* Parameters : none
* Returns : access port value
*******************************************************************************/
uint32 espconn_port(void)
uint32 ICACHE_FLASH_ATTR
espconn_port(void)
{
uint32 port = 0;
static uint32 randnum = 0;
......@@ -718,32 +1257,17 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t
return dns_gethostbyname(hostname, addr, found, pespconn);
}
sint8 espconn_recv_hold(struct espconn *pespconn) {
espconn_msg *pnode = NULL;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
pespconn->state = ESPCONN_WRITE;
if (!espconn_find_connection(pespconn, &pnode)) {
return ESPCONN_ARG;
}
espconn_tcp_hold(pnode);
return ESPCONN_OK;
/******************************************************************************
* FunctionName : espconn_dns_setserver
* Description : Initialize one of the DNS servers.
* Parameters : numdns -- the index of the DNS server to set must
* be < DNS_MAX_SERVERS = 2
* dnsserver -- IP address of the DNS server to set
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
{
dns_setserver(numdns,dnsserver);
}
sint8 espconn_recv_unhold(struct espconn *pespconn) {
espconn_msg *pnode = NULL;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
pespconn->state = ESPCONN_WRITE;
if (!espconn_find_connection(pespconn, &pnode)) {
return ESPCONN_ARG;
}
espconn_tcp_unhold(pnode);
return ESPCONN_OK;
}
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