uvw  2.8.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_MMSG_FREE = UV_UDP_MMSG_FREE,
51  UDP_RECVMMSG = UV_UDP_RECVMMSG
52 };
53 
54 
55 enum class UVMembership: std::underlying_type_t<uv_membership> {
56  LEAVE_GROUP = UV_LEAVE_GROUP,
57  JOIN_GROUP = UV_JOIN_GROUP
58 };
59 
60 
61 class SendReq final: public Request<SendReq, uv_udp_send_t> {
62 public:
63  using Deleter = void(*)(char *);
64 
65  SendReq(ConstructorAccess ca, std::shared_ptr<Loop> loop, std::unique_ptr<char[], Deleter> dt, unsigned int len);
66 
67  void send(uv_udp_t *handle, const struct sockaddr* addr);
68 
69 private:
70  std::unique_ptr<char[], Deleter> data;
71  uv_buf_t buf;
72 };
73 
74 
75 }
76 
77 
94 class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
95  template<typename I>
96  static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) {
97  const typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
98 
99  UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
100  // data will be destroyed no matter of what the value of nread is
101  std::unique_ptr<char[]> data{buf->base};
102 
103  if(nread > 0) {
104  // data available (can be truncated)
105  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), !(0 == (flags & UV_UDP_PARTIAL))});
106  } else if(nread == 0 && addr == nullptr) {
107  // no more data to be read, doing nothing is fine
108  } else if(nread == 0 && addr != nullptr) {
109  // empty udp packet
110  udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), static_cast<std::size_t>(nread), false});
111  } else {
112  // transmission error
113  udp.publish(ErrorEvent(nread));
114  }
115  }
116 
117 public:
118  using Membership = details::UVMembership;
119  using Bind = details::UVUDPFlags;
120  using IPv4 = uvw::IPv4;
121  using IPv6 = uvw::IPv6;
122 
123  explicit UDPHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, unsigned int f = {});
124 
129  bool init();
130 
143  void open(OSSocketHandle socket);
144 
164  void bind(const sockaddr &addr, Flags<Bind> opts = Flags<Bind>{});
165 
179  void connect(const sockaddr &addr);
180 
195  template<typename I = IPv4>
196  void connect(std::string ip, unsigned int port);
197 
211  template<typename I = IPv4>
212  void connect(Addr addr);
213 
221  void disconnect();
222 
227  template<typename I = IPv4>
228  Addr peer() const noexcept;
229 
250  template<typename I = IPv4>
251  void bind(std::string ip, unsigned int port, Flags<Bind> opts = Flags<Bind>{});
252 
272  template<typename I = IPv4>
273  void bind(Addr addr, Flags<Bind> opts = Flags<Bind>{});
274 
279  template<typename I = IPv4>
280  Addr sock() const noexcept;
281 
295  template<typename I = IPv4>
296  bool multicastMembership(std::string multicast, std::string iface, Membership membership);
297 
306  bool multicastLoop(bool enable = true);
307 
313  bool multicastTtl(int val);
314 
320  template<typename I = IPv4>
321  bool multicastInterface(std::string iface);
322 
328  bool broadcast(bool enable = false);
329 
335  bool ttl(int val);
336 
354  void send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
355 
374  template<typename I = IPv4>
375  void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
376 
394  template<typename I = IPv4>
395  void send(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
396 
414  void send(const sockaddr &addr, char *data, unsigned int len);
415 
434  template<typename I = IPv4>
435  void send(std::string ip, unsigned int port, char *data, unsigned int len);
436 
454  template<typename I = IPv4>
455  void send(Addr addr, char *data, unsigned int len);
456 
468  template<typename I = IPv4>
469  int trySend(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len);
470 
483  template<typename I = IPv4>
484  int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len);
485 
497  template<typename I = IPv4>
498  int trySend(Addr addr, std::unique_ptr<char[]> data, unsigned int len);
499 
511  template<typename I = IPv4>
512  int trySend(const sockaddr &addr, char *data, unsigned int len);
513 
526  template<typename I = IPv4>
527  int trySend(std::string ip, unsigned int port, char *data, unsigned int len);
528 
540  template<typename I = IPv4>
541  int trySend(Addr addr, char *data, unsigned int len);
542 
553  template<typename I = IPv4>
554  void recv();
555 
559  void stop();
560 
568  size_t sendQueueSize() const noexcept;
569 
574  size_t sendQueueCount() const noexcept;
575 
576 private:
577  enum { DEFAULT, FLAGS } tag{DEFAULT};
578  unsigned int flags{};
579 };
580 
581 
588 // (extern) explicit instantiations
589 #ifdef UVW_AS_LIB
590 extern template void UDPHandle::connect<IPv4>(std::string, unsigned int);
591 extern template void UDPHandle::connect<IPv6>(std::string, unsigned int);
592 
593 extern template void UDPHandle::connect<IPv4>(Addr);
594 extern template void UDPHandle::connect<IPv6>(Addr);
595 
596 extern template Addr UDPHandle::peer<IPv4>() const noexcept;
597 extern template Addr UDPHandle::peer<IPv6>() const noexcept;
598 
599 extern template void UDPHandle::bind<IPv4>(std::string, unsigned int, Flags<Bind>);
600 extern template void UDPHandle::bind<IPv6>(std::string, unsigned int, Flags<Bind>);
601 
602 extern template void UDPHandle::bind<IPv4>(Addr, Flags<Bind>);
603 extern template void UDPHandle::bind<IPv6>(Addr, Flags<Bind>);
604 
605 extern template Addr UDPHandle::sock<IPv4>() const noexcept;
606 extern template Addr UDPHandle::sock<IPv6>() const noexcept;
607 
608 extern template bool UDPHandle::multicastMembership<IPv4>(std::string, std::string, Membership);
609 extern template bool UDPHandle::multicastMembership<IPv6>(std::string, std::string, Membership);
610 
611 extern template bool UDPHandle::multicastInterface<IPv4>(std::string);
612 extern template bool UDPHandle::multicastInterface<IPv6>(std::string);
613 
614 extern template void UDPHandle::send<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
615 extern template void UDPHandle::send<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
616 
617 extern template void UDPHandle::send<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
618 extern template void UDPHandle::send<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
619 
620 extern template void UDPHandle::send<IPv4>(std::string, unsigned int, char *, unsigned int);
621 extern template void UDPHandle::send<IPv6>(std::string, unsigned int, char *, unsigned int);
622 
623 extern template void UDPHandle::send<IPv4>(Addr, char *, unsigned int);
624 extern template void UDPHandle::send<IPv6>(Addr, char *, unsigned int);
625 
626 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
627 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, std::unique_ptr<char[]>, unsigned int);
628 
629 extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
630 extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, std::unique_ptr<char[]>, unsigned int);
631 
632 extern template int UDPHandle::trySend<IPv4>(Addr, std::unique_ptr<char[]>, unsigned int);
633 extern template int UDPHandle::trySend<IPv6>(Addr, std::unique_ptr<char[]>, unsigned int);
634 
635 extern template int UDPHandle::trySend<IPv4>(const sockaddr &, char *, unsigned int);
636 extern template int UDPHandle::trySend<IPv6>(const sockaddr &, char *, unsigned int);
637 
638 extern template int UDPHandle::trySend<IPv4>(std::string, unsigned int, char *, unsigned int);
639 extern template int UDPHandle::trySend<IPv6>(std::string, unsigned int, char *, unsigned int);
640 
641 extern template int UDPHandle::trySend<IPv4>(Addr, char *, unsigned int);
642 extern template int UDPHandle::trySend<IPv6>(Addr, char *, unsigned int);
643 
644 extern template void UDPHandle::recv<IPv4>();
645 extern template void UDPHandle::recv<IPv6>();
646 #endif // UVW_AS_LIB
647 
654 }
655 
656 
657 #ifndef UVW_AS_LIB
658 #include "udp.cpp"
659 #endif
660 
661 #endif // UVW_UDP_INCLUDE_H
uvw::UDPHandle::multicastInterface
bool multicastInterface(std::string iface)
Sets the multicast interface to send or receive data on.
uvw::UDPHandle::bind
void bind(Addr addr, Flags< Bind > opts=Flags< Bind >{})
Binds the UDP handle to an IP address and port.
uvw::Resource< UDPHandle, uv_udp_t >::data
std::shared_ptr< R > data() const
Gets user-defined data. uvw won't use this field in any case.
Definition: resource.hpp:52
uvw::UDPHandle::connect
void connect(std::string ip, unsigned int port)
Associates the handle to a remote address and port (either IPv4 or IPv6).
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::UDPHandle::connect
void connect(Addr addr)
Associates the handle to a remote address and port (either IPv4 or IPv6).
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:94
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::Resource< SendReq, uv_udp_send_t >::data
void data(std::shared_ptr< void > uData)
Sets arbitrary data. uvw won't use this field in any case.
Definition: resource.hpp:60
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.