mirror of
https://github.com/ADElectronics/RTL00_WEB_VS.git
synced 2024-11-22 14:04:22 +00:00
1013 lines
39 KiB
C
1013 lines
39 KiB
C
/******************************************************************************
|
||
* FileName: tcp_srv_conn.c
|
||
* TCP сервачек для ESP8266
|
||
* pvvx ver1.0 20/12/2014
|
||
* Перекинут на RTL871X pvvx 2017
|
||
******************************************************************************/
|
||
#include "user_config.h"
|
||
#include "autoconf.h"
|
||
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#include "diag.h"
|
||
#include "lwip/tcp.h"
|
||
#include "lwip/tcp_impl.h"
|
||
#include "lwip/memp.h"
|
||
#include "lwip/ip_addr.h"
|
||
#include "flash_eep.h"
|
||
#include "tcpsrv/tcp_srv_conn.h"
|
||
#include "rtl8195a/rtl_libc.h"
|
||
#include "esp_comp.h"
|
||
|
||
#ifdef CONFIG_DEBUG_LOG
|
||
#undef DEBUGSOO
|
||
#define DEBUGSOO 2 // уровень вывода отладочной инфы по умолчанию = 2, =1 только error
|
||
#else
|
||
#undef DEBUGSOO
|
||
#define DEBUGSOO 0
|
||
#endif
|
||
// Lwip funcs - http://www.ecoscentric.com/ecospro/doc/html/ref/lwip.html
|
||
|
||
#define TCP_SRV_BSSDATA_ATTR
|
||
#define TCP_SRV_RODATA_ATTR
|
||
#define TCP_SRV_CODE_ATTR
|
||
|
||
#define ts_printf(...) rtl_printf(__VA_ARGS__)
|
||
#define system_get_free_heap_size xPortGetFreeHeapSize
|
||
|
||
extern void *pvPortZalloc(size_t xWantedSize);
|
||
extern void vPortFree(void *pv);
|
||
extern void *pvPortMalloc(size_t xWantedSize);
|
||
#undef os_free
|
||
#define os_free(p) vPortFree(p)
|
||
#undef os_malloc
|
||
#define os_malloc(p) pvPortMalloc(p)
|
||
#undef os_zalloc
|
||
#define os_zalloc(p) pvPortZalloc(p)
|
||
#undef os_realloc
|
||
#define os_realloc(p,s) pvPortReAlloc(p,s)
|
||
/*
|
||
extern __rtl_memsetw_v1_00(void *, uint32, size_t);
|
||
|
||
void *pvPortZalloc( size_t xWantedSize )
|
||
{
|
||
void *pvReturn = pvPortMalloc(xWantedSize);
|
||
if(pvReturn != NULL) __rtl_memsetw_v1_00(pvReturn, 0, (xWantedSize + 3)>>2);
|
||
return pvReturn;
|
||
}
|
||
*/
|
||
|
||
TCP_SERV_CFG *phcfg TCP_SRV_BSSDATA_ATTR; // = NULL; // начальный указатель в памяти на структуры открытых сервачков
|
||
|
||
#if DEBUGSOO > 0
|
||
const uint8 txt_tcpsrv_NULL_pointer[] TCP_SRV_RODATA_ATTR = "tcpsrv: NULL pointer!\n";
|
||
const uint8 txt_tcpsrv_already_initialized[] TCP_SRV_RODATA_ATTR = "tcpsrv: already initialized!\n";
|
||
const uint8 txt_tcpsrv_out_of_mem[] TCP_SRV_RODATA_ATTR = "tcpsrv: out of mem!\n";
|
||
#endif
|
||
|
||
//#define mMIN(a, b) ((a<b)?a:b)
|
||
// пред.описание...
|
||
static void tcpsrv_list_delete(TCP_SERV_CONN * ts_conn) TCP_SRV_CODE_ATTR;
|
||
static void tcpsrv_disconnect_successful(TCP_SERV_CONN * ts_conn) TCP_SRV_CODE_ATTR;
|
||
static void tcpsrv_server_close(TCP_SERV_CONN * ts_conn) TCP_SRV_CODE_ATTR;
|
||
static err_t tcpsrv_poll(void *arg, struct tcp_pcb *pcb) TCP_SRV_CODE_ATTR;
|
||
static void tcpsrv_error(void *arg, err_t err) TCP_SRV_CODE_ATTR;
|
||
//err_t tcpsrv_connected(void *arg, struct tcp_pcb *tpcb, err_t err) TCP_SRV_CODE_ATTR;
|
||
//err_t tcpsrv_client_connect(TCP_SERV_CONN * ts_conn) TCP_SRV_CODE_ATTR;
|
||
//void tcpsrv_client_reconnect(TCP_SERV_CONN * ts_conn) TCP_SRV_CODE_ATTR;
|
||
|
||
#ifndef LWIP_DEBUG
|
||
#include "lwip/init.h"
|
||
#if (LWIP_VERSION != 0x010401ff)
|
||
#error "Only LwIP version 1.4.1 !"
|
||
#endif
|
||
static const char *err_strerr[] = {
|
||
"Ok", /* ERR_OK 0 */
|
||
"Out of memory error", /* ERR_MEM -1 */
|
||
"Buffer error", /* ERR_BUF -2 */
|
||
"Timeout", /* ERR_TIMEOUT -3 */
|
||
"Routing problem", /* ERR_RTE -4 */
|
||
"Operation in progress", /* ERR_INPROGRESS -5 */
|
||
"Illegal value", /* ERR_VAL -6 */
|
||
"Operation would block", /* ERR_WOULDBLOCK -7 */
|
||
"Address in use", /* ERR_USE -8 */
|
||
"Already connected", /* ERR_ISCONN -9 */
|
||
"Connection aborted", /* ERR_ABRT -10 */
|
||
"Connection reset", /* ERR_RST -11 */
|
||
"Connection closed", /* ERR_CLSD -12 */
|
||
"Not connected", /* ERR_CONN -13 */
|
||
"Illegal argument", /* ERR_ARG -14 */
|
||
"Low-level netif error", /* ERR_IF -15 */
|
||
};
|
||
#endif
|
||
|
||
static const char srvContenErrX[] = "?";
|
||
/******************************************************************************
|
||
* FunctionName : tspsrv_error_msg
|
||
* Description : строка ошибки по номеру
|
||
* Parameters : LwIP err
|
||
* Returns : указатель на строку ошибки
|
||
*******************************************************************************/
|
||
const char * tspsrv_error_msg(err_t err)
|
||
{
|
||
if((err > -16) && (err < 1)) {
|
||
return lwip_strerr(err);
|
||
}
|
||
else return srvContenErrX;
|
||
}
|
||
|
||
extern const char * const tcp_state_str[];
|
||
/******************************************************************************
|
||
* FunctionName : tspsrv_tcp_state_msg
|
||
* Description : строка tcp_state по номеру
|
||
* Parameters : LwIP tcp_state
|
||
* Returns : указатель на строку
|
||
*******************************************************************************/
|
||
const char * tspsrv_tcp_state_msg(enum tcp_state state)
|
||
{
|
||
if(state > TIME_WAIT && state < CLOSED) return srvContenErrX;
|
||
return tcp_state_str[state];
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tspsrv_tcp_state_msg
|
||
* Description : строка tcp_state по номеру
|
||
* Parameters : LwIP tcp_state
|
||
* Returns : указатель на строку
|
||
*******************************************************************************/
|
||
static const char *msg_srvconn_state[] = {
|
||
"NONE",
|
||
"CLOSEWAIT",
|
||
"LISTEN",
|
||
"CONNECT",
|
||
"CLOSED"
|
||
};
|
||
|
||
const char * tspsrv_srvconn_state_msg(enum srvconn_state state)
|
||
{
|
||
if(state > SRVCONN_CLOSED && state < SRVCONN_NONE) return (const char *) srvContenErrX;
|
||
return (const char *) msg_srvconn_state[state];
|
||
}
|
||
//#endif
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_print_remote_info
|
||
* Description : выводит remote_ip:remote_port [conn_count] ts_printf("srv x.x.x.x:x [n] ")
|
||
* Parameters : TCP_SERV_CONN * ts_conn
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
void TCP_SRV_CODE_ATTR tcpsrv_print_remote_info(TCP_SERV_CONN *ts_conn) {
|
||
//#if DEBUGSOO > 0
|
||
uint16 port;
|
||
if(ts_conn->pcb != NULL) port = ts_conn->pcb->local_port;
|
||
else port = ts_conn->pcfg->port;
|
||
ts_printf("srv[%u] %d.%d.%d.%d:%d [%d] ", port,
|
||
ts_conn->remote_ip.b[0], ts_conn->remote_ip.b[1],
|
||
ts_conn->remote_ip.b[2], ts_conn->remote_ip.b[3],
|
||
ts_conn->remote_port, ts_conn->pcfg->conn_count);
|
||
//#endif
|
||
}
|
||
/******************************************************************************
|
||
* Default call back functions
|
||
******************************************************************************/
|
||
//------------------------------------------------------------------------------
|
||
void TCP_SRV_CODE_ATTR tcpsrv_disconnect_calback_default(TCP_SERV_CONN *ts_conn) {
|
||
ts_conn->pcb = NULL;
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("disconnect\n");
|
||
#endif
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_listen_default(TCP_SERV_CONN *ts_conn) {
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("listen\n");
|
||
#endif
|
||
return ERR_OK;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_connected_default(TCP_SERV_CONN *ts_conn) {
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("connected\n");
|
||
#endif
|
||
return ERR_OK;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_sent_callback_default(TCP_SERV_CONN *ts_conn) {
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("sent_cb\n");
|
||
#endif
|
||
return ERR_OK;
|
||
}
|
||
//------------------------------------------------------------------------------
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_received_data_default(TCP_SERV_CONN *ts_conn) {
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("received, buffer %d bytes\n", ts_conn->sizei);
|
||
#endif
|
||
return ERR_OK;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_check_max_tm_tcp_pcb
|
||
* Description : Ограничение неактивных pcb в списках lwip до MAX_TIME_WAIT_PCB
|
||
* Parameters : none
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
static void TCP_SRV_CODE_ATTR tcpsrv_check_max_tm_tcp_pcb(void)
|
||
{
|
||
struct tcp_pcb *pcb;
|
||
int i = 0;
|
||
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) i++;
|
||
#if DEBUGSOO > 4
|
||
ts_printf("tcpsrv: check %d tm pcb\n", i);
|
||
#endif
|
||
while(i-- > MAX_TIME_WAIT_PCB) {
|
||
struct tcp_pcb *inactive = NULL;
|
||
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||
inactive = pcb;
|
||
}
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv: kill %d tm pcb\n", i);
|
||
#endif
|
||
if(inactive != NULL) {
|
||
tcp_pcb_remove(&tcp_tw_pcbs, inactive);
|
||
memp_free(MEMP_TCP_PCB, inactive);
|
||
}
|
||
}
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : find_tcp_pcb
|
||
* Description : поиск pcb в списках lwip
|
||
* Parameters : TCP_SERV_CONN * ts_conn
|
||
* Returns : *pcb or NULL
|
||
*******************************************************************************/
|
||
struct tcp_pcb * TCP_SRV_CODE_ATTR find_tcp_pcb(TCP_SERV_CONN * ts_conn) {
|
||
struct tcp_pcb *pcb = ts_conn->pcb;
|
||
if (pcb) {
|
||
uint16 remote_port = ts_conn->remote_port;
|
||
uint16 local_port = ts_conn->pcfg->port;
|
||
uint32 ip = ts_conn->remote_ip.dw;
|
||
if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
|
||
&& (pcb->remote_ip.addr == ip))
|
||
return pcb;
|
||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||
if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
|
||
&& (pcb->remote_ip.addr == ip))
|
||
return pcb;
|
||
};
|
||
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||
if ((pcb->remote_port == remote_port) && (pcb->local_port == local_port)
|
||
&& (pcb->remote_ip.addr == ip))
|
||
return pcb;
|
||
};
|
||
}
|
||
return NULL;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_disconnect
|
||
* Description : disconnect
|
||
* Parameters : TCP_SERV_CONN * ts_conn
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
void TCP_SRV_CODE_ATTR tcpsrv_disconnect(TCP_SERV_CONN * ts_conn) {
|
||
if (ts_conn == NULL || ts_conn->state == SRVCONN_CLOSEWAIT) return; // уже закрывается
|
||
ts_conn->pcb = find_tcp_pcb(ts_conn); // ещё жива данная pcb ?
|
||
if (ts_conn->pcb != NULL) tcpsrv_server_close(ts_conn);
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : internal fun: tcpsrv_int_sent_data
|
||
* Description : передача данных (не буферизированная! только передача в tcp Lwip-у)
|
||
* вызывать только из call back с текущим pcb!
|
||
* Parameters : TCP_SERV_CONN * ts_conn
|
||
* uint8* psent - буфер с данными
|
||
* uint16 length - кол-во передаваемых байт
|
||
* Returns : tcp error
|
||
******************************************************************************/
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_int_sent_data(TCP_SERV_CONN * ts_conn, uint8 *psent, uint16 length) {
|
||
err_t err = ERR_ARG;
|
||
if(ts_conn == NULL) return err;
|
||
ts_conn->pcb = find_tcp_pcb(ts_conn); // ещё жива данная pcb ?
|
||
struct tcp_pcb *pcb = ts_conn->pcb;
|
||
if(pcb == NULL || ts_conn->state == SRVCONN_CLOSEWAIT) return ERR_CONN;
|
||
ts_conn->flag.busy_bufo = 1; // буфер bufo занят
|
||
if(tcp_sndbuf(pcb) < length) {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("sent_data length (%u) > sndbuf (%u)!\n", length, tcp_sndbuf(pcb));
|
||
#endif
|
||
return err;
|
||
}
|
||
if (length) {
|
||
if(ts_conn->flag.nagle_disabled) tcp_nagle_disable(pcb);
|
||
err = tcp_write(pcb, psent, length, 1);
|
||
if (err == ERR_OK) {
|
||
ts_conn->ptrtx = psent + length;
|
||
ts_conn->cntro -= length;
|
||
ts_conn->flag.wait_sent = 1; // ожидать завершения передачи (sent_cb)
|
||
err = tcp_output(pcb); // передать что влезло
|
||
} else { // ts_conn->state = SRVCONN_CLOSE;
|
||
#if DEBUGSOO > 1
|
||
ts_printf("tcp_write(%p, %p, %u) = %d! pbuf = %u\n", pcb, psent, length, err, tcp_sndbuf(pcb));
|
||
#endif
|
||
ts_conn->flag.wait_sent = 0;
|
||
tcpsrv_server_close(ts_conn);
|
||
};
|
||
} else { // создать вызов tcpsrv_server_sent()
|
||
tcp_nagle_enable(pcb);
|
||
err = tcp_output(pcb); // передать пустое
|
||
}
|
||
ts_conn->flag.busy_bufo = 0; // буфер bufo свободен
|
||
return err;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_server_sent
|
||
* Description : Data has been sent and acknowledged by the remote host.
|
||
* This means that more data can be sent.
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* pcb -- The connection pcb for which data has been acknowledged
|
||
* len -- The amount of bytes acknowledged
|
||
* Returns : ERR_OK: try to send some data by calling tcp_output
|
||
* ERR_ABRT: if you have called tcp_abort from within the function!
|
||
******************************************************************************/
|
||
static err_t TCP_SRV_CODE_ATTR tcpsrv_server_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) {
|
||
sint8 ret_err = ERR_OK;
|
||
TCP_SERV_CONN * ts_conn = arg;
|
||
if (ts_conn == NULL || pcb == NULL) return ERR_ARG;
|
||
ts_conn->state = SRVCONN_CONNECT;
|
||
ts_conn->recv_check = 0;
|
||
ts_conn->flag.wait_sent = 0; // блок передан
|
||
if ((ts_conn->flag.tx_null == 0)
|
||
&& (ts_conn->pcfg->func_sent_cb != NULL)) {
|
||
ret_err = ts_conn->pcfg->func_sent_cb(ts_conn);
|
||
}
|
||
return ret_err;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : recv_trim_bufi
|
||
* Description : увеличение размера буфера приема на newadd
|
||
* Parameters : ts_conn, newadd - требуемое дополнение размера буфера
|
||
* Returns : err_t
|
||
******************************************************************************/
|
||
static err_t TCP_SRV_CODE_ATTR recv_trim_bufi(TCP_SERV_CONN * ts_conn, uint32 newadd)
|
||
{
|
||
uint32 len = 0;
|
||
// while(ts_conn->flag.busy_bufi) vTaskDelay(1);
|
||
ts_conn->flag.busy_bufi = 1; // идет обработка bufi
|
||
if(newadd) {
|
||
// требуется дополнение размера буфера
|
||
if(ts_conn->pbufi != NULL) { // уже есть какой-то буфер
|
||
if ((ts_conn->flag.rx_buf) && ts_conn->cntri < ts_conn->sizei) { // буфер не пуст
|
||
len = ts_conn->sizei - ts_conn->cntri; // размер необработанных данных
|
||
if(ts_conn->cntri >= newadd) { // кол-во обработанных байт (пустого места в буфере) больше чем дополнение
|
||
os_memcpy(ts_conn->pbufi, &ts_conn->pbufi[ts_conn->cntri], len ); // скопировать необработанную часть в начало буфера
|
||
ts_conn->sizei = len;
|
||
if(ts_conn->cntri != newadd) { // кол-во обработанных байт (пустого места в буфере) равно требуемому дополнению
|
||
// уменьшение занимаемого буфера в памяти
|
||
len += newadd; //
|
||
ts_conn->pbufi = (uint8 *)os_realloc(ts_conn->pbufi, len + 1); //mem_trim(ts_conn->pbufi, len);
|
||
if(ts_conn->pbufi == NULL) {
|
||
#if DEBUGSOO > 2
|
||
ts_printf("memtrim err %p[%d] ", ts_conn->pbufi, len + 1);
|
||
#endif
|
||
return ERR_MEM;
|
||
}
|
||
#if DEBUGSOO > 2
|
||
ts_printf("memi%p[%d] ", ts_conn->pbufi, len);
|
||
#endif
|
||
}
|
||
ts_conn->pbufi[len] = '\0'; // вместо os_zalloc;
|
||
ts_conn->cntri = 0;
|
||
ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
|
||
return ERR_OK;
|
||
}
|
||
}
|
||
else { // буфер пуст или не тот режим
|
||
// удалить буфер
|
||
os_free(ts_conn->pbufi);
|
||
ts_conn->pbufi = NULL;
|
||
}
|
||
}
|
||
// подготовка нового буфера, если его нет или не лезет дополнение
|
||
uint8 * newbufi = (uint8 *) os_malloc(len + newadd + 1);
|
||
if (newbufi == NULL) {
|
||
#if DEBUGSOO > 2
|
||
ts_printf("memerr %p[%d] ", newbufi, len + newadd);
|
||
#endif
|
||
ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
|
||
return ERR_MEM;
|
||
}
|
||
#if DEBUGSOO > 2
|
||
ts_printf("memi%p[%d] ", newbufi, len + newadd);
|
||
#endif
|
||
newbufi[len + newadd] = '\0'; // вместо os_zalloc
|
||
if(len) {
|
||
os_memcpy(newbufi, &ts_conn->pbufi[ts_conn->cntri], len);
|
||
os_free(ts_conn->pbufi);
|
||
};
|
||
ts_conn->pbufi = newbufi;
|
||
ts_conn->sizei = len;
|
||
}
|
||
else {
|
||
// оптимизация буфера (уменьшение занимаемого размера)
|
||
if((!ts_conn->flag.rx_buf) || ts_conn->cntri >= ts_conn->sizei) { // буфер обработан
|
||
ts_conn->sizei = 0;
|
||
if (ts_conn->pbufi != NULL) {
|
||
os_free(ts_conn->pbufi); // освободить буфер.
|
||
ts_conn->pbufi = NULL;
|
||
};
|
||
}
|
||
else if(ts_conn->cntri) { // есть обработанные данные
|
||
// уменьшение занимаемого размера на обработанные данные
|
||
len = ts_conn->sizei - ts_conn->cntri;
|
||
os_memcpy(ts_conn->pbufi, &ts_conn->pbufi[ts_conn->cntri], len );
|
||
ts_conn->sizei = len;
|
||
ts_conn->pbufi = (uint8 *)os_realloc(ts_conn->pbufi, len + 1); //mem_trim(ts_conn->pbufi, len);
|
||
if(ts_conn->pbufi == NULL) {
|
||
#if DEBUGSOO > 2
|
||
ts_printf("memtrim err %p[%d] ", ts_conn->pbufi, len + 1);
|
||
#endif
|
||
ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
|
||
return ERR_MEM;
|
||
}
|
||
ts_conn->pbufi[len] = '\0'; // вместо os_zalloc;
|
||
}
|
||
}
|
||
ts_conn->cntri = 0;
|
||
ts_conn->flag.busy_bufi = 0; // обработка bufi окончена
|
||
return ERR_OK;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_server_recv
|
||
* Description : Data has been received on this pcb.
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* pcb -- The connection pcb which received data
|
||
* p -- The received data (or NULL when the connection has been closed!)
|
||
* err -- An error code if there has been an error receiving
|
||
* Returns : ERR_ABRT: if you have called tcp_abort from within the function!
|
||
******************************************************************************/
|
||
static err_t TCP_SRV_CODE_ATTR tcpsrv_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
|
||
// Sets the callback function that will be called when new data arrives on the connection associated with pcb.
|
||
// The callback function will be passed a NULL pbuf to indicate that the remote host has closed the connection.
|
||
TCP_SERV_CONN * ts_conn = arg;
|
||
if (ts_conn == NULL || pcb == NULL) return ERR_ARG;
|
||
|
||
// if(syscfg.cfg.b.hi_speed_enable) set_cpu_clk();
|
||
|
||
if (p == NULL || err != ERR_OK) { // the remote host has closed the connection.
|
||
tcpsrv_server_close(ts_conn);
|
||
return err;
|
||
};
|
||
// если нет функции обработки или ожидаем закрытия соединения, то принимаем данные в трубу
|
||
if ((ts_conn->flag.rx_null != 0) || (ts_conn->pcfg->func_recv == NULL)
|
||
|| (ts_conn->state == SRVCONN_CLOSEWAIT)) { // соединение закрыто? нет.
|
||
tcp_recved(pcb, p->tot_len + ts_conn->unrecved_bytes); // сообщает стеку, что съели len и можно посылать ACK и принимать новые данные.
|
||
ts_conn->unrecved_bytes = 0;
|
||
#if DEBUGSOO > 3
|
||
ts_printf("rec_null %d of %d\n", ts_conn->cntri, p->tot_len);
|
||
#endif
|
||
pbuf_free(p); // данные выели
|
||
return ERR_OK;
|
||
};
|
||
ts_conn->state = SRVCONN_CONNECT; // был прием
|
||
ts_conn->recv_check = 0; // счет времени до авто-закрытия с нуля
|
||
if(p->tot_len) {
|
||
err = recv_trim_bufi(ts_conn, p->tot_len); // увеличить буфер
|
||
if(err != ERR_OK) return err;
|
||
// добавление всего что отдал Lwip в буфер
|
||
uint32 len = pbuf_copy_partial(p, &ts_conn->pbufi[ts_conn->sizei], p->tot_len, 0);
|
||
ts_conn->sizei += len;
|
||
pbuf_free(p); // все данные выели
|
||
if(!ts_conn->flag.rx_buf) {
|
||
tcp_recved(pcb, len); // сообщает стеку, что съели len и можно посылать ACK и принимать новые данные.
|
||
}
|
||
else ts_conn->unrecved_bytes += len;
|
||
#if DEBUGSOO > 3
|
||
ts_printf("rec %d of %d :\n", p->tot_len, ts_conn->sizei);
|
||
#endif
|
||
err = ts_conn->pcfg->func_recv(ts_conn);
|
||
err_t err2 = recv_trim_bufi(ts_conn, 0); // оптимизировать размер занимаемый буфером
|
||
if(err2 != ERR_OK) return err2;
|
||
}
|
||
return err;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_unrecved_win
|
||
* Description : Update the TCP window.
|
||
* This can be used to throttle data reception (e.g. when received data is
|
||
* programmed to flash and data is received faster than programmed).
|
||
* Parameters : TCP_SERV_CONN * ts_conn
|
||
* Returns : none
|
||
* После включения throttle, будет принято до 5840 (MAX WIN) + 1460 (MSS) байт?
|
||
******************************************************************************/
|
||
void TCP_SRV_CODE_ATTR tcpsrv_unrecved_win(TCP_SERV_CONN *ts_conn) {
|
||
if (ts_conn->unrecved_bytes) {
|
||
// update the TCP window
|
||
#if DEBUGSOO > 3
|
||
ts_printf("recved_bytes=%d\n", ts_conn->unrecved_bytes);
|
||
#endif
|
||
#if 1
|
||
if(ts_conn->pcb != NULL) tcp_recved(ts_conn->pcb, ts_conn->unrecved_bytes);
|
||
#else
|
||
struct tcp_pcb *pcb = find_tcp_pcb(ts_conn); // уже закрыто?
|
||
if(pcb != NULL) tcp_recved(ts_conn->pcb, ts_conn->unrecved_bytes);
|
||
#endif
|
||
}
|
||
ts_conn->unrecved_bytes = 0;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_disconnect
|
||
* Description : disconnect with host
|
||
* Parameters : ts_conn
|
||
* Returns : none
|
||
******************************************************************************/
|
||
static void TCP_SRV_CODE_ATTR tcpsrv_disconnect_successful(TCP_SERV_CONN * ts_conn) {
|
||
ts_conn->pcb = NULL;
|
||
tcpsrv_list_delete(ts_conn); // remove the node from the server's connection list
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_server_close
|
||
* Description : The connection shall be actively closed.
|
||
* Parameters : ts_conn
|
||
* Returns : none
|
||
******************************************************************************/
|
||
static void TCP_SRV_CODE_ATTR tcpsrv_server_close(TCP_SERV_CONN * ts_conn) {
|
||
|
||
struct tcp_pcb *pcb = ts_conn->pcb;
|
||
if(pcb == NULL) {
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv_server_close, state: %s, pcb = NULL!\n", tspsrv_srvconn_state_msg(ts_conn->state));
|
||
#endif
|
||
return;
|
||
}
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv_server_close[%d], state: %s\n", pcb->local_port, tspsrv_srvconn_state_msg(ts_conn->state));
|
||
#endif
|
||
if(ts_conn->state != SRVCONN_CLOSEWAIT && ts_conn->state != SRVCONN_CLOSED) {
|
||
#if DEBUGSOO > 2
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("start close...\n");
|
||
#endif
|
||
ts_conn->state = SRVCONN_CLOSEWAIT;
|
||
ts_conn->recv_check = 0;
|
||
ts_conn->flag.wait_sent = 0; // блок передан
|
||
ts_conn->flag.rx_null = 1; // отключение вызова func_received_data() и прием в null
|
||
ts_conn->flag.tx_null = 1; // отключение вызова func_sent_callback() и передача в null
|
||
// отключение функций приема, передачи и poll
|
||
tcp_recv(pcb, NULL); // отключение приема
|
||
tcp_sent(pcb, NULL); // отключение передачи
|
||
tcp_poll(pcb, NULL, 0); // отключение poll
|
||
tcp_err(pcb, NULL);
|
||
//
|
||
if(ts_conn->unrecved_bytes) {
|
||
tcp_recved(pcb, TCP_WND);
|
||
ts_conn->unrecved_bytes = 0;
|
||
}
|
||
// освободить буфера
|
||
if (ts_conn->pbufo != NULL) {
|
||
os_free(ts_conn->pbufo);
|
||
ts_conn->pbufo = NULL;
|
||
}
|
||
ts_conn->sizeo = 0;
|
||
ts_conn->cntro = 0;
|
||
if (ts_conn->pbufi != NULL) {
|
||
os_free(ts_conn->pbufi);
|
||
ts_conn->pbufi = NULL;
|
||
}
|
||
ts_conn->sizei = 0;
|
||
ts_conn->cntri = 0;
|
||
}
|
||
if(ts_conn->state == SRVCONN_CLOSEWAIT || ts_conn->state == SRVCONN_CLOSED) {
|
||
if (pcb->state == CLOSED || pcb->state == TIME_WAIT) {
|
||
/*remove the node from the server's active connection list*/
|
||
#if DEBUGSOO > 3
|
||
ts_printf("close[%d]\n", pcb->local_port);
|
||
#endif
|
||
tcpsrv_disconnect_successful(ts_conn);
|
||
} else {
|
||
if (ts_conn->recv_check > 3) { // счет до принудительного закрытия 3 раза по TCP_SRV_CLOSE_WAIT
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("tcp_abandon!\n");
|
||
#endif
|
||
tcp_poll(pcb, NULL, 0);
|
||
//?/ tcp_err(pcb, NULL);
|
||
tcp_abandon(pcb, 0);
|
||
// ts_conn->pcb = NULL;
|
||
// remove the node from the server's active connection list
|
||
tcpsrv_disconnect_successful(ts_conn);
|
||
}
|
||
else if (tcp_close(pcb) != ERR_OK) { // послать закрытие соединения, closing failed
|
||
#if DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("+ncls+[%d]\n", pcb->local_port);
|
||
#endif
|
||
// closing failed, try again later
|
||
tcp_poll(pcb, tcpsrv_poll, 2*(TCP_SRV_CLOSE_WAIT));
|
||
}
|
||
else {
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcp_close[%d] ok.\n", pcb->local_port);
|
||
#endif
|
||
tcpsrv_disconnect_successful(ts_conn);
|
||
}
|
||
}
|
||
}
|
||
#if DEBUGSOO > 2
|
||
else {
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("already close!\n");
|
||
}
|
||
#endif
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_poll (server and client)
|
||
* Description : The poll function is called every 1 second.
|
||
* This could be increased, but we don't want to waste resources for bad connections.
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* pcb -- The connection pcb for which data has been acknowledged
|
||
* Returns : ERR_OK: try to send some data by calling tcp_output
|
||
* ERR_ABRT: if you have called tcp_abort from within the function!
|
||
*******************************************************************************/
|
||
static err_t TCP_SRV_CODE_ATTR tcpsrv_poll(void *arg, struct tcp_pcb *pcb) {
|
||
TCP_SERV_CONN * ts_conn = arg;
|
||
if (ts_conn == NULL) {
|
||
#if DEBUGSOO > 3
|
||
ts_printf("poll, ts_conn = NULL! - abandon\n");
|
||
#endif
|
||
tcp_poll(pcb, NULL, 0);
|
||
tcp_err(pcb, NULL);
|
||
tcp_abandon(pcb, 0);
|
||
return ERR_ABRT;
|
||
}
|
||
#if DEBUGSOO > 3
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("poll: %d %s#%s, %d,%d, pcb:%p\n", ts_conn->recv_check, tspsrv_srvconn_state_msg(ts_conn->state), tspsrv_tcp_state_msg(pcb->state), ts_conn->pcfg->time_wait_rec, ts_conn->pcfg->time_wait_cls), pcb;
|
||
#endif
|
||
if (ts_conn->pcb != NULL && ts_conn->state != SRVCONN_CLOSEWAIT) {
|
||
ts_conn->recv_check++;
|
||
if (pcb->state == ESTABLISHED) {
|
||
if ((ts_conn->state == SRVCONN_LISTEN
|
||
&& (ts_conn->pcfg->time_wait_rec)
|
||
&& ts_conn->recv_check > ts_conn->pcfg->time_wait_rec)
|
||
|| (ts_conn->state == SRVCONN_CONNECT
|
||
&& (ts_conn->pcfg->time_wait_cls)
|
||
&& ts_conn->recv_check > ts_conn->pcfg->time_wait_cls)) {
|
||
tcpsrv_server_close(ts_conn);
|
||
}
|
||
}
|
||
else tcpsrv_server_close(ts_conn);
|
||
}
|
||
else tcpsrv_server_close(ts_conn);
|
||
#ifdef SRV_WDGREFESH_IN_POOL
|
||
WDGRefresh();
|
||
#endif
|
||
return ERR_OK;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_list_delete
|
||
* Description : remove the node from the connection list
|
||
* Parameters : ts_conn
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
static void TCP_SRV_CODE_ATTR tcpsrv_list_delete(TCP_SERV_CONN * ts_conn) {
|
||
// if (ts_conn == NULL) return;
|
||
if(ts_conn->state != SRVCONN_CLOSED) {
|
||
ts_conn->state = SRVCONN_CLOSED; // исключить повторное вхождение из запросов в func_discon_cb()
|
||
if (ts_conn->pcfg->func_discon_cb != NULL)
|
||
ts_conn->pcfg->func_discon_cb(ts_conn);
|
||
if(phcfg == NULL || ts_conn->pcfg == NULL) return; // если в func_discon_cb() было вызвано tcpsrv_close_all() и т.д.
|
||
}
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv_list_delete (%p)\n", ts_conn->pcb);
|
||
#endif
|
||
TCP_SERV_CONN ** p = &ts_conn->pcfg->conn_links;
|
||
TCP_SERV_CONN *tcpsrv_cmp = ts_conn->pcfg->conn_links;
|
||
while (tcpsrv_cmp != NULL) {
|
||
if (tcpsrv_cmp == ts_conn) {
|
||
*p = ts_conn->next;
|
||
ts_conn->next = NULL;
|
||
ts_conn->pcfg->conn_count--;
|
||
if (ts_conn->linkd != NULL) {
|
||
os_free(ts_conn->linkd);
|
||
ts_conn->linkd = NULL;
|
||
}
|
||
if (ts_conn->pbufo != NULL) {
|
||
os_free(ts_conn->pbufo);
|
||
ts_conn->pbufo = NULL;
|
||
}
|
||
if (ts_conn->pbufi != NULL) {
|
||
os_free(ts_conn->pbufi);
|
||
ts_conn->pbufi = NULL;
|
||
}
|
||
os_free(ts_conn);
|
||
return; // break;
|
||
}
|
||
p = &tcpsrv_cmp->next;
|
||
tcpsrv_cmp = tcpsrv_cmp->next;
|
||
};
|
||
}
|
||
//-----------------------------------------------------------------------------
|
||
static void tspsrv_delete_pcb(TCP_SERV_CONN * ts_conn)
|
||
{
|
||
struct tcp_pcb *pcb = find_tcp_pcb(ts_conn);
|
||
if(pcb) {
|
||
tcp_arg(pcb, NULL);
|
||
tcp_recv(pcb, NULL);
|
||
tcp_err(pcb, NULL);
|
||
tcp_poll(pcb, NULL, 0);
|
||
tcp_sent(pcb, NULL);
|
||
tcp_recved(pcb, TCP_WND);
|
||
tcp_close(pcb);
|
||
ts_conn->pcb = NULL;
|
||
}
|
||
tcpsrv_list_delete(ts_conn);
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_error (server and client)
|
||
* Description : The pcb had an error and is already deallocated.
|
||
* The argument might still be valid (if != NULL).
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* err -- Error code to indicate why the pcb has been closed
|
||
* Returns : none
|
||
*******************************************************************************/
|
||
static void TCP_SRV_CODE_ATTR tcpsrv_error(void *arg, err_t err) {
|
||
TCP_SERV_CONN * ts_conn = arg;
|
||
// struct tcp_pcb *pcb = NULL;
|
||
if (ts_conn != NULL) {
|
||
#if DEBUGSOO > 2
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
ts_printf("error %d (%s)\n", err, tspsrv_error_msg(err));
|
||
#elif DEBUGSOO > 1
|
||
tcpsrv_print_remote_info(ts_conn);
|
||
#ifdef LWIP_DEBUG
|
||
ts_printf("error %d (%s)\n", err, tspsrv_error_msg(err));
|
||
#else
|
||
ts_printf("error %d\n", err);
|
||
#endif
|
||
#endif
|
||
if (ts_conn->state != SRVCONN_CLOSEWAIT) {
|
||
if(ts_conn->pcb != NULL) {
|
||
// && ts_conn->state != SRVCONN_CLOSED) {
|
||
// && (ts_conn->state != SRVCONN_CONNECT || ts_conn->state == SRVCONN_LISTEN)) {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("eclose[%d]\n", ts_conn->pcfg->port);
|
||
#endif
|
||
tcpsrv_list_delete(ts_conn); // remove the node from the server's connection list
|
||
};
|
||
};
|
||
}
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_tcp_accept
|
||
* Description : A new incoming connection has been accepted.
|
||
* Parameters : arg -- Additional argument to pass to the callback function
|
||
* pcb -- The connection pcb which is accepted
|
||
* err -- An unused error code, always ERR_OK currently
|
||
* Returns : acception result
|
||
*******************************************************************************/
|
||
static err_t TCP_SRV_CODE_ATTR tcpsrv_server_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
|
||
struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*) arg;
|
||
TCP_SERV_CFG *p = tcpsrv_server_port2pcfg(pcb->local_port);
|
||
TCP_SERV_CONN * ts_conn;
|
||
if (p == NULL) return ERR_ARG;
|
||
if (system_get_free_heap_size() < p->min_heap) {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("srv[%u] new listen - low heap size!\n", p->port);
|
||
#endif
|
||
return ERR_MEM;
|
||
}
|
||
if (p->conn_count >= p->max_conn) {
|
||
if(p->flag.srv_reopen) {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("srv[%u] reconnect!\n", p->port);
|
||
#endif
|
||
if (p->conn_links != NULL) {
|
||
tspsrv_delete_pcb(p->conn_links);
|
||
};
|
||
}
|
||
else {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("srv[%u] new listen - max connection!\n", p->port);
|
||
#endif
|
||
return ERR_CONN;
|
||
}
|
||
}
|
||
ts_conn = (TCP_SERV_CONN *) os_zalloc(sizeof(TCP_SERV_CONN));
|
||
if (ts_conn == NULL) {
|
||
#if DEBUGSOO > 1
|
||
ts_printf("srv[%u] new listen - out of mem!\n", ts_conn->pcfg->port);
|
||
#endif
|
||
return ERR_MEM;
|
||
}
|
||
ts_conn->pcfg = p;
|
||
// перенести флаги по умолчанию на данное соединение
|
||
ts_conn->flag = p->flag;
|
||
tcp_accepted(lpcb); // Decrease the listen backlog counter
|
||
// tcp_setprio(pcb, TCP_PRIO_MIN); // Set priority ?
|
||
// init/copy data ts_conn
|
||
ts_conn->pcb = pcb;
|
||
ts_conn->remote_port = pcb->remote_port;
|
||
ts_conn->remote_ip.dw = pcb->remote_ip.addr;
|
||
// *(uint16 *) &ts_conn->flag = 0; //zalloc
|
||
// ts_conn->recv_check = 0; //zalloc
|
||
// ts_conn->linkd = NULL; //zalloc
|
||
// Insert new ts_conn
|
||
ts_conn->next = ts_conn->pcfg->conn_links;
|
||
ts_conn->pcfg->conn_links = ts_conn;
|
||
ts_conn->pcfg->conn_count++;
|
||
ts_conn->state = SRVCONN_LISTEN;
|
||
// Tell TCP that this is the structure we wish to be passed for our callbacks.
|
||
tcp_arg(pcb, ts_conn);
|
||
// Set up the various callback functions
|
||
tcp_err(pcb, tcpsrv_error);
|
||
tcp_sent(pcb, tcpsrv_server_sent);
|
||
tcp_recv(pcb, tcpsrv_server_recv);
|
||
tcp_poll(pcb, tcpsrv_poll, 2); /* every 1/2 seconds */
|
||
#if MEMP_MEM_MALLOC // tcp_alloc() уже управляет убийством TIME_WAIT если MEMP_MEM_MALLOC == 0
|
||
if(ts_conn->flag.pcb_time_wait_free) tcpsrv_check_max_tm_tcp_pcb();
|
||
// http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
|
||
#endif
|
||
if (p->func_listen != NULL)
|
||
return p->func_listen(ts_conn);
|
||
return ERR_OK;
|
||
}
|
||
/******************************************************************************
|
||
* FunctionName : tcpsrv_server_port2pcfg
|
||
* Description : поиск конфига servera по порту
|
||
* Parameters : номер порта
|
||
* Returns : указатель на TCP_SERV_CFG или NULL
|
||
*******************************************************************************/
|
||
TCP_SERV_CFG * TCP_SRV_CODE_ATTR tcpsrv_server_port2pcfg(uint16 portn) {
|
||
TCP_SERV_CFG * p;
|
||
for (p = phcfg; p != NULL; p = p->next)
|
||
if (p->port == portn) return p;
|
||
return NULL;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_init server.
|
||
*******************************************************************************/
|
||
TCP_SERV_CFG * TCP_SRV_CODE_ATTR tcpsrv_init(uint16 portn) {
|
||
// if (portn == 0) portn = 80;
|
||
if (portn == 0) return NULL;
|
||
TCP_SERV_CFG * p;
|
||
for (p = phcfg; p != NULL; p = p->next) {
|
||
if (p->port == portn) {
|
||
#if DEBUGSOO > 0
|
||
ts_printf(txt_tcpsrv_already_initialized);
|
||
#endif
|
||
return NULL;
|
||
}
|
||
}
|
||
p = (TCP_SERV_CFG *) os_zalloc(sizeof(TCP_SERV_CFG));
|
||
if (p == NULL) {
|
||
#if DEBUGSOO > 0
|
||
ts_printf(txt_tcpsrv_out_of_mem);
|
||
#endif
|
||
return NULL;
|
||
}
|
||
p->port = portn;
|
||
p->conn_count = 0;
|
||
p->min_heap = TCP_SRV_MIN_HEAP_SIZE;
|
||
p->time_wait_rec = TCP_SRV_RECV_WAIT;
|
||
p->time_wait_cls = TCP_SRV_END_WAIT;
|
||
// p->phcfg->conn_links = NULL; // zalloc
|
||
// p->pcb = NULL; // zalloc
|
||
// p->lnk = NULL; // zalloc
|
||
p->max_conn = TCP_SRV_MAX_CONNECTIONS;
|
||
p->func_listen = tcpsrv_listen_default;
|
||
p->func_discon_cb = tcpsrv_disconnect_calback_default;
|
||
p->func_sent_cb = tcpsrv_sent_callback_default;
|
||
p->func_recv = tcpsrv_received_data_default;
|
||
return p;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_start
|
||
*******************************************************************************/
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_start(TCP_SERV_CFG *p) {
|
||
err_t err = ERR_OK;
|
||
if (p == NULL) {
|
||
#if DEBUGSOO > 0
|
||
ts_printf(txt_tcpsrv_NULL_pointer);
|
||
#endif
|
||
return ERR_ARG;
|
||
}
|
||
if (p->pcb != NULL) {
|
||
#if DEBUGSOO > 0
|
||
ts_printf(txt_tcpsrv_already_initialized);
|
||
#endif
|
||
return ERR_USE;
|
||
}
|
||
p->pcb = tcp_new();
|
||
|
||
if (p->pcb != NULL) {
|
||
tcp_setprio(p->pcb, TCP_SRV_PRIO);
|
||
err = tcp_bind(p->pcb, IP_ADDR_ANY, p->port); // Binds pcb to a local IP address and port number.
|
||
if (err == ERR_OK) { // If another connection is bound to the same port, the function will return ERR_USE, otherwise ERR_OK is returned.
|
||
p->pcb = tcp_listen(p->pcb); // Commands pcb to start listening for incoming connections.
|
||
// When an incoming connection is accepted, the function specified with the tcp_accept() function
|
||
// will be called. pcb must have been bound to a local port with the tcp_bind() function.
|
||
// The tcp_listen() function returns a new connection identifier, and the one passed as an
|
||
// argument to the function will be deallocated. The reason for this behavior is that less
|
||
// memory is needed for a connection that is listening, so tcp_listen() will reclaim the memory
|
||
// needed for the original connection and allocate a new smaller memory block for the listening connection.
|
||
// tcp_listen() may return NULL if no memory was available for the listening connection.
|
||
// If so, the memory associated with pcb will not be deallocated.
|
||
if (p->pcb != NULL) {
|
||
tcp_arg(p->pcb, p->pcb);
|
||
// insert new tcpsrv_config
|
||
p->next = phcfg;
|
||
phcfg = p;
|
||
// initialize callback arg and accept callback
|
||
tcp_accept(p->pcb, tcpsrv_server_accept);
|
||
return err;
|
||
}
|
||
}
|
||
tcp_abandon(p->pcb, 0);
|
||
p->pcb = NULL;
|
||
} else
|
||
err = ERR_MEM;
|
||
#if DEBUGSOO > 0
|
||
ts_printf("tcpsrv: not new tcp!\n");
|
||
#endif
|
||
return err;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_close
|
||
*******************************************************************************/
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_close(TCP_SERV_CFG *p) {
|
||
if (p == NULL) {
|
||
#if DEBUGSOO > 0
|
||
ts_printf(txt_tcpsrv_NULL_pointer);
|
||
#endif
|
||
return ERR_ARG;
|
||
};
|
||
TCP_SERV_CFG **pwr = &phcfg;
|
||
TCP_SERV_CFG *pcmp = phcfg;
|
||
while (pcmp != NULL) {
|
||
if (pcmp == p) {
|
||
*pwr = p->next;
|
||
while (p->conn_links != NULL) {
|
||
tspsrv_delete_pcb(p->conn_links);
|
||
};
|
||
if(p->pcb != NULL) tcp_close(p->pcb);
|
||
os_free(p);
|
||
p = NULL;
|
||
return ERR_OK; // break;
|
||
}
|
||
pwr = &pcmp->next;
|
||
pcmp = pcmp->next;
|
||
};
|
||
#if DEBUGSOO > 2
|
||
ts_printf("tcpsrv: srv_cfg not find!\n");
|
||
#endif
|
||
return ERR_CONN;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_close_port
|
||
*******************************************************************************/
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_close_port(uint16 portn)
|
||
{
|
||
if(portn) return tcpsrv_close(tcpsrv_server_port2pcfg(portn));
|
||
else return ERR_ARG;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_close_all_tcp_pcb
|
||
*******************************************************************************/
|
||
int TCP_SRV_CODE_ATTR tcpsrv_close_all_tcp_pcb(void)
|
||
{
|
||
struct tcp_pcb *pcb;
|
||
int ret = 0;
|
||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv: abort %p pcb\n", pcb);
|
||
#endif
|
||
tcp_abort(pcb);
|
||
ret = 1;
|
||
}
|
||
return ret;
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_delete_all_tm_tcp_pcb
|
||
*******************************************************************************/
|
||
void TCP_SRV_CODE_ATTR tcpsrv_delete_all_tm_tcp_pcb(void)
|
||
{
|
||
struct tcp_pcb *pcb;
|
||
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||
#if DEBUGSOO > 3
|
||
ts_printf("tcpsrv: del tm %p pcb\n", pcb);
|
||
#endif
|
||
tcp_pcb_remove(&tcp_tw_pcbs, pcb);
|
||
memp_free(MEMP_TCP_PCB, pcb);
|
||
}
|
||
}
|
||
/******************************************************************************
|
||
tcpsrv_close_all
|
||
*******************************************************************************/
|
||
err_t TCP_SRV_CODE_ATTR tcpsrv_close_all(void)
|
||
{
|
||
err_t err = ERR_OK;
|
||
while(phcfg != NULL && err == ERR_OK) err = tcpsrv_close(phcfg);
|
||
if(tcpsrv_close_all_tcp_pcb()) vTaskDelay(50);
|
||
tcpsrv_delete_all_tm_tcp_pcb();
|
||
return err;
|
||
}
|
||
|