169 lines
4.0 KiB
C
169 lines
4.0 KiB
C
#include <stdint.h>
|
||
#include <string.h>
|
||
#include "lwip/ip_addr.h"
|
||
#include "lwip/tcp.h"
|
||
#include "lwip/err.h"
|
||
#include "lwip/opt.h"
|
||
#include "lwip/sockets.h"
|
||
#include "esp_log.h"
|
||
|
||
#include "tcp_server.h"
|
||
#include "inc/communication_pad.h"
|
||
|
||
#define LOG_TAG "[communication_tcp_sr]: "
|
||
|
||
|
||
struct clientNode client_list; // 客户端链表头结点
|
||
struct clientNode *client_r_p = &client_list; // 客户端链表尾指针
|
||
|
||
void client_list_add(struct tcp_pcb *pcb)
|
||
{
|
||
struct clientNode *client = (struct clientNode *)malloc(sizeof(struct clientNode));
|
||
client->pcb = pcb;
|
||
client->enable_notify = 0;
|
||
client->next = NULL;
|
||
client_r_p->next = client;
|
||
client_r_p = client;
|
||
}
|
||
|
||
void client_list_delete(struct tcp_pcb *pcb)
|
||
{
|
||
struct clientNode *p = &client_list;
|
||
while (p->next)
|
||
{
|
||
if (p->next->pcb == pcb)
|
||
{
|
||
struct clientNode *q = p->next;
|
||
if (q == client_r_p)
|
||
{
|
||
client_r_p = p;
|
||
}
|
||
p->next = q->next;
|
||
free(q);
|
||
return;
|
||
}
|
||
p = p->next;
|
||
}
|
||
}
|
||
|
||
void cilent_list_delete_all(void)
|
||
{
|
||
struct clientNode *p = &client_list;
|
||
while (p->next)
|
||
{
|
||
struct clientNode *q = p->next;
|
||
p->next = q->next;
|
||
free(q);
|
||
}
|
||
client_r_p = &client_list;
|
||
}
|
||
|
||
struct clientNode* find_client_by_pcb(struct tcp_pcb *pcb)
|
||
{
|
||
struct clientNode *p = client_list.next;
|
||
struct clientNode *ret = NULL;
|
||
while (p)
|
||
{
|
||
if (p->pcb == pcb)
|
||
{
|
||
ret = p;
|
||
break;
|
||
}
|
||
p = p->next;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
static err_t ModBusSlave_recv(void *arg, struct tcp_pcb *newpcb, struct pbuf *p, err_t err) {
|
||
if (p != NULL) {
|
||
uint8_t *rxbuf;
|
||
uint8_t *txbuf = NULL;
|
||
int rxlen, txlen = 0;
|
||
tcp_recved(newpcb, p->tot_len);
|
||
rxbuf = (uint8_t *)p->payload;
|
||
rxlen = p->len;
|
||
ESP_LOGI(LOG_TAG, "recive data %d:", rxlen);
|
||
esp_log_buffer_hex(LOG_TAG, rxbuf, rxlen);
|
||
|
||
// 接受到数据,调用pad_deal_recived_data处理,如果需要回复(读操作),则再将数据发送出去
|
||
struct clientNode* client = find_client_by_pcb(newpcb);
|
||
if (!client)
|
||
{
|
||
ESP_LOGI(LOG_TAG, "err:not find this client");
|
||
return ERR_OK;
|
||
}
|
||
pad_deal_recived_data(rxbuf, rxlen, &client->enable_notify, &txbuf, &txlen);
|
||
if (txbuf)
|
||
{
|
||
tcp_write(newpcb, txbuf, txlen, 1);
|
||
free(txbuf);
|
||
}
|
||
pbuf_free(p);
|
||
}
|
||
else if (err == ERR_OK)
|
||
{
|
||
ESP_LOGI(LOG_TAG, "gps1 remote end is closing the connection\n");
|
||
tcp_err(newpcb, NULL);
|
||
tcp_recv(newpcb, NULL);
|
||
// tcp_poll(newpcb, NULL, 120);
|
||
err_t err_p = tcp_close(newpcb);
|
||
client_list_delete(newpcb);
|
||
if (ERR_OK != err_p)
|
||
{
|
||
ESP_LOGI(LOG_TAG, "gps1 close error. err:%d\n", err_p);
|
||
}
|
||
return err_p;
|
||
}
|
||
return ERR_OK;
|
||
}
|
||
|
||
|
||
static void ModBusSlave_conn_err(void *arg, err_t err) {
|
||
ESP_LOGI(LOG_TAG, "connect err!");
|
||
// log_printf(LERROR, LOG_TAG "connection error, err:%d\n", err);
|
||
// cilent_list_delete_all(); // 不知道为什么这个回调函数没有提供newpcb
|
||
}
|
||
static err_t ModBusSlave_poll(void *arg, struct tcp_pcb *newpcb) {
|
||
// if (newpcb) {
|
||
// // log_printf(LERROR, LOG_TAG "close pcb\n");
|
||
// tcp_close(newpcb);
|
||
// newpcb = NULL;
|
||
// }
|
||
ESP_LOGI(LOG_TAG, "poll!");
|
||
return ERR_OK;
|
||
}
|
||
|
||
|
||
static err_t ModBusSlave_accept(void *arg, struct tcp_pcb *pcb, err_t err) {
|
||
tcp_err(pcb, ModBusSlave_conn_err);
|
||
tcp_recv(pcb, ModBusSlave_recv);
|
||
// tcp_poll(pcb, ModBusSlave_poll, 120); // 60 second timeout
|
||
client_list_add(pcb);
|
||
return ERR_OK;
|
||
}
|
||
|
||
void tcp_server_init(void) {
|
||
struct tcp_pcb *pcb;
|
||
pcb = tcp_new();
|
||
tcp_bind(pcb, IP_ADDR_ANY, TCP_SERVER_PORT);
|
||
pcb = tcp_listen(pcb);
|
||
tcp_accept(pcb, ModBusSlave_accept);
|
||
}
|
||
|
||
// 遍历所有客户端,如果允许上报,则将数据上报
|
||
void tcp_server_notify(uint8_t *data, int len)
|
||
{
|
||
struct clientNode *p = client_list.next;
|
||
while (p)
|
||
{
|
||
if (p->enable_notify == 1) // 开启上报
|
||
{
|
||
ESP_LOGI(LOG_TAG, "tcp_server_notify");
|
||
esp_log_buffer_hex(LOG_TAG, data, len);
|
||
tcp_write(p->pcb, data, len, 1);
|
||
}
|
||
p = p->next;
|
||
}
|
||
}
|