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