uvw  2.6.0
udp.h
1 #ifndef UVW_UDP_INCLUDE_H
2 #define UVW_UDP_INCLUDE_H
3 
4 
5 #include <type_traits>
6 #include <utility>
7 #include <cstddef>
8 #include <memory>
9 #include <string>
10 #include <uv.h>
11 #include "request.hpp"
12 #include "handle.hpp"
13 #include "util.h"
14 
15 
16 namespace uvw {
17 
18 
24 struct SendEvent {};
25 
26 
32 struct UDPDataEvent {
33  explicit UDPDataEvent(Addr sndr, std::unique_ptr<char[]> buf, std::size_t len, bool part) noexcept;
34 
35  std::unique_ptr<char[]> data;
36  std::size_t length;
38  bool partial;
39 };
40 
41 
42 namespace details {
43 
44 
45 enum class UVUDPFlags: std::underlying_type_t<uv_udp_flags> {
46  IPV6ONLY = UV_UDP_IPV6ONLY,
47  UDP_PARTIAL = UV_UDP_PARTIAL,
48  REUSEADDR = UV_UDP_REUSEADDR,
49  UDP_MMSG_CHUNK = UV_UDP_MMSG_CHUNK,
50  UDP_RECVMMSG = UV_UDP_RECVMMSG
51 };
52 
53 
54 enum class UVMembership: std::underlying_type_t<uv_membership> {
55  LEAVE_GROUP = UV_LEAVE_GROUP,
56  JOIN_GROUP = UV_JOIN_GROUP
57 };
58 
59 
60 class SendReq final: public Request<SendReq, uv_udp_send_t> {
61 public:
62  using Deleter = void(*)(char *);
63 
64  SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<char[], Deleter> dt, unsigned int len);
65 
66  void send(uv_udp_t *handle, const struct sockaddr* addr);
67 
68 private:
69  std::unique_ptr<char[], Deleter> data;
70  uv_buf_t buf;
71 };
72 
73 
74 }
75 
76 
93 class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
94  template<typename I>
95  static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
96  const typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
97 
98  UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
99  // data will be destroyed no matter of what the value of nread is
100  std::unique_ptr<char[]> data{buf->base};
101 
102  if(nread > 0) {
103  // data available (can be truncated)
104  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
105  } else if(nread == 0 && addr == nullptr) {
106  // no more data to be read, doing nothing is fine
107  } else if(nread == 0 && addr != nullptr) {
108  // empty udp packet
109  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), false});
110  } else {
111  // transmission error
112  udp.publish(ErrorEvent(nread));
113  }
114  }
115 
116 public:
117  using Membership = details::UVMembership;
118  using Bind = details::UVUDPFlags;
119  using IPv4 = uvw::IPv4;
120  using IPv6 = uvw::IPv6;
121 
122  using Handle::Handle;
123 
124  explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f);
125 
130  bool init();
131 
144  void open(OSSocketHandle socket);
145 
163  void bind(const sockaddr &addr, Flags<Bind> opts = Flags<Bind>{});
164 
178  void connect(const sockaddr &addr);
179 
194  template<typename I = IPv4>
195  void connect(std::string ip, unsigned int port);
196 
210  template<typename I = IPv4>
211  void connect(Addr addr);
212 
220  void disconnect();
221 
226  template<typename I = IPv4>
227  Addr peer() const noexcept;
228 
248  template<typename I = IPv4>
249  void bind(std::string ip, unsigned int port, Flags<Bind> opts = Flags<Bind>{});
250 
269  template<typename I = IPv4>
270  void bind(Addr addr, Flags<Bind> opts = Flags<Bind>{});
271 
276  template<typename I = IPv4>
277  Addr sock() const noexcept;
278 
292  template<typename I = IPv4>
293  bool multicastMembership(std::string multicast, std::string iface, Membership membership);
294 
303  bool multicastLoop(bool enable = true);
304 
310  bool multicastTtl(int val);
311 
317  template<typename I = IPv4>
318  bool multicastInterface(std::string iface);
319 
325  bool broadcast(bool enable = false);
326 
332  bool ttl(int val);
333 
351  void send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
352 
371  template<typename I = IPv4>
372  void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
373 
391  template<typename I = IPv4>
392  void send(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
393 
411  void send(const sockaddr &addr, char *data, unsigned int len);
412 
431  template<typename I = IPv4>
432  void send(std::string ip, unsigned int port, char *data, unsigned int len);
433 
451  template<typename I = IPv4>
452  void send(Addr addr, char *data, unsigned int len);
453 
465  template<typename I = IPv4>
466  int trySend(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
467 
480  template<typename I = IPv4>
481  int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
482 
494  template<typename I = IPv4>
495  int trySend(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
496 
508  template<typename I = IPv4>
509  int trySend(const sockaddr &addr, char *data, unsigned int len);
510 
523  template<typename I = IPv4>
524  int trySend(std::string ip, unsigned int port, char *data, unsigned int len);
525 
537  template<typename I = IPv4>
538  int trySend(Addr addr, char *data, unsigned int len);
539 
550  template<typename I = IPv4>
551  void recv();
552 
556  void stop();
557 
565  size_t sendQueueSize() const noexcept;
566 
571  size_t sendQueueCount() const noexcept;
572 
573 private:
574  enum { DEFAULT, FLAGS } tag{DEFAULT};
575  unsigned int flags{};
576 };
577 
578 
585 // (extern) explicit instantiations
586 
587 extern template void UDPHandle::connect<IPv4>(std::string, unsigned int);
588 extern template void UDPHandle::connect<IPv6>(std::string, unsigned int);
589 
590 extern template void UDPHandle::connect<IPv4>(Addr);
591 extern template void UDPHandle::connect<IPv6>(Addr);
592 
593 extern template Addr UDPHandle::peer<IPv4>() const noexcept;
594 extern template Addr UDPHandle::peer<IPv6>() const noexcept;
595 
596 extern template void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
597 extern template void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
598 
599 extern template void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
600 extern template void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
601 
602 extern template Addr UDPHandle::sock<IPv4>() const noexcept;
603 extern template Addr UDPHandle::sock<IPv6>() const noexcept;
604 
605 extern template bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
606 extern template bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
607 
608 extern template bool UDPHandle::multicastInterface<IPv4>(std::string);
609 extern template bool UDPHandle::multicastInterface<IPv6>(std::string);
610 
611 extern template void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
612 extern template void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
613 
614 extern template void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
615 extern template void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
616 
617 extern template void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
618 extern template void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
619 
620 extern template void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
621 extern template void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
622 
623 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
624 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
625 
626 extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
627 extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
628 
629 extern template int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
630 extern template int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
631 
632 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
633 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
634 
635 extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
636 extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
637 
638 extern template int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
639 extern template int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
640 
641 extern template void UDPHandle::recv<IPv4>();
642 extern template void UDPHandle::recv<IPv6>();
643 
644 
651 }
652 
653 
654 #ifndef UVW_AS_LIB
655 #include "udp.cpp"
656 #endif
657 
658 #endif // UVW_UDP_INCLUDE_H
uvw::UDPHandle::multicastInterface
bool multicastInterface(std::string iface)
Sets the multicast interface to send or receive data on.
uvw::Resource::data
std::shared_ptr< R > data() const
Gets user-defined data. uvw won't use this field in any case.
Definition: resource.hpp:54
uvw
uvw default namespace.
Definition: async.h:10
uvw::UDPHandle::broadcast
bool broadcast(bool enable=false)
Sets broadcast on or off.
uvw::UDPDataEvent
UDPDataEvent event.
Definition: udp.h:32
uvw::UDPHandle::send
void send(const sockaddr &addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
uvw::ErrorEvent
The ErrorEvent event.
Definition: emitter.h:24
uvw::UDPHandle::init
bool init()
Initializes the handle. The actual socket is created lazily.
uvw::SendEvent
SendEvent event.
Definition: udp.h:24
uvw::UDPHandle::multicastTtl
bool multicastTtl(int val)
Sets the multicast ttl.
uvw::UDPHandle::trySend
int trySend(const sockaddr &addr, std::unique_ptr< char[]> data, unsigned int len)
Sends data over the UDP socket.
uvw::UDPHandle::bind
void bind(const sockaddr &addr, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
uvw::UDPHandle::multicastLoop
bool multicastLoop(bool enable=true)
Sets IP multicast loop flag.
uvw::UDPHandle::recv
void recv()
Prepares for receiving data.
uvw::UDPHandle::multicastMembership
bool multicastMembership(std::string multicast, std::string iface, Membership membership)
Sets membership for a multicast address.
uvw::IPv4
The IPv4 tag.
Definition: util.h:307
uvw::UDPHandle
The UDPHandle handle.
Definition: udp.h:93
uvw::Flags
Utility class to handle flags.
Definition: util.h:82
uvw::UDPHandle::sock
Addr sock() const noexcept
Get the local IP and port of the UDP handle.
uvw::UDPDataEvent::data
std::unique_ptr< char[]> data
Definition: udp.h:35
uvw::Handle
Handle base class.
Definition: handle.hpp:30
uvw::UDPHandle::sendQueueCount
size_t sendQueueCount() const noexcept
Number of send requests currently in the queue awaiting to be processed.
uvw::Addr
Address representation.
Definition: util.h:321
uvw::UDPHandle::disconnect
void disconnect()
Disconnects the handle.
uvw::UDPHandle::open
void open(OSSocketHandle socket)
Opens an existing file descriptor or SOCKET as a UDP handle.
uvw::UDPDataEvent::sender
Addr sender
Definition: udp.h:37
uvw::UDPHandle::ttl
bool ttl(int val)
Sets the time to live.
uvw::OSSocketHandle
details::UVTypeWrapper< uv_os_sock_t > OSSocketHandle
Definition: util.h:190
uvw::UDPDataEvent::length
std::size_t length
Definition: udp.h:36
uvw::UDPHandle::peer
Addr peer() const noexcept
Gets the remote address to which the handle is connected, if any.
uvw::UDPHandle::connect
void connect(const sockaddr &addr)
Associates the handle to a remote address and port (either IPv4 or IPv6).
uvw::IPv6
The IPv6 tag.
Definition: util.h:315
uvw::UDPHandle::stop
void stop()
Stops listening for incoming datagrams.
uvw::UDPDataEvent::partial
bool partial
Definition: udp.h:38
uvw::UDPHandle::sendQueueSize
size_t sendQueueSize() const noexcept
Gets the number of bytes queued for sending.