2017-04-22 13:54:00 +00:00
# ifndef __TCP_SERV_CONN_H__
/***********************************
* FileName : tcp_srv_conn . h
* Tcp с е р в а ч е к д л я ESP8266
* PV ` ver1 .0 20 / 12 / 2014
* PV ` ver1 .0 29 / 10 / 2016 д л я RTL87xx
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define __TCP_SERV_CONN_H__
2017-05-09 15:55:08 +00:00
# include "user_config.h"
2017-09-06 11:34:28 +00:00
# include "tcp.h"
2017-04-22 13:54:00 +00:00
# include "lwip/err.h"
enum srvconn_state {
SRVCONN_NONE = 0 ,
SRVCONN_CLOSEWAIT , // ожидает закрытия
SRVCONN_LISTEN , // соединение открыто, ждет rx или tx
SRVCONN_CONNECT , // соединение открыто, было rx или tx
SRVCONN_CLOSED // соединение закрыто
} ;
// приоритет pcb 1..127 1 - min, 127 - max
# ifndef TCP_SRV_PRIO
2017-04-23 09:26:57 +00:00
# define TCP_SRV_PRIO 99 // TCP_PRIO_MIN
2017-04-22 13:54:00 +00:00
# endif
// максимальное кол-во TCP c TIME_WAIT
# ifndef MAX_TIME_WAIT_PCB
# define MAX_TIME_WAIT_PCB 10
# endif
2017-12-12 20:34:32 +00:00
# define _mMIN(a, b) ((a < b)? a : b)
2017-04-22 13:54:00 +00:00
// кол-во одновременно открытых соединений по умолчанию
# ifndef TCP_SRV_MAX_CONNECTIONS
2017-12-12 20:34:32 +00:00
# define TCP_SRV_MAX_CONNECTIONS _mMIN(MEMP_NUM_TCP_PCB, 10)
2017-04-22 13:54:00 +00:00
# endif
// порт сервера по умолчанию
# ifndef TCP_SRV_SERVER_PORT
# define TCP_SRV_SERVER_PORT 80
# endif
2017-05-06 14:50:18 +00:00
# define SRV_WDGREFESH_IN_POOL // использовать WDGRefresh() в tcpsrv_poll()
2017-04-22 13:54:00 +00:00
// время (сек), по умолчанию, ожидания запроса (передачи пакета) от клиента, до авто-закрытия соединения,
// при = 0 заменяется на эти 5 сек.
# ifndef TCP_SRV_RECV_WAIT
# define TCP_SRV_RECV_WAIT 5
# endif
// время (сек), по умолчанию, до авто-закрытия соединения после приема или передачи,
// при = 0 заменяется на эти 5 сек.
# ifndef TCP_SRV_END_WAIT
# define TCP_SRV_END_WAIT 5
# endif
// время (в сек) до повтора закрытия соединения (исполняется до 3-х раз).
# define TCP_SRV_CLOSE_WAIT 5 // 5 сек
// минимальный размер heap по умолчанию, при открытии нового соединения, при = 0 заменяется на это:
2017-05-01 11:19:48 +00:00
# define TCP_SRV_MIN_HEAP_SIZE 32768 // самый минимум от 6Kb
2017-04-22 13:54:00 +00:00
// максимальный размер выделяемого буфера в heap для приема порции
# ifndef TCP_SRV_SERVER_MAX_RXBUF
2017-10-17 14:42:32 +00:00
# define TCP_SRV_SERVER_MAX_RXBUF TCP_WND // (TCP_MSS*3) // 1460*2=2920, 1460*3=4380, 1460*4=5840
2017-04-22 13:54:00 +00:00
# endif
// размер выделяемого буфера в heap для передачи при буферизированном выводе
# ifndef TCP_SRV_SERVER_DEF_TXBUF
2017-10-17 14:42:32 +00:00
# define TCP_SRV_SERVER_DEF_TXBUF TCP_SND_BUF //(TCP_MSS*3) // 1460*2=2920, 1460*3=4380, 1460*4=5840
2017-04-22 13:54:00 +00:00
# endif
# define ID_CLIENTS_PORT 3 // до 3-х clients
# define tcpsrv_init_client1() tcpsrv_init(1) // tcp2uart_client
# define tcpsrv_init_client2() tcpsrv_init(2) // mdb_tcp_client
# define tcpsrv_init_client3() tcpsrv_init(3)
# define TCP_CLIENT_NEXT_CONNECT_S 5 // syscfg.tcp_client_twait // 5000 // через 5 сек
# define TCP_CLIENT_MAX_CONNECT_RETRY 7 // до 7 раз с интервалом TCP_CLIENT_NEXT_CONNECT_MS
//--------------------------------------------------------------------------
// Структура соединения
//
typedef struct t_tcpsrv_conn_flags {
2017-06-24 02:03:03 +00:00
uint16 srv_reopen : 1 ; //0001 открытие нового соединения более max_conn ведет к закрытию наиболее старого соединения.
uint16 pcb_time_wait_free : 1 ; //0002 проверка на макс кол-во и уничтожение pcb с TIME_WAIT при вызове disconnect() (иначе pcb TIME_WAIT 60 сек http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html)
uint16 nagle_disabled : 1 ; //0004 выключение nagle
uint16 rx_buf : 1 ; //0008 прием в буфер, используется ручное управление размером окна TCP
uint16 rx_null : 1 ; //0010 отключение вызова func_received_data() и прием в null (устанавливается автоматически при вызове tcpsrv_disconnect())
uint16 tx_null : 1 ; //0020 отключение вызова func_sent_callback() и передача в null (устанавливается автоматически при вызове tcpsrv_disconnect())
uint16 wait_sent : 1 ; //0040 ожидет завершения/подтверждения передачи от lwip
uint16 busy_bufo : 1 ; //0080 идет обработка bufo
uint16 busy_bufi : 1 ; //0100 идет обработка bufi
uint16 tmp0 : 1 ; //0200 резерв
uint16 tmp1 : 1 ; //0400 резерв
2017-04-22 13:54:00 +00:00
// далее идут биты не относящиеся к работе tcp_srv_conn
2017-06-24 02:03:03 +00:00
uint16 user_flg1 : 1 ; //0800 для нужд процедур уровнем выше (пока свободен)
2017-04-22 13:54:00 +00:00
uint16 user_flg2 : 1 ; //1000 для нужд процедур уровнем выше (пока свободен)
uint16 user_option1 : 1 ; //2000 для нужд процедур обработки переменных (использован для hexdump, xml_mdb в web_int_callbacks.c)
uint16 user_option2 : 1 ; //4000 для нужд процедур обработки переменных (использован для xml_mdb в web_int_callbacks.c)
} __attribute__ ( ( packed ) ) tcpsrv_conn_flags ;
typedef struct t_TCP_SERV_CONN {
volatile tcpsrv_conn_flags flag ; //+0 флаги соеднения
enum srvconn_state state ; //+4 состояние
struct t_TCP_SERV_CFG * pcfg ; //+8 указатель на базовую структуру сервера
uint16 recv_check ; //+12 счет тиков соединения в tcpsrv_poll
uint16 remote_port ; //+16 номер порта клиента
union { //+20 ip клиента
uint32 dw ;
uint8 b [ 4 ] ;
} remote_ip ;
struct t_TCP_SERV_CONN * next ; //+24 указатель на следующую структуру
struct tcp_pcb * pcb ; //+28 указатель на pcb в Lwip
uint8 * pbufo ; //+32 указатель на сегмент с передаваемыми данными
uint8 * ptrtx ; //+36 указатель на ещё не переданные данные
uint8 * pbufi ; //+40 указатель на сегмент буфера с принимаемыми данными
uint16 sizeo ; //+44 размер буфера передачи
uint16 sizei ; //+48 размер приемного буфера (кол-во принятых и ещё не обработанных байт)
uint16 cntro ; //+52 кол-во обработанных байт в буфере передачи
uint16 cntri ; //+56 кол-во обработанных байт в буфере приема
uint16 unrecved_bytes ; //+60 используется при ручном управлении TCP WIN / This can be used to throttle data reception
// далее идут переменные не относящиеся к работе tcp_srv_conn
uint8 * linkd ; //+64 указатель на прилепленные данные пользователя (при закрытии соединения вызывается os_close(linkd), если linkd != NULL;
} TCP_SERV_CONN ;
//--------------------------------------------------------------------------
// Вызываемые функции пользователя (calback-и)
//
typedef void ( * func_disconect_calback ) ( TCP_SERV_CONN * ts_conn ) ; // соединение закрыто
typedef err_t ( * func_listen ) ( TCP_SERV_CONN * ts_conn ) ; // новый клиент
typedef err_t ( * func_received_data ) ( TCP_SERV_CONN * ts_conn ) ; // принято всего ts_conn->sizei байт, лежат в буфере по ts_conn->pbufi, по выходу принимается обработанных ts_conn->cntri;
typedef err_t ( * func_sent_callback ) ( TCP_SERV_CONN * ts_conn ) ; // блок данных передан
//--------------------------------------------------------------------------
// Структура конфигурации tcp сервера
//
typedef struct t_TCP_SERV_CFG {
2017-06-24 02:03:03 +00:00
struct t_tcpsrv_conn_flags flag ; // начальные флаги для соединения
uint16 port ; // номер порта
uint16 min_heap ; // минимальный размер heap при открытии нового соединения, при = 0 заменяется на 8192.
uint8 max_conn ; // максимальное кол-во одновременных соединений
uint8 conn_count ; // кол-во текущих соединений, при инициализации прописывает 0
uint8 time_wait_rec ; // время (сек) ожидания запроса (передачи пакета) от клиента, до авто-закрытия соединения, по умолчанию TCP_SRV_RECV_WAIT сек.
uint8 time_wait_cls ; // время (сек) до авто-закрытия соединения после приема или передачи, по умолчанию TCP_SRV_END_WAIT сек.
TCP_SERV_CONN * conn_links ; // указатель на цепочку активных соединений, при инициализации или отсуствии активных соединений = NULL
struct tcp_pcb * pcb ; // начальный pcb [LISTEN] если сервер, иначе NULL
2017-04-22 13:54:00 +00:00
func_disconect_calback func_discon_cb ; // функция вызываемая после закрытия соединения, если = NULL - не вызывается
func_listen func_listen ; // функция вызываемая при присоединении клиента или коннекта к серверу, если = NULL - не вызывается
func_sent_callback func_sent_cb ; // функция вызываемая после передачи данных или наличию места в ip стеке для следушей передачи данных, если = NULL - не вызывается (+см. флаги)
func_received_data func_recv ; // функция вызываемая при приеме данных, если = NULL - не вызывается (+см. флаги)
struct t_TCP_SERV_CFG * next ; // следующий экземпляр структуры сервера/клиента
} TCP_SERV_CFG ;
//--------------------------------------------------------------------------
// Данные
//
extern TCP_SERV_CFG * phcfg ; // указатель на цепочку TCP_SERV_CFG (стартовавших серверов)
//--------------------------------------------------------------------------
// Функции
//
err_t tcpsrv_int_sent_data ( TCP_SERV_CONN * ts_conn , uint8 * psent , uint16 length ) ; // передать length байт (внутрення функция - никаких проверок)
void tcpsrv_disconnect ( TCP_SERV_CONN * ts_conn ) ; // закрыть соединение
void tcpsrv_print_remote_info ( TCP_SERV_CONN * ts_conn ) ; // выводит remote_ip:remote_port [conn_count] os_printf("srv x.x.x.x:x [n] ")
TCP_SERV_CFG * tcpsrv_server_port2pcfg ( uint16 portn ) ; // поиск структуры конфига по номеру порта
void tcpsrv_unrecved_win ( TCP_SERV_CONN * ts_conn ) ; // Восстановить размер TCP WIN, если используется ручное управление размером окна TCP
void tcpsrv_disconnect_calback_default ( TCP_SERV_CONN * ts_conn ) ;
err_t tcpsrv_listen_default ( TCP_SERV_CONN * ts_conn ) ;
err_t tcpsrv_sent_callback_default ( TCP_SERV_CONN * ts_conn ) ;
err_t tcpsrv_received_data_default ( TCP_SERV_CONN * ts_conn ) ;
TCP_SERV_CFG * tcpsrv_init ( uint16 portn ) ;
err_t tcpsrv_start ( TCP_SERV_CFG * p ) ;
err_t tcpsrv_close ( TCP_SERV_CFG * p ) ;
err_t tcpsrv_close_port ( uint16 portn ) ;
err_t tcpsrv_close_all ( void ) ;
2017-09-06 11:34:28 +00:00
const char * tspsrv_error_msg ( err_t err ) ;
const char * tspsrv_tcp_state_msg ( enum tcp_state state ) ;
const char * tspsrv_srvconn_state_msg ( enum srvconn_state state ) ;
2017-04-22 13:54:00 +00:00
# endif // __TCP_SERV_CONN_H__