Open Pagghiu opened 8 months ago
I am interested in this task, so I have already started to work on it :) Before I start to actually implement it, I would share with you the definition of the class.
/// @brief Provides User Datagram Protocol (UDP) network services.
///
/// The UdpClient class provides simple methods for sending and receiving connectionless UDP datagrams
/// in blocking synchronous mode. Because UDP is a connectionless transport protocol, you do not need
/// to establish a remote host connection prior to sending and receiving data.
/// You can create an instaince of the UdpSocket class and using the remote host address as a parameter:
/**
* @code{.cpp}
SocketDescriptor udpSocket;
UdpSocket udp(udpSocket);
// Write some data to the socket
char buf[1] = {testValue};
SC_TRY(udp.write(serverAddress, udpPort, {buf, sizeof(buf)}));
buf[0]++; // change the value and write again
SC_TRY(udp.write(serverAddress, udpPort, {buf, sizeof(buf)}));
// Close the socket
SC_TRY(udp.close());
@endcode
*/
/// Example of doing two synchronous reads:
/**
* @code{.cpp}
SocketDescriptor udpSocket;
UdpSocket udp(udpSocket, localPort);
SocketIPAddress remoteAddress;
// Read some data blocking until it's available
Span<char> readData;
SC_TRY(udp.read({buf, sizeof(buf)}, readData, remoteAddress));
SC_TRY(buf[0] == testValue and testValue != 0);
// Read again blocking but with a timeout of 10 seconds
SC_TRY(udp.readWithTimeout({buf, sizeof(buf)}, readData, remoteAddress, 10000_ms));
SC_TRY(buf[0] == testValue + 1);
// Close the client
SC_TRY(udp.close());
@endcode
*/
struct SC::UdpSocket
{
/// @brief Constructs a UdpSocket from a SocketDescriptor
/// @param socket A socket descriptor
UdpSocket(SocketDescriptor& socket);
/// @brief Constructs a UdpSocket from a SocketDescriptor and binds it to the local port number
/// @param socket A socket descriptor
/// @param port Local port number to bind
UdpSocket(SocketDescriptor& socket, uint16_t port);
/// @brief Calls SocketDescriptor::close
/// @return The Result of SocketDescriptor::close
[[nodiscard]] Result close();
/// @brief Sends a UDP datagram to a remote host at the specified remote address
/// @param ipAddress Remote IP address
/// @param data Bytes to write to this socket
/// @return Valid Result if bytes have been written successfully
[[nodiscard]] Result write(SocketIPAddress ipAddress, Span<const char> data);
/// @brief Sends a UDP datagram to a remote host at the specified remote host address and port
/// @param address Address as string
/// @param port Port on a specified remote host
/// @param data Bytes to write to this socket
/// @return Valid Result if bytes have been written successfully
[[nodiscard]] Result write(StringView address, uint16_t port, Span<const char> data);
/// @brief Reads a UDP datagram that was sent by a remote host
/// @param[in] data Span of memory pointing at a buffer that will receive the read data
/// @param[out] readData A sub-Span of `data` that has the length of actually read bytes
/// @param[out] ipAddress IP address of the sender host
/// @return Valid Result if bytes have been read successfully
[[nodiscard]] Result read(Span<char> data, Span<char>& readData, SocketIPAddress& ipAddress);
/// @brief Reads a UDP datagram that was sent by a remote host. Socket is blocked until they're actually received or
/// timeout occurs
/// @param[in] data Span of memory pointing at a buffer that will receive the read data
/// @param[out] readData A sub-Span of `data` that has the length of actually read bytes
/// @param[out] ipAddress IP address of the sender host
/// @param[in] timeout For how many milliseconds the read should wait before timing out
/// @return Valid Result if bytes have been read successfully and timeout didn't occur
[[nodiscard]] Result readWithTimeout(Span<char> data, Span<char>& readData, SocketIPAddress& ipAddress,
Time::Milliseconds timeout);
private:
SocketDescriptor& socket;
};
Hi @silent-tech,
The current SocketDescriptor / SocketServer / SocketClient classes should already allow handling basic connected UDP sockets, that I think is what you're trying to do looking at your header definition.
It probably wasn't clear because of:
I have been adding SocketServer::bind and a simple (connected) UDP socket test (see cf3034e). I've been using this occasion cleanup that library a little bit in a couple of additional commits, splitting it into more organized files and updating docs / refactoring/renaming a couple of methods.
If you need some more UDP specific features (like unconnected send, multicast addresses or similar additions) I suggest to create a SocketClientUDP
class deriving from SocketClient
to add the wanted functionality there (in an Internal/SocketClientUDP.inl
file), making them clearly not applicable to non-UDP sockets (like the regular TCP ones).
Regarding this issue we can maybe re-target it to add "more advanced UDP features".
Sockets library only supports TCP so far and adding UDP support would be great 😀