uvw  2.12.1
udp.h
1 #ifndef UVW_UDP_INCLUDE_H
2 #define UVW_UDP_INCLUDE_H
3 
4 #include <cstddef>
5 #include <memory>
6 #include <string>
7 #include <type_traits>
8 #include <utility>
9 #include <uv.h>
10 #include "handle.hpp"
11 #include "request.hpp"
12 #include "util.h"
13 
14 namespace uvw {
15 
21 struct SendEvent {};
22 
28 struct UDPDataEvent {
29  explicit UDPDataEvent(Addr sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept;
30 
31  std::unique_ptr<char[]> data;
32  std::size_t length;
34  bool partial;
35 };
36 
37 namespace details {
38 
39 enum class UVUDPFlags : std::underlying_type_t<uv_udp_flags> {
40  IPV6ONLY = UV_UDP_IPV6ONLY,
41  UDP_PARTIAL = UV_UDP_PARTIAL,
42  REUSEADDR = UV_UDP_REUSEADDR,
43  UDP_MMSG_CHUNK = UV_UDP_MMSG_CHUNK,
44  UDP_MMSG_FREE = UV_UDP_MMSG_FREE,
45  UDP_LINUX_RECVERR = UV_UDP_LINUX_RECVERR,
46  UDP_RECVMMSG = UV_UDP_RECVMMSG
47 };
48 
49 enum class UVMembership : std::underlying_type_t<uv_membership> {
50  LEAVE_GROUP = UV_LEAVE_GROUP,
51  JOIN_GROUP = UV_JOIN_GROUP
52 };
53 
54 class SendReq final: public Request<SendReq, uv_udp_send_t> {
55 public:
56  using Deleter = void (*)(char *);
57 
58  SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<char[], Deleter> dt, unsigned int len);
59 
60  void send(uv_udp_t *handle, const struct sockaddr *addr);
61 
62 private:
63  std::unique_ptr<char[], Deleter> data;
64  uv_buf_t buf;
65 };
66 
67 } // namespace details
68 
85 class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
86  template<typename I>
87  static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
88  const typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
89 
90  UDPHandle &udp = *(static_cast<UDPHandle *>(handle->data));
91  // data will be destroyed no matter of what the value of nread is
92  std::unique_ptr<char[]> data{buf->base};
93 
94  if(nread > 0) {
95  // data available (can be truncated)
96  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
97  } else if(nread == 0 && addr == nullptr) {
98  // no more data to be read, doing nothing is fine
99  } else if(nread == 0 && addr != nullptr) {
100  // empty udp packet
101  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), false});
102  } else {
103  // transmission error
104  udp.publish(ErrorEvent(nread));
105  }
106  }
107 
108 public:
109  using Membership = details::UVMembership;
110  using Bind = details::UVUDPFlags;
111  using IPv4 = uvw::IPv4;
112  using IPv6 = uvw::IPv6;
113 
114  explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f = {});
115 
120  bool init();
121 
134  void open(OSSocketHandle socket);
135 
156  void bind(const sockaddr &addr, Flags<Bind> opts = Flags<Bind>{});
157 
171  void connect(const sockaddr &addr);
172 
187  template<typename I = IPv4>
188  void connect(const std::string &ip, unsigned int port);
189 
203  template<typename I = IPv4>
204  void connect(Addr addr);
205 
213  void disconnect();
214 
219  template<typename I = IPv4>
220  Addr peer() const noexcept;
221 
243  template<typename I = IPv4>
244  void bind(const std::string &ip, unsigned int port, Flags<Bind> opts = Flags<Bind>{});
245 
266  template<typename I = IPv4>
267  void bind(Addr addr, Flags<Bind> opts = Flags<Bind>{});
268 
273  template<typename I = IPv4>
274  Addr sock() const noexcept;
275 
289  template<typename I = IPv4>
290  bool multicastMembership(const std::string &multicast, const std::string &iface, Membership membership);
291 
300  bool multicastLoop(bool enable = true);
301 
307  bool multicastTtl(int val);
308 
314  template<typename I = IPv4>
315  bool multicastInterface(const std::string &iface);
316 
322  bool broadcast(bool enable = false);
323 
329  bool ttl(int val);
330 
348  void send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
349 
368  template<typename I = IPv4>
369  void send(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
370 
388  template<typename I = IPv4>
389  void send(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
390 
408  void send(const sockaddr &addr, char *data, unsigned int len);
409 
428  template<typename I = IPv4>
429  void send(const std::string &ip, unsigned int port, char *data, unsigned int len);
430 
448  template<typename I = IPv4>
449  void send(Addr addr, char *data, unsigned int len);
450 
462  template<typename I = IPv4>
463  int trySend(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
464 
477  template<typename I = IPv4>
478  int trySend(const std::string &ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
479 
491  template<typename I = IPv4>
492  int trySend(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
493 
505  template<typename I = IPv4>
506  int trySend(const sockaddr &addr, char *data, unsigned int len);
507 
520  template<typename I = IPv4>
521  int trySend(const std::string &ip, unsigned int port, char *data, unsigned int len);
522 
534  template<typename I = IPv4>
535  int trySend(Addr addr, char *data, unsigned int len);
536 
547  template<typename I = IPv4>
548  void recv();
549 
553  void stop();
554 
562  size_t sendQueueSize() const noexcept;
563 
568  size_t sendQueueCount() const noexcept;
569 
570 private:
571  enum {
572  DEFAULT,
573  FLAGS
574  } tag{DEFAULT};
575 
576  unsigned int flags{};
577 };
578 
584 // (extern) explicit instantiations
585 #ifdef UVW_AS_LIB
586 extern template void UDPHandle::connect<IPv4>(const std::string &, unsigned int);
587 extern template void UDPHandle::connect<IPv6>(const std::string &, unsigned int);
588 
589 extern template void UDPHandle::connect<IPv4>(Addr);
590 extern template void UDPHandle::connect<IPv6>(Addr);
591 
592 extern template Addr UDPHandle::peer<IPv4>() const noexcept;
593 extern template Addr UDPHandle::peer<IPv6>() const noexcept;
594 
595 extern template void UDPHandle::bind<IPv4>(const std::string &, unsigned int, Flags<Bind>);
596 extern template void UDPHandle::bind<IPv6>(const std::string &, unsigned int, Flags<Bind>);
597 
598 extern template void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
599 extern template void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
600 
601 extern template Addr UDPHandle::sock<IPv4>() const noexcept;
602 extern template Addr UDPHandle::sock<IPv6>() const noexcept;
603 
604 extern template bool UDPHandle::multicastMembership<IPv4>(const std::string &, const std::string &, Membership);
605 extern template bool UDPHandle::multicastMembership<IPv6>(const std::string &, const std::string &, Membership);
606 
607 extern template bool UDPHandle::multicastInterface<IPv4>(const std::string &);
608 extern template bool UDPHandle::multicastInterface<IPv6>(const std::string &);
609 
610 extern template void UDPHandle::send<IPv4>(const std::string &, unsigned int, std::unique_ptr<char[]>, unsigned int);
611 extern template void UDPHandle::send<IPv6>(const std::string &, unsigned int, std::unique_ptr<char[]>, unsigned int);
612 
613 extern template void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
614 extern template void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
615 
616 extern template void UDPHandle::send<IPv4>(const std::string &, unsigned int, char *, unsigned int);
617 extern template void UDPHandle::send<IPv6>(const std::string &, unsigned int, char *, unsigned int);
618 
619 extern template void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
620 extern template void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
621 
622 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
623 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
624 
625 extern template int UDPHandle::trySend<IPv4>(const std::string &, unsigned int, std::unique_ptr<char[]>, unsigned int);
626 extern template int UDPHandle::trySend<IPv6>(const std::string &, unsigned int, std::unique_ptr<char[]>, unsigned int);
627 
628 extern template int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
629 extern template int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
630 
631 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
632 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
633 
634 extern template int UDPHandle::trySend<IPv4>(const std::string &, unsigned int, char *, unsigned int);
635 extern template int UDPHandle::trySend<IPv6>(const std::string &, unsigned int, char *, unsigned int);
636 
637 extern template int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
638 extern template int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
639 
640 extern template void UDPHandle::recv<IPv4>();
641 extern template void UDPHandle::recv<IPv6>();
642 #endif // UVW_AS_LIB
643 
649 } // namespace uvw
650 
651 #ifndef UVW_AS_LIB
652 # include "udp.cpp"
653 #endif
654 
655 #endif // UVW_UDP_INCLUDE_H
Utility class to handle flags.
Definition: util.h:79
Handle base class.
Definition: handle.hpp:26
std::shared_ptr< R > data() const
Gets user-defined data. uvw won't use this field in any case.
Definition: resource.hpp:48
The UDPHandle handle.
Definition: udp.h:85
bool init()
Initializes the handle. The actual socket is created lazily.
void stop()
Stops listening for incoming datagrams.
bool broadcast(bool enable=false)
Sets broadcast on or off.
void connect(Addr addr)
Associates the handle to a remote address and port (either IPv4 or IPv6).
size_t sendQueueSize() const noexcept
Gets the number of bytes queued for sending.
void bind(const sockaddr &addr, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
int trySend(const sockaddr &addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
size_t sendQueueCount() const noexcept
Number of send requests currently in the queue awaiting to be processed.
void bind(Addr addr, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
bool multicastTtl(int val)
Sets the multicast ttl.
Addr peer() const noexcept
Gets the remote address to which the handle is connected, if any.
void send(const sockaddr &addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
void recv()
Prepares for receiving data.
bool multicastInterface(const std::string &iface)
Sets the multicast interface to send or receive data on.
bool ttl(int val)
Sets the time to live.
bool multicastMembership(const std::string &multicast, const std::string &iface, Membership membership)
Sets membership for a multicast address.
Addr sock() const noexcept
Get the local IP and port of the UDP handle.
void disconnect()
Disconnects the handle.
void connect(const sockaddr &addr)
Associates the handle to a remote address and port (either IPv4 or IPv6).
void open(OSSocketHandle socket)
Opens an existing file descriptor or SOCKET as a UDP handle.
void connect(const std::string &ip, unsigned int port)
Associates the handle to a remote address and port (either IPv4 or IPv6).
bool multicastLoop(bool enable=true)
Sets IP multicast loop flag.
uvw default namespace.
Definition: async.h:8
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.h:205
Address representation.
Definition: util.h:331
The ErrorEvent event.
Definition: emitter.h:22
The IPv4 tag.
Definition: util.h:319
The IPv6 tag.
Definition: util.h:326
SendEvent event.
Definition: udp.h:21
UDPDataEvent event.
Definition: udp.h:28
std::size_t length
Definition: udp.h:32
Addr sender
Definition: udp.h:33
bool partial
Definition: udp.h:34
std::unique_ptr< char[]> data
Definition: udp.h:31