pile_com_stm32/main/communication_pad/udp_server.c
2024-04-25 10:20:39 +08:00

170 lines
4.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
}