170 lines
4.3 KiB
C
170 lines
4.3 KiB
C
#include <stdint.h>
|
||
#include <string.h>
|
||
#include "lwip/ip_addr.h"
|
||
#include "lwip/udp.h"
|
||
#include "lwip/err.h"
|
||
#include "lwip/opt.h"
|
||
#include "lwip/sockets.h"
|
||
#include "esp_log.h"
|
||
|
||
#include "inc/udp_server.h"
|
||
#include "inc/communication_pad.h"
|
||
|
||
#define LOG_TAG "[communication_udp_server]: "
|
||
|
||
|
||
struct clientNode client_list; // 客户端链表头结点
|
||
struct clientNode *client_r_p = &client_list; // 客户端链表尾指针
|
||
|
||
|
||
struct clientNode *client_list_add(struct udp_pcb * upcb, ip_addr_t *addr, uint16_t port)
|
||
{
|
||
struct clientNode *p = client_list.next;
|
||
struct clientNode *ret = NULL;
|
||
while (p)
|
||
{
|
||
if (ip_addr_cmp(&p->addr, addr) && p->port == port)
|
||
{
|
||
ret = p;
|
||
break;
|
||
}
|
||
p = p->next;
|
||
}
|
||
|
||
if (ret == NULL)
|
||
{
|
||
struct clientNode *client = (struct clientNode *)malloc(sizeof(struct clientNode));
|
||
client->upcb = upcb;
|
||
ip_addr_copy(client->addr, *addr);
|
||
client->port = port;
|
||
client->notify_timeout = UDP_NOTIFY_TIMEOUT;
|
||
client->next = NULL;
|
||
client_r_p->next = client;
|
||
client_r_p = client;
|
||
ret = client;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
// 返回删除的前一个
|
||
struct clientNode *client_list_delete(ip_addr_t *addr, uint16_t port)
|
||
{
|
||
struct clientNode *p = &client_list;
|
||
while (p->next)
|
||
{
|
||
if (ip_addr_cmp(&p->next->addr, addr) && p->next->port == port)
|
||
{
|
||
struct clientNode *q = p->next;
|
||
if (q == client_r_p)
|
||
{
|
||
client_r_p = p;
|
||
}
|
||
p->next = q->next;
|
||
free(q);
|
||
return p;
|
||
}
|
||
p = p->next;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
void udp_server_recived(void *arg, struct udp_pcb *upcb, struct pbuf *pkt_buf,
|
||
ip_addr_t *addr, u16_t port)
|
||
{
|
||
uint8_t *rxbuf;
|
||
uint8_t *txbuf = NULL;
|
||
int rxlen, txlen = 0;
|
||
rxbuf = (uint8_t *)pkt_buf->payload;
|
||
rxlen = pkt_buf->len;
|
||
ESP_LOGI(LOG_TAG, "recive data %d:", rxlen);
|
||
esp_log_buffer_hex(LOG_TAG, rxbuf, rxlen);
|
||
|
||
// 接受到数据,调用pad_deal_recived_data处理,如果需要回复(读操作),则再将数据发送出去
|
||
struct clientNode* client = client_list_add(upcb, addr, port);
|
||
int enable_notify = -1;
|
||
pad_deal_recived_data(rxbuf, rxlen, &enable_notify, &txbuf, &txlen);
|
||
if (enable_notify == 1)
|
||
{
|
||
client->notify_timeout = UDP_NOTIFY_TIMEOUT;
|
||
}
|
||
else if (enable_notify == 0)
|
||
{
|
||
client->notify_timeout = 0;
|
||
}
|
||
if (txbuf)
|
||
{
|
||
struct pbuf *pkt_txbuf = pbuf_alloc(PBUF_TRANSPORT, 1400, PBUF_RAM);
|
||
char *buf = (char *)pkt_txbuf->payload;
|
||
pkt_txbuf->len = txlen;
|
||
pkt_txbuf->tot_len = txlen;
|
||
memcpy(buf, txbuf, txlen);
|
||
err_t err = udp_sendto(upcb, pkt_txbuf, &addr, port);
|
||
pbuf_free(pkt_txbuf);
|
||
free(txbuf);
|
||
}
|
||
pbuf_free(pkt_buf);
|
||
}
|
||
|
||
void udp_server_init(void) {
|
||
err_t err;
|
||
struct udp_pcb *UDPpcb;
|
||
UDPpcb = udp_new();
|
||
if (!UDPpcb)
|
||
{
|
||
return;
|
||
}
|
||
err = udp_bind(UDPpcb, IP_ADDR_ANY, UDP_SERVER_PORT);
|
||
if (err != ERR_OK)
|
||
{
|
||
return;
|
||
}
|
||
udp_recv(UDPpcb, udp_server_recived, NULL);
|
||
}
|
||
|
||
// 遍历所有客户端,如果允许上报,则将数据上报
|
||
void udp_server_notify(uint8_t *data, int len)
|
||
{
|
||
struct clientNode *p = client_list.next;
|
||
while (p)
|
||
{
|
||
if (p->notify_timeout > 0)
|
||
{
|
||
// ESP_LOGI(LOG_TAG, "tcp_server_notify");
|
||
// esp_log_buffer_hex(LOG_TAG, data, len);
|
||
|
||
struct pbuf *pkt_txbuf = pbuf_alloc(PBUF_TRANSPORT, 1400, PBUF_RAM);
|
||
char *buf = (char *)pkt_txbuf->payload;
|
||
pkt_txbuf->len = len;
|
||
pkt_txbuf->tot_len = len;
|
||
memcpy(buf, data, len);
|
||
udp_sendto(p->upcb, pkt_txbuf, &p->addr, p->port);
|
||
pbuf_free(pkt_txbuf);
|
||
p->notify_timeout--;
|
||
}
|
||
else if (p->notify_timeout == 0) // 时间耗尽,删除
|
||
{
|
||
p = client_list_delete(&p->addr, p->port);
|
||
if (p == NULL)
|
||
{
|
||
ESP_LOGI(LOG_TAG, "err, confilct");
|
||
return;
|
||
}
|
||
}
|
||
p = p->next;
|
||
}
|
||
}
|