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