16#include "lwip/priv/tcpip_priv.h"
41 struct udp_pcb *
out =
nullptr;
55static bool udp_pbuf_send(
struct udp_pcb *pcb,
const ip_addr_t *addr, u16_t port,
const uint8_t *data,
size_t len)
57 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)len, PBUF_RAM);
60 memcpy(p->payload, data, len);
61 err_t e = udp_sendto(pcb, p, addr, port);
69static void udp_trampoline(
void *arg,
struct udp_pcb *pcb,
struct pbuf *p,
const ip_addr_t *addr, u16_t port)
74 u16_t n = (p->tot_len <
sizeof(s_udp.
rx)) ? p->tot_len : (u16_t)
sizeof(s_udp.
rx);
75 pbuf_copy_partial(p, s_udp.
rx, n, 0);
100 struct tcpip_api_call_data
base;
112static err_t udp_do(
struct tcpip_api_call_data *c)
121 struct udp_pcb *pcb = udp_new();
124 if (udp_bind(pcb, IP_ANY_TYPE, k->
port) == ERR_OK)
142 s_udp.
out = udp_new();
162 memset(&k, 0,
sizeof(k));
166 tcpip_api_call(udp_do, &k.
base);
180 if (!peer || !peer->
pcb || !peer->
addr || !data || len == 0)
183 return udp_pbuf_send(peer->
pcb, peer->
addr, peer->
port, data, len);
185 memset(&k, 0,
sizeof(k));
192 tcpip_api_call(udp_do, &k.
base);
196bool det_udp_sendto(
const char *dst_ip, uint16_t dst_port,
const uint8_t *data,
size_t len)
198 if (!dst_ip || !data || len == 0)
201 if (!ipaddr_aton(dst_ip, &dst))
207 s_udp.
out = udp_new();
211 return udp_pbuf_send(s_udp.
out, &dst, dst_port, data, len);
214 memset(&k, 0,
sizeof(k));
220 tcpip_api_call(udp_do, &k.
base);
226 if (!peer || !peer->
addr || !ip_out || ip_cap < 8)
228 ipaddr_ntoa_r(peer->
addr, ip_out, (
int)ip_cap);
230 *port_out = peer->
port;
237 if (!dst_ip || !data || len == 0)
240 if (!ipaddr_aton(dst_ip, &dst))
242 struct udp_pcb *pcb =
nullptr;
254 return udp_pbuf_send(pcb, &dst, dst_port, data, len);
256 memset(&k, 0,
sizeof(k));
263 tcpip_api_call(udp_do, &k.
base);
283struct HostUdpListener
294 uint8_t cap_buf[2048];
296 bool listener_sendto_ok;
298HostUdpCtx s_udp = {{},
false, {}, 0,
true};
301bool host_capture(
const uint8_t *data,
size_t len)
303 if (s_udp.cap_on && data && len && len <=
sizeof(s_udp.cap_buf))
305 memcpy(s_udp.cap_buf, data, len);
316 HostUdpListener *slot =
nullptr;
318 if (s_udp.lst[i].used && s_udp.lst[i].port == port)
319 slot = &s_udp.lst[i];
321 if (!s_udp.lst[i].used)
322 slot = &s_udp.lst[i];
324 slot = &s_udp.lst[0];
326 slot->handler = handler;
332void det_udp_inject(uint16_t listen_port,
const char *src_ip, uint16_t src_port,
const uint8_t *data,
size_t len)
335 if (s_udp.lst[i].used && s_udp.lst[i].port == listen_port && s_udp.lst[i].handler)
338 strncpy(peer.ip, src_ip ? src_ip :
"", sizeof(peer.ip) - 1);
339 peer.ip[
sizeof(peer.ip) - 1] =
'\0';
340 peer.
port = src_port;
341 s_udp.lst[i].handler(data, len, &peer, s_udp.lst[i].ctx);
346void det_udp_set_listener_sendto_result(
bool ok)
348 s_udp.listener_sendto_ok = ok;
351void det_udp_reset_listeners()
355 s_udp.listener_sendto_ok =
true;
361 return host_capture(data, len);
364void det_udp_capture_enable()
369void det_udp_capture_reset()
373const uint8_t *det_udp_captured()
375 return s_udp.cap_len ? s_udp.cap_buf :
nullptr;
377size_t det_udp_captured_len()
379 return s_udp.cap_len;
382bool det_udp_sendto(
const char *dst_ip, uint16_t dst_port,
const uint8_t *data,
size_t len)
386 return host_capture(data, len);
393 if (ip_out && ip_cap)
395 strncpy(ip_out, peer->ip, ip_cap - 1);
396 ip_out[ip_cap - 1] =
'\0';
399 *port_out = peer->
port;
409 if (!s_udp.listener_sendto_ok)
411 host_capture(data, len);
#define DETWS_UDP_RX_BUF_SIZE
Shared receive-scratch size for the transport-layer UDP service.
#define DETWS_MAX_UDP_LISTENERS
Maximum simultaneously bound UDP ports (transport-layer UDP service).
struct tcpip_api_call_data base
uint8_t rx[DETWS_UDP_RX_BUF_SIZE]
UdpListener listeners[DETWS_MAX_UDP_LISTENERS]
volatile bool in_tcpip_thread
bool det_udp_peer_addr(const struct DetUdpPeer *peer, char *ip_out, size_t ip_cap, uint16_t *port_out)
Copy a received peer's source IPv4 address (dotted-quad) and port out.
bool det_udp_sendto(const char *dst_ip, uint16_t dst_port, const uint8_t *data, size_t len)
Send a UDP datagram to an arbitrary destination (outbound client).
bool det_udp_send(struct DetUdpPeer *peer, const uint8_t *data, size_t len)
Send a datagram back to the peer captured during the handler call.
bool det_udp_listen(uint16_t port, DetUdpHandler handler, void *ctx)
Bind a UDP port and route incoming datagrams to handler.
bool det_udp_listener_sendto(uint16_t listen_port, const char *dst_ip, uint16_t dst_port, const uint8_t *data, size_t len)
Send a datagram from the listener bound on listen_port to an address.
Layer 4 (Transport) - connectionless UDP datagram service.
void(* DetUdpHandler)(const uint8_t *data, size_t len, struct DetUdpPeer *peer, void *ctx)
Datagram handler invoked for each received UDP packet.