8000 Support more advanced UDP specific features in Sockets library · Issue #6 · Pagghiu/SaneCppLibraries · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Support more advanced UDP specific features in Sockets library #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Pagghiu opened this issue Jan 12, 2024 · 2 comments
Open

Support more advanced UDP specific features in Sockets library #6

Pagghiu opened this issue Jan 12, 2024 · 2 comments

Comments

@Pagghiu
Copy link
Owner
Pagghiu commented Jan 12, 2024

Sockets library only supports TCP so far and adding UDP support would be great 😀

@silent-tech
Copy link
Contributor

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;
};

@Pagghiu
Copy link
Owner Author
Pagghiu commented May 27, 2024

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:

  • The existence of this github issue, that I have created forgetting that basic UDP was already possible 😓
  • The lacking documentation
  • The lack of an explicit SocketServer::bind (it was done implicitly inside SocketServer::listen)
  • The lack of a test / example showing it

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".

@Pagghiu Pagghiu changed the title Support UDP in Sockets library Support more advanced UDP specific features in Sockets library May 27, 2024
@Pagghiu Pagghiu removed the good first issue Good for newcomers label May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants
0