Merge pull request #46 from cynnyx/master

docs
This commit is contained in:
Michele Caini 2016-08-04 14:27:30 +02:00 committed by GitHub
commit 805b8e5b0e
16 changed files with 597 additions and 21 deletions

View File

@ -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<AsyncEvent> { };

View File

@ -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<CheckEvent> { };

View File

@ -13,11 +13,24 @@
namespace uvw {
/**
* @brief AddrInfoEvent event.
*
* It will be emitted by GetAddrInfoReq according with its functionalities.
*/
struct AddrInfoEvent: Event<AddrInfoEvent> {
AddrInfoEvent(std::unique_ptr<addrinfo, void(*)(addrinfo *)> 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> {
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).<br/>
* It offers either asynchronous and synchronous access methods.
*/
class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
static void getAddrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(req));
@ -67,37 +108,86 @@ class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
}
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<typename... Args>
static std::shared_ptr<GetAddrInfoReq> create(Args&&... args) {
return std::shared_ptr<GetAddrInfoReq>{new GetAddrInfoReq{std::forward<Args>(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).<br/>
* It offers either asynchronous and synchronous access methods.
*/
class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
static void getNameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
auto ptr = reserve(reinterpret_cast<uv_req_t*>(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<typename... Args>
static std::shared_ptr<GetNameInfoReq> create(Args&&... args) {
return std::shared_ptr<GetNameInfoReq>{new GetNameInfoReq{std::forward<Args>(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<typename I = IPv4>
void getNameInfo(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::Type addr;
@ -123,11 +224,22 @@ public:
invoke(&uv_getnameinfo, parent(), get<uv_getnameinfo_t>(), &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<typename I = IPv4>
void getNameInfo(Addr addr, int flags = 0) {
getNameInfo<I>(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<typename I = IPv4>
auto getNameInfoSync(std::string ip, unsigned int port, int flags = 0) {
typename details::IpTraits<I>::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<typename I = IPv4>
auto getNameInfoSync(Addr addr, int flags = 0) {
getNameInfoSync<I>(addr.ip, addr.port, flags);

View File

@ -35,7 +35,7 @@ enum class UVFsEvent: std::underlying_type_t<uv_fs_event> {
/**
* @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> {
FsEventEvent(std::string fPath, Flags<details::UVFsEvent> f)

View File

@ -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<FsPollEvent> {
explicit FsPollEvent(const Stat &p, const Stat &c) noexcept

View File

@ -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<IdleEvent> { };

View File

@ -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
* its 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<uv_pipe_t>(), file);

View File

@ -30,7 +30,7 @@ enum class UVPollEvent: std::underlying_type_t<uv_poll_event> {
/**
* @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<PollEvent> {
explicit PollEvent(Flags<details::UVPollEvent> f) noexcept

View File

@ -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<PrepareEvent> { };

View File

@ -39,9 +39,20 @@ enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
}
/**
* @brief ExitEvent event.
*
* It will be emitted by ProcessHandle according with its functionalities.
*/
struct ExitEvent: Event<ExitEvent> { };
/**
* @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<ProcessHandle, uv_process_t> {
static void exitCallback(uv_process_t *handle, int64_t exitStatus, int termSignal) {
ProcessHandle &process = *(static_cast<ProcessHandle*>(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<typename... Args>
static std::shared_ptr<ProcessHandle> create(Args&&... args) {
return std::shared_ptr<ProcessHandle>{new ProcessHandle{std::forward<Args>(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 dont accidentally inherit these handles.<br/>
* 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<uv_process_t>(), &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<uv_process_t>(), signum);
}
/**
* @brief Gets the PID of the spawned process.
*
* Its set after calling `spawn()`.
*
* @return The PID of the spawned process.
*/
int pid() noexcept {
return get<uv_process_t>()->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<Process> 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<typename T, typename U>
ProcessHandle& stdio(Flags<StdIO> flags, StreamHandle<T, U> &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<typename T>
ProcessHandle& stdio(Flags<StdIO> 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;

View File

@ -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<SignalEvent> {
explicit SignalEvent(int sig) noexcept: signum(sig) { }

View File

@ -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<ConnectEvent> { };
@ -26,7 +26,7 @@ struct ConnectEvent: Event<ConnectEvent> { };
/**
* @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<EndEvent> { };
@ -34,7 +34,7 @@ struct EndEvent: Event<EndEvent> { };
/**
* @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<ListenEvent> { };
@ -42,7 +42,7 @@ struct ListenEvent: Event<ListenEvent> { };
/**
* @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<ShutdownEvent> { };
@ -50,7 +50,7 @@ struct ShutdownEvent: Event<ShutdownEvent> { };
/**
* @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<WriteEvent> { };
@ -58,7 +58,7 @@ struct WriteEvent: Event<WriteEvent> { };
/**
* @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<DataEvent> {
explicit DataEvent(std::unique_ptr<const char[]> ptr, ssize_t l) noexcept
@ -257,7 +257,7 @@ public:
*
* Data are written in order.<br/>
* A WriteEvent event will be emitted when the data have been written.<br/>
* 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<char[]> data, ssize_t len) {
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };

View File

@ -27,6 +27,13 @@ enum class UVTcpFlags: std::underlying_type_t<uv_tcp_flags> {
}
/**
* @brief The TcpHandle handle.
*
* TCP handles are used to represent both TCP streams and servers.<br/>
* 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<TcpHandle, uv_tcp_t> {
explicit TcpHandle(std::shared_ptr<Loop> 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.<br/>
* 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<typename... Args>
static std::shared_ptr<TcpHandle> create(Args&&... args) {
return std::shared_ptr<TcpHandle>{new TcpHandle{std::forward<Args>(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_t>(&uv_tcp_init_ex, flags)
: initialize<uv_tcp_t>(&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
* its 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<uv_tcp_t>(), sock);
}
/**
* @brief Enables/Disables Nagles algorithm.
* @param value True to enable it, false otherwise.
*/
void noDelay(bool value = false) {
invoke(&uv_tcp_nodelay, get<uv_tcp_t>(), 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<uv_tcp_t>(), 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.<br/>
* 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<uv_tcp_t>(), 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.<br/>
* `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<typename I = IPv4>
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
typename details::IpTraits<I>::Type addr;
@ -76,21 +147,55 @@ public:
invoke(&uv_tcp_bind, get<uv_tcp_t>(), reinterpret_cast<const sockaddr *>(&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.<br/>
* `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<typename I = IPv4>
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
bind<I>(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<typename I = IPv4>
Addr sock() const noexcept {
return details::address<I>(&uv_tcp_getsockname, get<uv_tcp_t>());
}
/**
* @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<typename I = IPv4>
Addr peer() const noexcept {
return details::address<I>(&uv_tcp_getpeername, get<uv_tcp_t>());
}
/**
* @brief Establishes an IPv4 or IPv6 TCP connection.
*
* A ConnectEvent event is emitted when the connection has been
* established.<br/>
* 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<typename I = IPv4>
void connect(std::string ip, unsigned int port) {
typename details::IpTraits<I>::Type addr;
@ -106,6 +211,15 @@ public:
connect->connect(&uv_tcp_connect, get<uv_tcp_t>(), reinterpret_cast<const sockaddr *>(&addr));
}
/**
* @brief Establishes an IPv4 or IPv6 TCP connection.
*
* A ConnectEvent event is emitted when the connection has been
* established.<br/>
* An ErrorEvent event is emitted in case of errors during the connection.
*
* @param addr A valid instance of Addr.
*/
template<typename I = IPv4>
void connect(Addr addr) {
connect<I>(addr.ip, addr.port);

View File

@ -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<TimerEvent> { };

View File

@ -15,17 +15,46 @@
namespace uvw {
/**
* @brief SendEvent event.
*
* It will be emitted by UDPHandle according with its functionalities.
*/
struct SendEvent: Event<SendEvent> { };
/**
* @brief UDPDataEvent event.
*
* It will be emitted by UDPHandle according with its functionalities.
*/
struct UDPDataEvent: Event<UDPDataEvent> {
explicit UDPDataEvent(Addr addr, std::unique_ptr<const char[]> 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.<br/>
* 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<UDPHandle, uv_udp_t> {
template<typename I>
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.<br/>
* 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<typename... Args>
static std::shared_ptr<UDPHandle> create(Args&&... args) {
return std::shared_ptr<UDPHandle>{new UDPHandle{std::forward<Args>(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_t>(&uv_udp_init_ex, flags)
: initialize<uv_udp_t>(&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
* its 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<uv_udp_t>(), 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<typename I = IPv4>
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
typename details::IpTraits<I>::Type addr;
@ -129,42 +210,111 @@ public:
invoke(&uv_udp_bind, get<uv_udp_t>(), reinterpret_cast<const sockaddr *>(&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<typename I = IPv4>
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
bind<I>(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<typename I = IPv4>
Addr sock() const noexcept {
return details::address<I>(&uv_udp_getsockname, get<uv_udp_t>());
}
/**
* @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<typename I = IPv4>
void multicastMembership(std::string multicast, std::string interface, Membership membership) {
invoke(&uv_udp_set_membership, get<uv_udp_t>(), multicast.data(), interface.data(), static_cast<uv_membership>(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<uv_udp_t>(), 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<uv_udp_t>(), val > 255 ? 255 : val);
}
/**
* @brief Sets the multicast interface to send or receive data on.
* @param interface Interface address.
*/
template<typename I = IPv4>
void multicastInterface(std::string interface) {
invoke(&uv_udp_set_multicast_interface, get<uv_udp_t>(), 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<uv_udp_t>(), 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<uv_udp_t>(), 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.<br/>
* 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<typename I = IPv4>
void send(std::string ip, unsigned int port, std::unique_ptr<char[]> data, ssize_t len) {
typename details::IpTraits<I>::Type addr;
@ -182,6 +332,18 @@ public:
send->send(get<uv_udp_t>(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
}
/**
* @brief Sends data over the UDP socket.
*
* Same as `send()`, but it wont queue a send request if it cant 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<typename I = IPv4>
int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, ssize_t len) {
typename details::IpTraits<I>::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.<br/>
* An ErrorEvent event will be emitted in case of errors.
*/
template<typename I = IPv4>
void recv() {
invoke(&uv_udp_recv_start, get<uv_udp_t>(), &allocCallback, &recvCallback<I>);
}
/**
* @brief Stops listening for incoming datagrams.
*/
void stop() {
invoke(&uv_udp_recv_stop, get<uv_udp_t>());
}

View File

@ -13,9 +13,24 @@
namespace uvw {
/**
* @brief WorkEvent event.
*
* It will be emitted by WorkReq according with its functionalities.
*/
struct WorkEvent: Event<WorkEvent> { };
/**
* @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<WorkReq, uv_work_t> {
using InternalTask = std::function<void(void)>;
@ -30,11 +45,28 @@ class WorkReq final: public Request<WorkReq, uv_work_t> {
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<void(void)>`.
*
* @return A pointer to the newly created handle.
*/
template<typename... Args>
static std::shared_ptr<WorkReq> create(Args&&... args) {
return std::shared_ptr<WorkReq>{new WorkReq{std::forward<Args>(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.<br/>
* This request can be cancelled with `cancel()`.
*/
void queue() {
invoke(&uv_queue_work, parent(), get<uv_work_t>(), &workCallback, &defaultCallback<uv_work_t, WorkEvent>);
}