WPILibC++ 2024.3.2
Udp.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#ifndef WPINET_UV_UDP_H_
6#define WPINET_UV_UDP_H_
7
8#include <uv.h>
9
10#include <functional>
11#include <memory>
12#include <span>
13#include <string_view>
14#include <utility>
15
16#include <wpi/Signal.h>
17
18#include "wpinet/uv/Handle.h"
19#include "wpinet/uv/Request.h"
20
21namespace wpi::uv {
22
23class Loop;
24class Udp;
25
26/**
27 * UDP send request.
28 */
29class UdpSendReq : public RequestImpl<UdpSendReq, uv_udp_send_t> {
30 public:
32
33 Udp& GetUdp() const { return *static_cast<Udp*>(GetRaw()->handle->data); }
34
35 /**
36 * Send completed signal. This is called even if an error occurred.
37 * @param err error value
38 */
40};
41
42/**
43 * UDP handle.
44 * UDP handles encapsulate UDP communication for both clients and servers.
45 */
46class Udp final : public HandleImpl<Udp, uv_udp_t> {
47 struct private_init {};
48
49 public:
50 explicit Udp(const private_init&) {}
51 ~Udp() noexcept override = default;
52
53 /**
54 * Create a UDP handle.
55 *
56 * @param loop Loop object where this handle runs.
57 * @param flags Flags
58 */
59 static std::shared_ptr<Udp> Create(Loop& loop,
60 unsigned int flags = AF_UNSPEC);
61
62 /**
63 * Create a UDP handle.
64 *
65 * @param loop Loop object where this handle runs.
66 * @param flags Flags
67 */
68 static std::shared_ptr<Udp> Create(const std::shared_ptr<Loop>& loop,
69 unsigned int flags = AF_UNSPEC) {
70 return Create(*loop, flags);
71 }
72
73 /**
74 * Open an existing file descriptor or SOCKET as a UDP handle.
75 *
76 * @param sock A valid socket handle (either a file descriptor or a SOCKET).
77 */
78 void Open(uv_os_sock_t sock) { Invoke(&uv_udp_open, GetRaw(), sock); }
79
80 /**
81 * Bind the handle to an IPv4 or IPv6 address and port.
82 *
83 * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
84 * @param flags Optional additional flags.
85 */
86 void Bind(const sockaddr& addr, unsigned int flags = 0) {
87 Invoke(&uv_udp_bind, GetRaw(), &addr, flags);
88 }
89
90 void Bind(const sockaddr_in& addr, unsigned int flags = 0) {
91 Bind(reinterpret_cast<const sockaddr&>(addr), flags);
92 }
93
94 void Bind(const sockaddr_in6& addr, unsigned int flags = 0) {
95 Bind(reinterpret_cast<const sockaddr&>(addr), flags);
96 }
97
98 /**
99 * Bind the handle to an IPv4 address and port.
100 *
101 * @param ip The address to which to bind.
102 * @param port The port to which to bind.
103 * @param flags Optional additional flags.
104 */
105 void Bind(std::string_view ip, unsigned int port, unsigned int flags = 0);
106
107 /**
108 * Bind the handle to an IPv6 address and port.
109 *
110 * @param ip The address to which to bind.
111 * @param port The port to which to bind.
112 * @param flags Optional additional flags.
113 */
114 void Bind6(std::string_view ip, unsigned int port, unsigned int flags = 0);
115
116 /**
117 * Associate the handle to a remote address and port, so every message sent
118 * by this handle is automatically sent to that destination.
119 *
120 * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
121 */
122 void Connect(const sockaddr& addr) {
123 Invoke(&uv_udp_connect, GetRaw(), &addr);
124 }
125
126 void Connect(const sockaddr_in& addr) {
127 Connect(reinterpret_cast<const sockaddr&>(addr));
128 }
129
130 void Connect(const sockaddr_in6& addr) {
131 Connect(reinterpret_cast<const sockaddr&>(addr));
132 }
133
134 /**
135 * Associate the handle to an IPv4 address and port, so every message sent
136 * by this handle is automatically sent to that destination.
137 *
138 * @param ip The address to which to bind.
139 * @param port The port to which to bind.
140 */
141 void Connect(std::string_view ip, unsigned int port);
142
143 /**
144 * Associate the handle to an IPv6 address and port, so every message sent
145 * by this handle is automatically sent to that destination.
146 *
147 * @param ip The address to which to bind.
148 * @param port The port to which to bind.
149 * @param flags Optional additional flags.
150 */
151 void Connect6(std::string_view ip, unsigned int port);
152
153 /**
154 * Get the remote IP and port on connected UDP handles.
155 * @return The address (will be zeroed if an error occurred).
156 */
157 sockaddr_storage GetPeer();
158
159 /**
160 * Get the current address to which the handle is bound.
161 * @return The address (will be zeroed if an error occurred).
162 */
163 sockaddr_storage GetSock();
164
165 /**
166 * Set membership for a multicast address.
167 *
168 * @param multicastAddr Multicast address to set membership for
169 * @param interfaceAddr Interface address
170 * @param membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP
171 */
172 void SetMembership(std::string_view multicastAddr,
173 std::string_view interfaceAddr, uv_membership membership);
174
175 /**
176 * Set membership for a source-specific multicast group.
177 *
178 * @param multicastAddr Multicast address to set membership for
179 * @param interfaceAddr Interface address
180 * @param sourceAddr Source address
181 * @param membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP
182 */
184 std::string_view interfaceAddr,
185 std::string_view sourceAddr,
186 uv_membership membership);
187
188 /**
189 * Set IP multicast loop flag. Makes multicast packets loop back to local
190 * sockets.
191 *
192 * @param enabled True for enabled, false for disabled
193 */
194 void SetMulticastLoop(bool enabled) {
195 Invoke(&uv_udp_set_multicast_loop, GetRaw(), enabled ? 1 : 0);
196 }
197
198 /**
199 * Set the multicast TTL.
200 *
201 * @param ttl Time to live (1-255)
202 */
203 void SetMulticastTtl(int ttl) {
205 }
206
207 /**
208 * Set the multicast interface to send or receive data on.
209 *
210 * @param interfaceAddr Interface address
211 */
213
214 /**
215 * Set broadcast on or off.
216 *
217 * @param enabled True for enabled, false for disabled
218 */
219 void SetBroadcast(bool enabled) {
220 Invoke(&uv_udp_set_broadcast, GetRaw(), enabled ? 1 : 0);
221 }
222
223 /**
224 * Set the time to live (TTL).
225 *
226 * @param ttl Time to live (1-255)
227 */
228 void SetTtl(int ttl) { Invoke(&uv_udp_set_ttl, GetRaw(), ttl); }
229
230 /**
231 * Send data over the UDP socket. If the socket has not previously been bound
232 * with Bind() it will be bound to 0.0.0.0 (the "all interfaces" IPv4 address)
233 * and a random port number.
234 *
235 * Data are written in order. The lifetime of the data pointers passed in
236 * the `bufs` parameter must exceed the lifetime of the send request.
237 * The callback can be used to free data after the request completes.
238 *
239 * HandleSendComplete() will be called on the request object when the data
240 * has been written. HandleSendComplete() is called even if an error occurs.
241 * HandleError() will be called on the request object in case of errors.
242 *
243 * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
244 * remote peer.
245 * @param bufs The buffers to be written to the stream.
246 * @param req write request
247 */
248 void Send(const sockaddr& addr, std::span<const Buffer> bufs,
249 const std::shared_ptr<UdpSendReq>& req);
250
251 void Send(const sockaddr_in& addr, std::span<const Buffer> bufs,
252 const std::shared_ptr<UdpSendReq>& req) {
253 Send(reinterpret_cast<const sockaddr&>(addr), bufs, req);
254 }
255
256 void Send(const sockaddr_in6& addr, std::span<const Buffer> bufs,
257 const std::shared_ptr<UdpSendReq>& req) {
258 Send(reinterpret_cast<const sockaddr&>(addr), bufs, req);
259 }
260
261 /**
262 * Variant of Send() for connected sockets. Cannot be used with
263 * connectionless sockets.
264 *
265 * @param bufs The buffers to be written to the stream.
266 * @param req write request
267 */
268 void Send(std::span<const Buffer> bufs,
269 const std::shared_ptr<UdpSendReq>& req);
270
271 /**
272 * Send data over the UDP socket. If the socket has not previously been bound
273 * with Bind() it will be bound to 0.0.0.0 (the "all interfaces" IPv4 address)
274 * and a random port number.
275 *
276 * Data are written in order. The lifetime of the data pointers passed in
277 * the `bufs` parameter must exceed the lifetime of the send request.
278 * The callback can be used to free data after the request completes.
279 *
280 * The callback will be called when the data has been sent. Errors will
281 * be reported via the error signal.
282 *
283 * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
284 * remote peer.
285 * @param bufs The buffers to be sent.
286 * @param callback Callback function to call when the data has been sent.
287 */
288 void Send(const sockaddr& addr, std::span<const Buffer> bufs,
289 std::function<void(std::span<Buffer>, Error)> callback);
290
291 void Send(const sockaddr_in& addr, std::span<const Buffer> bufs,
292 std::function<void(std::span<Buffer>, Error)> callback) {
293 Send(reinterpret_cast<const sockaddr&>(addr), bufs, std::move(callback));
294 }
295
296 void Send(const sockaddr_in6& addr, std::span<const Buffer> bufs,
297 std::function<void(std::span<Buffer>, Error)> callback) {
298 Send(reinterpret_cast<const sockaddr&>(addr), bufs, std::move(callback));
299 }
300
301 /**
302 * Variant of Send() for connected sockets. Cannot be used with
303 * connectionless sockets.
304 *
305 * @param bufs The buffers to be written to the stream.
306 * @param callback Callback function to call when the data has been sent.
307 */
308 void Send(std::span<const Buffer> bufs,
309 std::function<void(std::span<Buffer>, Error)> callback);
310
311 /**
312 * Same as Send(), but won't queue a send request if it can't be completed
313 * immediately.
314 *
315 * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
316 * remote peer.
317 * @param bufs The buffers to be send.
318 * @return Number of bytes sent.
319 */
320 int TrySend(const sockaddr& addr, std::span<const Buffer> bufs) {
321 int val = uv_udp_try_send(GetRaw(), bufs.data(),
322 static_cast<unsigned>(bufs.size()), &addr);
323 if (val < 0) {
324 this->ReportError(val);
325 return 0;
326 }
327 return val;
328 }
329
330 int TrySend(const sockaddr_in& addr, std::span<const Buffer> bufs) {
331 return TrySend(reinterpret_cast<const sockaddr&>(addr), bufs);
332 }
333
334 int TrySend(const sockaddr_in6& addr, std::span<const Buffer> bufs) {
335 return TrySend(reinterpret_cast<const sockaddr&>(addr), bufs);
336 }
337
338 /**
339 * Variant of TrySend() for connected sockets. Cannot be used with
340 * connectionless sockets.
341 *
342 * @param bufs The buffers to be written to the stream.
343 * @return Number of bytes sent.
344 */
345 int TrySend(std::span<const Buffer> bufs) {
346 int val = uv_udp_try_send(GetRaw(), bufs.data(),
347 static_cast<unsigned>(bufs.size()), nullptr);
348 if (val < 0) {
349 this->ReportError(val);
350 return 0;
351 }
352 return val;
353 }
354
355 /**
356 * Prepare for receiving data. If the socket has not previously been bound
357 * with Bind() it is bound to 0.0.0.0 (the "all interfaces" IPv4 address) and
358 * a random port number.
359 *
360 * A received signal will be emitted for each received data packet until
361 * `StopRecv()` is called.
362 */
363 void StartRecv();
364
365 /**
366 * Stop listening for incoming datagrams.
367 */
369
370 /**
371 * Returns true if the UDP handle was created with the UV_UDP_RECVMMSG flag
372 * and the platform supports recvmmsg(2), false otherwise.
373 * @return True if the UDP handle is using recvmmsg.
374 */
375 bool IsUsingRecvmmsg() const { return uv_udp_using_recvmmsg(GetRaw()); }
376
377 /**
378 * Gets the amount of queued bytes waiting to be sent.
379 * @return Amount of queued bytes waiting to be sent.
380 */
381 size_t GetSendQueueSize() const noexcept { return GetRaw()->send_queue_size; }
382
383 /**
384 * Gets the amount of queued packets waiting to be sent.
385 * @return Amount of queued packets waiting to be sent.
386 */
387 size_t GetSendQueueCount() const noexcept {
388 return GetRaw()->send_queue_count;
389 }
390
391 /**
392 * Signal generated for each incoming datagram. Parameters are the buffer,
393 * the number of bytes received, the address of the sender, and flags.
394 */
396};
397
398} // namespace wpi::uv
399
400#endif // WPINET_UV_UDP_H_
SignalBase is an implementation of the observer pattern, through the use of an emitting object and sl...
Definition: Signal.h:495
Error code.
Definition: Error.h:15
void ReportError(int err) const
Report an error.
Definition: Handle.h:252
bool Invoke(F &&f, Args &&... args) const
Definition: Handle.h:267
Handle.
Definition: Handle.h:290
uv_udp_t * GetRaw() const noexcept
Get the underlying handle data structure.
Definition: Handle.h:305
Event loop.
Definition: Loop.h:37
Request.
Definition: Request.h:135
uv_udp_send_t * GetRaw() noexcept
Get the underlying request data structure.
Definition: Request.h:150
UDP handle.
Definition: Udp.h:46
void SetSourceMembership(std::string_view multicastAddr, std::string_view interfaceAddr, std::string_view sourceAddr, uv_membership membership)
Set membership for a source-specific multicast group.
sockaddr_storage GetPeer()
Get the remote IP and port on connected UDP handles.
void Open(uv_os_sock_t sock)
Open an existing file descriptor or SOCKET as a UDP handle.
Definition: Udp.h:78
int TrySend(const sockaddr_in6 &addr, std::span< const Buffer > bufs)
Definition: Udp.h:334
void Bind(std::string_view ip, unsigned int port, unsigned int flags=0)
Bind the handle to an IPv4 address and port.
sig::Signal< Buffer &, size_t, const sockaddr &, unsigned > received
Signal generated for each incoming datagram.
Definition: Udp.h:395
void Send(const sockaddr_in &addr, std::span< const Buffer > bufs, const std::shared_ptr< UdpSendReq > &req)
Definition: Udp.h:251
void SetBroadcast(bool enabled)
Set broadcast on or off.
Definition: Udp.h:219
void Connect6(std::string_view ip, unsigned int port)
Associate the handle to an IPv6 address and port, so every message sent by this handle is automatical...
void Bind(const sockaddr_in6 &addr, unsigned int flags=0)
Definition: Udp.h:94
sockaddr_storage GetSock()
Get the current address to which the handle is bound.
Udp(const private_init &)
Definition: Udp.h:50
void Bind(const sockaddr &addr, unsigned int flags=0)
Bind the handle to an IPv4 or IPv6 address and port.
Definition: Udp.h:86
size_t GetSendQueueCount() const noexcept
Gets the amount of queued packets waiting to be sent.
Definition: Udp.h:387
bool IsUsingRecvmmsg() const
Returns true if the UDP handle was created with the UV_UDP_RECVMMSG flag and the platform supports re...
Definition: Udp.h:375
void SetMulticastLoop(bool enabled)
Set IP multicast loop flag.
Definition: Udp.h:194
void Bind(const sockaddr_in &addr, unsigned int flags=0)
Definition: Udp.h:90
void Bind6(std::string_view ip, unsigned int port, unsigned int flags=0)
Bind the handle to an IPv6 address and port.
size_t GetSendQueueSize() const noexcept
Gets the amount of queued bytes waiting to be sent.
Definition: Udp.h:381
void Send(std::span< const Buffer > bufs, const std::shared_ptr< UdpSendReq > &req)
Variant of Send() for connected sockets.
void SetMembership(std::string_view multicastAddr, std::string_view interfaceAddr, uv_membership membership)
Set membership for a multicast address.
void SetTtl(int ttl)
Set the time to live (TTL).
Definition: Udp.h:228
void Send(const sockaddr &addr, std::span< const Buffer > bufs, std::function< void(std::span< Buffer >, Error)> callback)
Send data over the UDP socket.
int TrySend(const sockaddr_in &addr, std::span< const Buffer > bufs)
Definition: Udp.h:330
int TrySend(std::span< const Buffer > bufs)
Variant of TrySend() for connected sockets.
Definition: Udp.h:345
void Send(std::span< const Buffer > bufs, std::function< void(std::span< Buffer >, Error)> callback)
Variant of Send() for connected sockets.
void Connect(std::string_view ip, unsigned int port)
Associate the handle to an IPv4 address and port, so every message sent by this handle is automatical...
int TrySend(const sockaddr &addr, std::span< const Buffer > bufs)
Same as Send(), but won't queue a send request if it can't be completed immediately.
Definition: Udp.h:320
void Send(const sockaddr_in &addr, std::span< const Buffer > bufs, std::function< void(std::span< Buffer >, Error)> callback)
Definition: Udp.h:291
void Connect(const sockaddr &addr)
Associate the handle to a remote address and port, so every message sent by this handle is automatica...
Definition: Udp.h:122
void Send(const sockaddr &addr, std::span< const Buffer > bufs, const std::shared_ptr< UdpSendReq > &req)
Send data over the UDP socket.
void Send(const sockaddr_in6 &addr, std::span< const Buffer > bufs, std::function< void(std::span< Buffer >, Error)> callback)
Definition: Udp.h:296
void SetMulticastTtl(int ttl)
Set the multicast TTL.
Definition: Udp.h:203
void StartRecv()
Prepare for receiving data.
void Connect(const sockaddr_in &addr)
Definition: Udp.h:126
~Udp() noexcept override=default
void StopRecv()
Stop listening for incoming datagrams.
Definition: Udp.h:368
void Connect(const sockaddr_in6 &addr)
Definition: Udp.h:130
void Send(const sockaddr_in6 &addr, std::span< const Buffer > bufs, const std::shared_ptr< UdpSendReq > &req)
Definition: Udp.h:256
void SetMulticastInterface(std::string_view interfaceAddr)
Set the multicast interface to send or receive data on.
static std::shared_ptr< Udp > Create(Loop &loop, unsigned int flags=AF_UNSPEC)
Create a UDP handle.
UDP send request.
Definition: Udp.h:29
Udp & GetUdp() const
Definition: Udp.h:33
sig::Signal< Error > complete
Send completed signal.
Definition: Udp.h:39
basic_string_view< char > string_view
Definition: core.h:501
Definition: array.h:89
Definition: WebSocket.h:27
size_t send_queue_count
Definition: uv.h:696
UV_HANDLE_FIELDS size_t send_queue_size
Definition: uv.h:692
UV_REQ_FIELDS uv_udp_t * handle
Definition: uv.h:703
flags
Definition: http_parser.h:206
int uv_os_sock_t
Definition: unix.h:118
UV_EXTERN int uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, unsigned int flags)
UV_EXTERN int uv_udp_set_ttl(uv_udp_t *handle, int ttl)
UV_EXTERN int uv_udp_recv_stop(uv_udp_t *handle)
uv_membership
Definition: uv.h:412
UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t *handle, int ttl)
UV_EXTERN int uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock)
UV_EXTERN int uv_udp_try_send(uv_udp_t *handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr *addr)
UV_EXTERN int uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr)
UV_EXTERN int uv_udp_using_recvmmsg(const uv_udp_t *handle)
UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t *handle, int on)
UV_EXTERN int uv_udp_set_broadcast(uv_udp_t *handle, int on)