From 06595602f8c124f2b95019c06316632b70948820 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 4 Aug 2016 10:38:32 +0200 Subject: [PATCH] docs --- src/uvw/async.hpp | 2 +- src/uvw/check.hpp | 2 +- src/uvw/dns.hpp | 117 ++++++++++++++++++++++++++++ src/uvw/fs_event.hpp | 2 +- src/uvw/fs_poll.hpp | 2 +- src/uvw/idle.hpp | 2 +- src/uvw/pipe.hpp | 6 +- src/uvw/poll.hpp | 2 +- src/uvw/prepare.hpp | 2 +- src/uvw/process.hpp | 138 +++++++++++++++++++++++++++++++++ src/uvw/signal.hpp | 2 +- src/uvw/stream.hpp | 16 ++-- src/uvw/tcp.hpp | 114 ++++++++++++++++++++++++++++ src/uvw/timer.hpp | 2 +- src/uvw/udp.hpp | 177 ++++++++++++++++++++++++++++++++++++++++++- src/uvw/work.hpp | 32 ++++++++ 16 files changed, 597 insertions(+), 21 deletions(-) diff --git a/src/uvw/async.hpp b/src/uvw/async.hpp index db7c2ffc..0785a216 100644 --- a/src/uvw/async.hpp +++ b/src/uvw/async.hpp @@ -15,7 +15,7 @@ namespace uvw { /** * @brief AsyncEvent event. * - * It will be emitted by the AsyncHandle according with its functionalities. + * It will be emitted by AsyncHandle according with its functionalities. */ struct AsyncEvent: Event { }; diff --git a/src/uvw/check.hpp b/src/uvw/check.hpp index 2c9d084a..b9dbde52 100644 --- a/src/uvw/check.hpp +++ b/src/uvw/check.hpp @@ -15,7 +15,7 @@ namespace uvw { /** * @brief CheckEvent event. * - * It will be emitted by the CheckHandle according with its functionalities. + * It will be emitted by CheckHandle according with its functionalities. */ struct CheckEvent: Event { }; diff --git a/src/uvw/dns.hpp b/src/uvw/dns.hpp index 86d4abea..924754a7 100644 --- a/src/uvw/dns.hpp +++ b/src/uvw/dns.hpp @@ -13,11 +13,24 @@ namespace uvw { +/** + * @brief AddrInfoEvent event. + * + * It will be emitted by GetAddrInfoReq according with its functionalities. + */ struct AddrInfoEvent: Event { AddrInfoEvent(std::unique_ptr ptr) : dt{std::move(ptr)} { } + /** + * @brief Gets an instance of `addrinfo`. + * + * See [getaddrinfo](http://linux.die.net/man/3/getaddrinfo) for further + * details. + * + * @return An initialized instance of `addrinfo`. + */ addrinfo& data() const noexcept { return *dt; } private: @@ -25,12 +38,34 @@ private: }; +/** + * @brief NameInfoEvent event. + * + * It will be emitted by GetNameInfoReq according with its functionalities. + */ struct NameInfoEvent: Event { NameInfoEvent(const char *h, const char *s) : host{h}, serv{s} { } + /** + * @brief Gets the returned hostname. + * + * See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further + * details. + * + * @return A valid hostname. + */ const char* hostname() const noexcept { return host; } + + /** + * @brief Gets the returned service name. + * + * See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further + * details. + * + * @return A valid service name. + */ const char* service() const noexcept { return serv; } private: @@ -39,6 +74,12 @@ private: }; +/** + * @brief The GetAddrInfoReq request. + * + * Wrapper for [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
+ * It offers either asynchronous and synchronous access methods. + */ class GetAddrInfoReq final: public Request { static void getAddrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res) { auto ptr = reserve(reinterpret_cast(req)); @@ -67,37 +108,86 @@ class GetAddrInfoReq final: public Request { } public: + /** + * @brief Creates a new `getaddrinfo` wrapper request. + * @param args A pointer to the loop from which the handle generated. + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new GetAddrInfoReq{std::forward(args)...}}; } + /** + * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param node Either a numerical network address or a network hostname. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ void getNodeAddrInfo(std::string node, addrinfo *hints = nullptr) { getNodeAddrInfo(node.data(), nullptr, hints); } + /** + * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param node Either a numerical network address or a network hostname. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ auto getNodeAddrInfoSync(std::string node, addrinfo *hints = nullptr) { return getNodeAddrInfoSync(node.data(), nullptr, hints); } + /** + * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param service Either a service name or a port number as a string. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ void getServiceAddrInfo(std::string service, addrinfo *hints = nullptr) { getNodeAddrInfo(nullptr, service.data(), hints); } + /** + * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param service Either a service name or a port number as a string. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ auto getServiceAddrInfoSync(std::string service, addrinfo *hints = nullptr) { return getNodeAddrInfo(nullptr, service.data(), hints); } + /** + * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param node Either a numerical network address or a network hostname. + * @param service Either a service name or a port number as a string. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ void getAddrInfo(std::string node, std::string service, addrinfo *hints = nullptr) { getNodeAddrInfo(node.data(), service.data(), hints); } + /** + * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo). + * @param node Either a numerical network address or a network hostname. + * @param service Either a service name or a port number as a string. + * @param hints Optional `addrinfo` data structure with additional address + * type constraints. + */ auto getAddrInfoSync(std::string node, std::string service, addrinfo *hints = nullptr) { return getNodeAddrInfo(node.data(), service.data(), hints); } }; +/** + * @brief The GetNameInfoReq request. + * + * Wrapper for [getnameinfo](http://linux.die.net/man/3/getnameinfo).
+ * It offers either asynchronous and synchronous access methods. + */ class GetNameInfoReq final: public Request { static void getNameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) { auto ptr = reserve(reinterpret_cast(req)); @@ -111,11 +201,22 @@ public: using IPv4 = details::IPv4; using IPv6 = details::IPv6; + /** + * @brief Creates a new `getnameinfo` wrapper request. + * @param args A pointer to the loop from which the handle generated. + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new GetNameInfoReq{std::forward(args)...}}; } + /** + * @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo). + * @param ip A valid IP address. + * @param port A valid port number. + * @param flags Optional flags that modify the behavior of `getnameinfo`. + */ template void getNameInfo(std::string ip, unsigned int port, int flags = 0) { typename details::IpTraits::Type addr; @@ -123,11 +224,22 @@ public: invoke(&uv_getnameinfo, parent(), get(), &getNameInfoCallback, &addr, flags); } + /** + * @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo). + * @param addr A valid instance of Addr. + * @param flags Optional flags that modify the behavior of `getnameinfo`. + */ template void getNameInfo(Addr addr, int flags = 0) { getNameInfo(addr.ip, addr.port, flags); } + /** + * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo). + * @param ip A valid IP address. + * @param port A valid port number. + * @param flags Optional flags that modify the behavior of `getnameinfo`. + */ template auto getNameInfoSync(std::string ip, unsigned int port, int flags = 0) { typename details::IpTraits::Type addr; @@ -137,6 +249,11 @@ public: return std::make_pair(ErrorEvent{err}, NameInfoEvent{req->host, req->service}); } + /** + * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo). + * @param addr A valid instance of Addr. + * @param flags Optional flags that modify the behavior of `getnameinfo`. + */ template auto getNameInfoSync(Addr addr, int flags = 0) { getNameInfoSync(addr.ip, addr.port, flags); diff --git a/src/uvw/fs_event.hpp b/src/uvw/fs_event.hpp index 16903388..f25d715a 100644 --- a/src/uvw/fs_event.hpp +++ b/src/uvw/fs_event.hpp @@ -35,7 +35,7 @@ enum class UVFsEvent: std::underlying_type_t { /** * @brief FsEventEvent event. * - * It will be emitted by the FsEventHandle according with its functionalities. + * It will be emitted by FsEventHandle according with its functionalities. */ struct FsEventEvent: Event { FsEventEvent(std::string fPath, Flags f) diff --git a/src/uvw/fs_poll.hpp b/src/uvw/fs_poll.hpp index 94c7df61..bbe59ad9 100644 --- a/src/uvw/fs_poll.hpp +++ b/src/uvw/fs_poll.hpp @@ -16,7 +16,7 @@ namespace uvw { /** * @brief FsPollEvent event. * - * It will be emitted by the FsPollHandle according with its functionalities. + * It will be emitted by FsPollHandle according with its functionalities. */ struct FsPollEvent: Event { explicit FsPollEvent(const Stat &p, const Stat &c) noexcept diff --git a/src/uvw/idle.hpp b/src/uvw/idle.hpp index 5df93e7b..1ccc0c1c 100644 --- a/src/uvw/idle.hpp +++ b/src/uvw/idle.hpp @@ -15,7 +15,7 @@ namespace uvw { /** * @brief IdleEvent event. * - * It will be emitted by the IdleHandle according with its functionalities. + * It will be emitted by IdleHandle according with its functionalities. */ struct IdleEvent: Event { }; diff --git a/src/uvw/pipe.hpp b/src/uvw/pipe.hpp index 8c22cf87..0d9b3c2f 100644 --- a/src/uvw/pipe.hpp +++ b/src/uvw/pipe.hpp @@ -67,12 +67,12 @@ public: } /** - * @brief Opens an existing file descriptor or handle as a pipe. + * @brief Opens an existing file descriptor or HANDLE as a pipe. * - * The passed file descriptor or handle is not checked for its type, but + * The passed file descriptor or HANDLE is not checked for its type, but * it’s required that it represents a valid pipe. * - * @param file A valid file handle (either a file descriptor or a handle). + * @param file A valid file handle (either a file descriptor or a HANDLE). */ void open(FileHandle file) { invoke(&uv_pipe_open, get(), file); diff --git a/src/uvw/poll.hpp b/src/uvw/poll.hpp index dd71537d..968211f7 100644 --- a/src/uvw/poll.hpp +++ b/src/uvw/poll.hpp @@ -30,7 +30,7 @@ enum class UVPollEvent: std::underlying_type_t { /** * @brief PollEvent event. * - * It will be emitted by the PollHandle according with its functionalities. + * It will be emitted by PollHandle according with its functionalities. */ struct PollEvent: Event { explicit PollEvent(Flags f) noexcept diff --git a/src/uvw/prepare.hpp b/src/uvw/prepare.hpp index 42cfe2a3..ae384f0b 100644 --- a/src/uvw/prepare.hpp +++ b/src/uvw/prepare.hpp @@ -15,7 +15,7 @@ namespace uvw { /** * @brief PrepareEvent event. * - * It will be emitted by the PrepareHandle according with its functionalities. + * It will be emitted by PrepareHandle according with its functionalities. */ struct PrepareEvent: Event { }; diff --git a/src/uvw/process.hpp b/src/uvw/process.hpp index ea4fc9dc..783fa270 100644 --- a/src/uvw/process.hpp +++ b/src/uvw/process.hpp @@ -39,9 +39,20 @@ enum class UVStdIOFlags: std::underlying_type_t { } +/** + * @brief ExitEvent event. + * + * It will be emitted by ProcessHandle according with its functionalities. + */ struct ExitEvent: Event { }; +/** + * @brief The ProcessHandle handle. + * + * Process handles will spawn a new process and allow the user to control it and + * establish communication channels with it using streams. + */ class ProcessHandle final: public Handle { static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal) { ProcessHandle &process = *(static_cast(handle->data)); @@ -54,21 +65,64 @@ public: using Process = details::UVProcessFlags; using StdIO = details::UVStdIOFlags; + /** + * @brief Creates a new check handle. + * @param args A pointer to the loop from which the handle generated. + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new ProcessHandle{std::forward(args)...}}; } + /** + * @brief Disables inheritance for file descriptors/handles. + * + * Disables inheritance for file descriptors/handles that this process + * inherited from its parent. The effect is that child processes spawned by + * this process don’t accidentally inherit these handles.
+ * It is recommended to call this function as early in your program as + * possible, before the inherited file descriptors can be closed or + * duplicated. + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_disable_stdio_inheritance) + * for further details. + */ static void disableStdIOInheritance() noexcept { uv_disable_stdio_inheritance(); } + /** + * @brief kill Sends the specified signal to the given PID. + * @param pid A valid process id. + * @param signum A valid signal identifier. + * @return True in case of success, false otherwise. + */ static bool kill(int pid, int signum) noexcept { return (0 == uv_kill(pid, signum)); } + /** + * @brief Initializes the handle. + * @return True in case of success, false otherwise. + */ bool init() const noexcept { return true; } + /** + * @brief spawn Starts the process. + * + * If the process isn't successfully spawned, an ErrorEvent event will be + * emitted by the handle. + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/process.html) + * for further details. + * + * @param file Path pointing to the program to be executed.. + * @param args Command line arguments. + * @param env Optional environment for the new process. + */ void spawn(const char *file, char **args, char **env = nullptr) { uv_process_options_t po; @@ -88,24 +142,78 @@ public: invoke(&uv_spawn, parent(), get(), &po); } + /** + * @brief Sends the specified signal to the internal process handle. + * @param signum A valid signal identifier. + */ void kill(int signum) { invoke(&uv_process_kill, get(), signum); } + /** + * @brief Gets the PID of the spawned process. + * + * It’s set after calling `spawn()`. + * + * @return The PID of the spawned process. + */ int pid() noexcept { return get()->pid; } + /** + * @brief Sets the current working directory for the subprocess. + * @param path The working directory to be used when `spawn()` is invoked. + * @return A reference to this process handle. + */ ProcessHandle& cwd(std::string &path) noexcept { poCwd = path; return *this; } + /** + * @brief Sets flags that control how `spawn()` behaves. + * + * Available flags are: + * + * * ProcessHandle::Process::SETUID + * * ProcessHandle::Process::SETGID + * * ProcessHandle::Process::WINDOWS_VERBATIM_ARGUMENTS + * * ProcessHandle::Process::DETACHED + * * ProcessHandle::Process::WINDOWS_HIDE + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_process_flags) + * for further details. + * + * @param flags A valid set of flags. + * @return A reference to this process handle. + */ ProcessHandle& flags(Flags flags) noexcept { poFlags = flags; return *this; } + /** + * @brief Makes a `stdio` handle available to the child process. + * + * Available flags are: + * + * * ProcessHandle::StdIO::IGNORE + * * ProcessHandle::StdIO::CREATE_PIPE + * * ProcessHandle::StdIO::INHERIT_FD + * * ProcessHandle::StdIO::INHERIT_STREAM + * * ProcessHandle::StdIO::READABLE_PIPE + * * ProcessHandle::StdIO::WRITABLE_PIPE + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags) + * for further details. + * + * @param flags A valid set of flags. + * @param stream A valid `stdio` handle. + * @return A reference to this process handle. + */ template ProcessHandle& stdio(Flags flags, StreamHandle &stream) { uv_stdio_container_t container; @@ -116,6 +224,26 @@ public: return *this; } + /** + * @brief Makes a file descriptor available to the child process. + * + * Available flags are: + * + * * ProcessHandle::StdIO::IGNORE + * * ProcessHandle::StdIO::CREATE_PIPE + * * ProcessHandle::StdIO::INHERIT_FD + * * ProcessHandle::StdIO::INHERIT_STREAM + * * ProcessHandle::StdIO::READABLE_PIPE + * * ProcessHandle::StdIO::WRITABLE_PIPE + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/process.html#c.uv_stdio_flags) + * for further details. + * + * @param flags A valid set of flags. + * @param fd A valid file descriptor. + * @return A reference to this process handle. + */ template ProcessHandle& stdio(Flags flags, FileHandle fd) { uv_stdio_container_t container; @@ -126,11 +254,21 @@ public: return *this; } + /** + * @brief Sets the child process' user id. + * @param id A valid user id to be used. + * @return A reference to this process handle. + */ ProcessHandle& uid(Uid id) { poUid = id; return *this; } + /** + * @brief Sets the child process' group id. + * @param id A valid group id to be used. + * @return A reference to this process handle. + */ ProcessHandle& gid(Gid id) { poGid = id; return *this; diff --git a/src/uvw/signal.hpp b/src/uvw/signal.hpp index e3f5da29..79357f19 100644 --- a/src/uvw/signal.hpp +++ b/src/uvw/signal.hpp @@ -15,7 +15,7 @@ namespace uvw { /** * @brief SignalEvent event. * - * It will be emitted by the SignalHandle according with its functionalities. + * It will be emitted by SignalHandle according with its functionalities. */ struct SignalEvent: Event { explicit SignalEvent(int sig) noexcept: signum(sig) { } diff --git a/src/uvw/stream.hpp b/src/uvw/stream.hpp index 65db0007..36d04667 100644 --- a/src/uvw/stream.hpp +++ b/src/uvw/stream.hpp @@ -18,7 +18,7 @@ namespace uvw { /** * @brief ConnectEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct ConnectEvent: Event { }; @@ -26,7 +26,7 @@ struct ConnectEvent: Event { }; /** * @brief EndEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct EndEvent: Event { }; @@ -34,7 +34,7 @@ struct EndEvent: Event { }; /** * @brief ListenEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct ListenEvent: Event { }; @@ -42,7 +42,7 @@ struct ListenEvent: Event { }; /** * @brief ShutdownEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct ShutdownEvent: Event { }; @@ -50,7 +50,7 @@ struct ShutdownEvent: Event { }; /** * @brief WriteEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct WriteEvent: Event { }; @@ -58,7 +58,7 @@ struct WriteEvent: Event { }; /** * @brief DataEvent event. * - * It will be emitted by the StreamHandle according with its functionalities. + * It will be emitted by StreamHandle according with its functionalities. */ struct DataEvent: Event { explicit DataEvent(std::unique_ptr ptr, ssize_t l) noexcept @@ -257,7 +257,7 @@ public: * * Data are written in order.
* A WriteEvent event will be emitted when the data have been written.
- * An ErrorEvent wvent will be emitted in case of errors. + * An ErrorEvent event will be emitted in case of errors. * * @param data The data to be written to the stream. * @param len The lenght of the submitted data. @@ -315,7 +315,7 @@ public: * * @param data The data to be written to the stream. * @param len The lenght of the submitted data. - * @return Nomuber of bytes written. + * @return Number of bytes written. */ int tryWrite(std::unique_ptr data, ssize_t len) { uv_buf_t bufs[] = { uv_buf_init(data.get(), len) }; diff --git a/src/uvw/tcp.hpp b/src/uvw/tcp.hpp index e6975c83..06d2075c 100644 --- a/src/uvw/tcp.hpp +++ b/src/uvw/tcp.hpp @@ -27,6 +27,13 @@ enum class UVTcpFlags: std::underlying_type_t { } +/** + * @brief The TcpHandle handle. + * + * TCP handles are used to represent both TCP streams and servers.
+ * By default, _IPv4_ is used as a template parameter. The handle already + * supports _IPv6_ out-of-the-box by using `uvw::TcpHandle::IPv6`. + */ class TcpHandle final: public StreamHandle { explicit TcpHandle(std::shared_ptr ref) : StreamHandle{std::move(ref)}, tag{DEFAULT}, flags{} @@ -42,33 +49,97 @@ public: using IPv4 = details::IPv4; using IPv6 = details::IPv6; + /** + * @brief Creates a new tcp handle. + * @param args + * + * * A pointer to the loop from which the handle generated. + * * An optional integer value (_flags_) that indicates optional flags used + * to initialize the socket.
+ * See the official + * [documentation](http://docs.libuv.org/en/v1.x/tcp.html#c.uv_tcp_init_ex) + * for further details. + * + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new TcpHandle{std::forward(args)...}}; } + /** + * @brief Initializes the handle. No socket is created as of yet. + * @return True in case of success, false otherwise. + */ bool init() { return (tag == FLAGS) ? initialize(&uv_tcp_init_ex, flags) : initialize(&uv_tcp_init); } + /** + * @brief Opens an existing file descriptor or SOCKET as a TCP handle. + * + * The passed file descriptor or SOCKET is not checked for its type, but + * it’s required that it represents a valid stream socket. + * + * @param sock A valid socket handle (either a file descriptor or a SOCKET). + */ void open(OSSocketHandle sock) { invoke(&uv_tcp_open, get(), sock); } + /** + * @brief Enables/Disables Nagle’s algorithm. + * @param value True to enable it, false otherwise. + */ void noDelay(bool value = false) { invoke(&uv_tcp_nodelay, get(), value); } + /** + * @brief Enables/Disables TCP keep-alive. + * @param enable True to enable it, false otherwise. + * @param time Initial delay in seconds (use `std::chrono::seconds`). + */ void keepAlive(bool enable = false, Time time = Time{0}) { invoke(&uv_tcp_keepalive, get(), enable, time.count()); } + /** + * @brief Enables/Disables simultaneous asynchronous accept requests. + * + * Enables/Disables simultaneous asynchronous accept requests that are + * queued by the operating system when listening for new TCP + * connections.
+ * This setting is used to tune a TCP server for the desired performance. + * Having simultaneous accepts can significantly improve the rate of + * accepting connections (which is why it is enabled by default) but may + * lead to uneven load distribution in multi-process setups. + * + * @param enable True to enable it, false otherwise. + */ void simultaneousAccepts(bool enable = true) { invoke(&uv_tcp_simultaneous_accepts, get(), enable); } + /** + * @brief Binds the handle to an address and port. + * + * A successful call to this function does not guarantee that the call to + * `listen()` or `connect()` will work properly.
+ * `ErrorEvent` events can be emitted because of either this function or the + * ones mentioned above. + * + * Available flags are: + * + * * TcpHandle::Bind::IPV6ONLY: it disables dual-stack support and only IPv6 + * is used. + * + * @param ip The address to which to bind. + * @param port The port to which to bind. + * @param flags Optional additional flags. + */ template void bind(std::string ip, unsigned int port, Flags flags = Flags{}) { typename details::IpTraits::Type addr; @@ -76,21 +147,55 @@ public: invoke(&uv_tcp_bind, get(), reinterpret_cast(&addr), flags); } + /** + * @brief Binds the handle to an address and port. + * + * A successful call to this function does not guarantee that the call to + * `listen()` or `connect()` will work properly.
+ * `ErrorEvent` events can be emitted because of either this function or the + * ones mentioned above. + * + * Available flags are: + * + * * TcpHandle::Bind::IPV6ONLY: it disables dual-stack support and only IPv6 + * is used. + * + * @param addr A valid instance of Addr. + * @param flags Optional additional flags. + */ template void bind(Addr addr, Flags flags = Flags{}) { bind(addr.ip, addr.port, flags); } + /** + * @brief Gets the current address to which the handle is bound. + * @return A valid instance of Addr, an empty one in case of errors. + */ template Addr sock() const noexcept { return details::address(&uv_tcp_getsockname, get()); } + /** + * @brief Gets the address of the peer connected to the handle. + * @return A valid instance of Addr, an empty one in case of errors. + */ template Addr peer() const noexcept { return details::address(&uv_tcp_getpeername, get()); } + /** + * @brief Establishes an IPv4 or IPv6 TCP connection. + * + * A ConnectEvent event is emitted when the connection has been + * established.
+ * An ErrorEvent event is emitted in case of errors during the connection. + * + * @param ip The address to which to bind. + * @param port The port to which to bind. + */ template void connect(std::string ip, unsigned int port) { typename details::IpTraits::Type addr; @@ -106,6 +211,15 @@ public: connect->connect(&uv_tcp_connect, get(), reinterpret_cast(&addr)); } + /** + * @brief Establishes an IPv4 or IPv6 TCP connection. + * + * A ConnectEvent event is emitted when the connection has been + * established.
+ * An ErrorEvent event is emitted in case of errors during the connection. + * + * @param addr A valid instance of Addr. + */ template void connect(Addr addr) { connect(addr.ip, addr.port); diff --git a/src/uvw/timer.hpp b/src/uvw/timer.hpp index a2934413..4fd9cc0e 100644 --- a/src/uvw/timer.hpp +++ b/src/uvw/timer.hpp @@ -16,7 +16,7 @@ namespace uvw { /** * @brief TimerEvent event. * - * It will be emitted by the TimerHandle according with its functionalities. + * It will be emitted by TimerHandle according with its functionalities. */ struct TimerEvent: Event { }; diff --git a/src/uvw/udp.hpp b/src/uvw/udp.hpp index 1e3f2ee3..79d3937e 100644 --- a/src/uvw/udp.hpp +++ b/src/uvw/udp.hpp @@ -15,17 +15,46 @@ namespace uvw { +/** + * @brief SendEvent event. + * + * It will be emitted by UDPHandle according with its functionalities. + */ struct SendEvent: Event { }; +/** + * @brief UDPDataEvent event. + * + * It will be emitted by UDPHandle according with its functionalities. + */ struct UDPDataEvent: Event { explicit UDPDataEvent(Addr addr, std::unique_ptr ptr, ssize_t l, bool trunc) noexcept : dt{std::move(ptr)}, len{l}, sndr(addr), part{trunc} { } + /** + * @brief Gets the data read on the stream. + * @return A bunch of data read on the stream. + */ const char * data() const noexcept { return dt.get(); } + + /** + * @brief Gets the amount of data read on the stream. + * @return The amount of data read on the stream. + */ ssize_t length() const noexcept { return len; } + + /** + * @brief Gets the address of the sender. + * @return A valid instance of Addr. + */ Addr sender() const noexcept { return sndr; } + + /** + * @brief Indicates if the message was truncated. + * @return True if the message was truncated, false otherwise. + */ bool partial() const noexcept { return part; } private: @@ -69,6 +98,13 @@ public: } +/** + * @brief The UDPHandle handle. + * + * UDP handles encapsulate UDP communication for both clients and servers.
+ * By default, _IPv4_ is used as a template parameter. The handle already + * supports _IPv6_ out-of-the-box by using `uvw::UDPHandle::IPv6`. + */ class UDPHandle final: public Handle { template static void recvCallback(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf, const sockaddr *addr, unsigned flags) { @@ -107,21 +143,66 @@ public: using IPv4 = details::IPv4; using IPv6 = details::IPv6; + /** + * @brief Creates a new udp handle. + * @param args + * + * * A pointer to the loop from which the handle generated. + * * An optional integer value (_flags_) that indicates optional flags used + * to initialize the socket.
+ * See the official + * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_init_ex) + * for further details. + * + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new UDPHandle{std::forward(args)...}}; } + /** + * @brief Initializes the handle. The actual socket is created lazily. + * @return True in case of success, false otherwise. + */ bool init() { return (tag == FLAGS) ? initialize(&uv_udp_init_ex, flags) : initialize(&uv_udp_init); } + /** + * @brief Opens an existing file descriptor or SOCKET as a UDP handle. + * + * The passed file descriptor or SOCKET is not checked for its type, but + * it’s required that it represents a valid stream socket. + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_open) + * for further details. + * + * @param sock A valid socket handle (either a file descriptor or a SOCKET). + */ void open(OSSocketHandle sock) { invoke(&uv_udp_open, get(), sock); } + /** + * @brief Binds the UDP handle to an IP address and port. + * + * Available flags are: + * + * * UDPHandle::Bind::IPV6ONLY + * * UDPHandle::Bind::REUSEADDR + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags) + * for further details. + * + * @param ip The IP address to which to bind. + * @param port The port to which to bind. + * @param flags Optional additional flags. + */ template void bind(std::string ip, unsigned int port, Flags flags = Flags{}) { typename details::IpTraits::Type addr; @@ -129,42 +210,111 @@ public: invoke(&uv_udp_bind, get(), reinterpret_cast(&addr), flags); } + /** + * @brief Binds the UDP handle to an IP address and port. + * + * Available flags are: + * + * * UDPHandle::Bind::IPV6ONLY + * * UDPHandle::Bind::REUSEADDR + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/udp.html#c.uv_udp_flags) + * for further details. + * + * @param addr A valid instance of Addr. + * @param flags Optional additional flags. + */ template void bind(Addr addr, Flags flags = Flags{}) { bind(addr.ip, addr.port, flags); } + /** + * @brief Get the local IP and port of the UDP handle. + * @return A valid instance of Addr, an empty one in case of errors. + */ template Addr sock() const noexcept { return details::address(&uv_udp_getsockname, get()); } + /** + * @brief Sets membership for a multicast address. + * + * Available values for `membership` are: + * + * * UDPHandle::Membership::LEAVE_GROUP + * * UDPHandle::Membership::JOIN_GROUP + * + * @param multicast Multicast address to set membership for. + * @param interface Interface address. + * @param membership Action to be performed. + */ template void multicastMembership(std::string multicast, std::string interface, Membership membership) { invoke(&uv_udp_set_membership, get(), multicast.data(), interface.data(), static_cast(membership)); } + /** + * @brief Sets IP multicast loop flag. + * + * This makes multicast packets loop back to local sockets. + * + * @param enable True to enable multicast loop, false otherwise. + */ void multicastLoop(bool enable = true) { invoke(&uv_udp_set_multicast_loop, get(), enable); } - void multicastTttl(int val) { + /** + * @brief Sets the multicast ttl. + * @param val A value in the range `[1, 255]`. + */ + void multicastTtl(int val) { invoke(&uv_udp_set_multicast_ttl, get(), val > 255 ? 255 : val); } + /** + * @brief Sets the multicast interface to send or receive data on. + * @param interface Interface address. + */ template void multicastInterface(std::string interface) { invoke(&uv_udp_set_multicast_interface, get(), interface.data()); } + /** + * @brief Sets broadcast on or off. + * @param enable True to set broadcast on, false otherwise. + */ void broadcast(bool enable = false) { invoke(&uv_udp_set_broadcast, get(), enable); } + /** + * @brief Sets the time to live. + * @param val A value in the range `[1, 255]`. + */ void ttl(int val) { invoke(&uv_udp_set_ttl, get(), val > 255 ? 255 : val); } + /** + * @brief Sends data over the UDP socket. + * + * Note that if the socket has not previously been bound with `bind()`, it + * will be bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a + * random port number. + * + * A SendEvent event will be emitted when the data have been sent.
+ * An ErrorEvent event will be emitted in case of errors. + * + * @param ip The address to which to send data. + * @param port The port to which to send data. + * @param data The data to be sent. + * @param len The lenght of the submitted data. + */ template void send(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { typename details::IpTraits::Type addr; @@ -182,6 +332,18 @@ public: send->send(get(), bufs, 1, reinterpret_cast(&addr)); } + /** + * @brief Sends data over the UDP socket. + * + * Same as `send()`, but it won’t queue a send request if it can’t be + * completed immediately. + * + * @param ip The address to which to send data. + * @param port The port to which to send data. + * @param data The data to be sent. + * @param len The lenght of the submitted data. + * @return Number of bytes written. + */ template int trySend(std::string ip, unsigned int port, std::unique_ptr data, ssize_t len) { typename details::IpTraits::Type addr; @@ -198,11 +360,24 @@ public: return bw; } + /** + * @brief Prepares for receiving data. + * + * Note that if the socket has not previously been bound with `bind()`, it + * is bound to `0.0.0.0` (the _all interfaces_ IPv4 address) and a random + * port number. + * + * An UDPDataEvent event will be emitted when the handle receives data.
+ * An ErrorEvent event will be emitted in case of errors. + */ template void recv() { invoke(&uv_udp_recv_start, get(), &allocCallback, &recvCallback); } + /** + * @brief Stops listening for incoming datagrams. + */ void stop() { invoke(&uv_udp_recv_stop, get()); } diff --git a/src/uvw/work.hpp b/src/uvw/work.hpp index f1c5b242..d96a5263 100644 --- a/src/uvw/work.hpp +++ b/src/uvw/work.hpp @@ -13,9 +13,24 @@ namespace uvw { +/** + * @brief WorkEvent event. + * + * It will be emitted by WorkReq according with its functionalities. + */ struct WorkEvent: Event { }; +/** + * @brief The WorkReq request. + * + * It runs user code using a thread from the threadpool and gets notified in the + * loop thread by means of an event. + * + * See the official + * [documentation](http://docs.libuv.org/en/v1.x/threadpool.html) + * for further details. + */ class WorkReq final: public Request { using InternalTask = std::function; @@ -30,11 +45,28 @@ class WorkReq final: public Request { public: using Task = InternalTask; + /** + * @brief Creates a new work request. + * @param args + * + * * A pointer to the loop from which the handle generated. + * * A valid instance of a `Task`, that is of type + * `std::function`. + * + * @return A pointer to the newly created handle. + */ template static std::shared_ptr create(Args&&... args) { return std::shared_ptr{new WorkReq{std::forward(args)...}}; } + /** + * @brief Runs the given task in a separate thread. + * + * A WorkEvent event will be emitted on the loop thread when the task is + * finished.
+ * This request can be cancelled with `cancel()`. + */ void queue() { invoke(&uv_queue_work, parent(), get(), &workCallback, &defaultCallback); }