12 #include "request.hpp" 34 explicit UDPDataEvent(
Addr sndr, std::unique_ptr<
const char[]> buf, std::size_t len,
bool part) noexcept
35 : data{std::move(buf)}, length{len}, sender{std::move(sndr)}, partial{part}
38 std::unique_ptr<const char[]>
data;
48 enum class UVUdpFlags: std::underlying_type_t<uv_udp_flags> {
49 IPV6ONLY = UV_UDP_IPV6ONLY,
50 REUSEADDR = UV_UDP_REUSEADDR
54 enum class UVMembership: std::underlying_type_t<uv_membership> {
55 LEAVE_GROUP = UV_LEAVE_GROUP,
56 JOIN_GROUP = UV_JOIN_GROUP
60 class SendReq final:
public Request<SendReq, uv_udp_send_t> {
62 using Deleter = void(*)(
char *);
64 SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<
char[], Deleter> dt,
unsigned int len)
65 : Request<SendReq, uv_udp_send_t>{ca, std::move(loop)},
67 buf{uv_buf_init(data.get(), len)}
70 void send(uv_udp_t *handle,
const struct sockaddr* addr) {
71 invoke(&uv_udp_send,
get(), handle, &buf, 1, addr, &defaultCallback<SendEvent>);
75 std::unique_ptr<char[], Deleter> data;
101 static void recvCallback(uv_udp_t *handle, ssize_t nread,
const uv_buf_t *buf,
const sockaddr *addr,
unsigned flags) {
102 const typename details::IpTraits<I>::Type *aptr =
reinterpret_cast<const typename details::IpTraits<I>::Type *
>(addr);
106 std::unique_ptr<const char[]> data{buf->base};
110 udp.publish(
UDPDataEvent{details::address<I>(aptr), std::move(data),
static_cast<std::size_t
>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
111 }
else if(nread == 0 && addr ==
nullptr) {
113 }
else if(nread == 0 && addr !=
nullptr) {
115 udp.publish(
UDPDataEvent{details::address<I>(aptr), std::move(data),
static_cast<std::size_t
>(nread),
false});
123 using Membership = details::UVMembership;
124 using Bind = details::UVUdpFlags;
128 using Handle::Handle;
130 explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref,
unsigned int f)
131 :
Handle{ca, std::move(ref)}, tag{FLAGS}, flags{f}
139 return (tag == FLAGS)
140 ? initialize(&uv_udp_init_ex, flags)
141 : initialize(&uv_udp_init);
157 invoke(&uv_udp_open,
get(), socket);
176 template<
typename I = IPv4>
178 typename details::IpTraits<I>::Type addr;
179 details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
180 invoke(&uv_udp_bind,
get(), reinterpret_cast<const sockaddr *>(&addr), opts);
198 template<
typename I = IPv4>
200 bind<I>(addr.
ip, addr.
port, opts);
207 template<
typename I = IPv4>
209 return details::address<I>(&uv_udp_getsockname,
get());
225 template<
typename I = IPv4>
227 return (0 == uv_udp_set_membership(
get(), multicast.data(), iface.data(),
static_cast<uv_membership
>(membership)));
239 return (0 == uv_udp_set_multicast_loop(
get(), enable));
248 return (0 == uv_udp_set_multicast_ttl(
get(), val > 255 ? 255 : val));
256 template<
typename I = IPv4>
258 return (0 == uv_udp_set_multicast_interface(
get(), iface.data()));
267 return (0 == uv_udp_set_broadcast(
get(), enable));
276 return (0 == uv_udp_set_ttl(
get(), val > 255 ? 255 : val));
297 template<
typename I = IPv4>
298 void send(std::string ip,
unsigned int port, std::unique_ptr<
char[]> data,
unsigned int len) {
299 typename details::IpTraits<I>::Type addr;
300 details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
302 auto req = loop().resource<details::SendReq>(
303 std::unique_ptr<char[], details::SendReq::Deleter>{
304 data.release(), [](
char *ptr) {
delete[] ptr; }
307 auto listener = [ptr = shared_from_this()](
const auto &event,
const auto &) {
313 req->send(
get(), reinterpret_cast<const sockaddr *>(&addr));
333 template<
typename I = IPv4>
334 void send(
Addr addr, std::unique_ptr<
char[]> data,
unsigned int len) {
335 send<I>(addr.
ip, addr.
port, std::move(data), len);
356 template<
typename I = IPv4>
357 void send(std::string ip,
unsigned int port,
char *data,
unsigned int len) {
358 typename details::IpTraits<I>::Type addr;
359 details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
361 auto req = loop().resource<details::SendReq>(
362 std::unique_ptr<char[], details::SendReq::Deleter>{
366 auto listener = [ptr = shared_from_this()](
const auto &event,
const auto &) {
372 req->send(
get(), reinterpret_cast<const sockaddr *>(&addr));
392 template<
typename I = IPv4>
393 void send(
Addr addr,
char *data,
unsigned int len) {
394 send<I>(addr.
ip, addr.
port, data, len);
409 template<
typename I = IPv4>
410 int trySend(std::string ip,
unsigned int port, std::unique_ptr<
char[]> data,
unsigned int len) {
411 typename details::IpTraits<I>::Type addr;
412 details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
414 uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
415 auto bw = uv_udp_try_send(
get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
436 template<
typename I = IPv4>
437 int trySend(
Addr addr, std::unique_ptr<
char[]> data,
unsigned int len) {
438 return trySend<I>(addr.
ip, addr.
port, std::move(data), len);
453 template<
typename I = IPv4>
454 int trySend(std::string ip,
unsigned int port,
char *data,
unsigned int len) {
455 typename details::IpTraits<I>::Type addr;
456 details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
458 uv_buf_t bufs[] = { uv_buf_init(data, len) };
459 auto bw = uv_udp_try_send(
get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
480 template<
typename I = IPv4>
482 return trySend<I>(addr.
ip, addr.
port, data, len);
495 template<
typename I = IPv4>
497 invoke(&uv_udp_recv_start,
get(), &allocCallback, &recvCallback<I>);
504 invoke(&uv_udp_recv_stop,
get());
508 enum { DEFAULT, FLAGS } tag{DEFAULT};
509 unsigned int flags{};
bool init()
Initializes the handle. The actual socket is created lazily.
int trySend(Addr addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
bool ttl(int val)
Sets the time to live.
void recv()
Prepares for receiving data.
void bind(Addr addr, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
void send(std::string ip, unsigned int port, char *data, unsigned int len)
Sends data over the UDP socket.
void send(Addr addr, char *data, unsigned int len)
Sends data over the UDP socket.
bool multicastMembership(std::string multicast, std::string iface, Membership membership)
Sets membership for a multicast address.
Utility class to handle flags.
void send(Addr addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
void stop()
Stops listening for incoming datagrams.
std::unique_ptr< const char[]> data
void open(OSSocketHandle socket)
Opens an existing file descriptor or SOCKET as a UDP handle.
int trySend(std::string ip, unsigned int port, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
bool multicastInterface(std::string iface)
Sets the multicast interface to send or receive data on.
int trySend(Addr addr, char *data, unsigned int len)
Sends data over the UDP socket.
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
bool broadcast(bool enable=false)
Sets broadcast on or off.
bool multicastTtl(int val)
Sets the multicast ttl.
void send(std::string ip, unsigned int port, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
bool multicastLoop(bool enable=true)
Sets IP multicast loop flag.
int trySend(std::string ip, unsigned int port, char *data, unsigned int len)
Sends data over the UDP socket.
void bind(std::string ip, unsigned int port, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
Addr sock() const noexcept
Get the local IP and port of the UDP handle.