Merge pull request #54 from cynnyx/master
miscellaneous utilities + interfaces + docs + bug fixing
This commit is contained in:
commit
b8a45f040d
@ -195,8 +195,8 @@ tcp->bind("127.0.0.1", 4242);
|
||||
tcp->listen();
|
||||
```
|
||||
|
||||
Note also that `uvw::TcpHandle` already supports _IPv6_ out-of-the-box. The statement above is equivalent to `tcp->bind<uvw::net::IPv4>("127.0.0.1", 4242)`.<br/>
|
||||
It's suffice to explicitly specify `uvw::net::IPv6` as the underlying protocol to use it.
|
||||
Note also that `uvw::TcpHandle` already supports _IPv6_ out-of-the-box. The statement above is equivalent to `tcp->bind<uvw::IPv4>("127.0.0.1", 4242)`.<br/>
|
||||
It's suffice to explicitly specify `uvw::IPv6` as the underlying protocol to use it.
|
||||
|
||||
The API reference is the recommended documentation for further details about resources and their methods.
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "request.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
@ -214,7 +214,7 @@ public:
|
||||
* @param port A valid port number.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void getNameInfo(std::string ip, unsigned int port, int flags = 0) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::AddrFunc(ip.data(), port, &addr);
|
||||
@ -226,7 +226,7 @@ public:
|
||||
* @param addr A valid instance of Addr.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void getNameInfo(Addr addr, int flags = 0) {
|
||||
getNameInfo<I>(addr.ip, addr.port, flags);
|
||||
}
|
||||
@ -237,7 +237,7 @@ public:
|
||||
* @param port A valid port number.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
auto getNameInfoSync(std::string ip, unsigned int port, int flags = 0) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::AddrFunc(ip.data(), port, &addr);
|
||||
@ -251,7 +251,7 @@ public:
|
||||
* @param addr A valid instance of Addr.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
auto getNameInfoSync(Addr addr, int flags = 0) {
|
||||
getNameInfoSync<I>(addr.ip, addr.port, flags);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "request.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#include <memory>
|
||||
#include <uv.h>
|
||||
#include "resource.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
112
src/uvw/misc.hpp
112
src/uvw/misc.hpp
@ -1,112 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <uv.h>
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
|
||||
namespace net {
|
||||
|
||||
|
||||
struct IPv4 { };
|
||||
struct IPv6 { };
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
|
||||
template<typename>
|
||||
struct IpTraits;
|
||||
|
||||
template<>
|
||||
struct IpTraits<net::IPv4> {
|
||||
using Type = sockaddr_in;
|
||||
using AddrFuncType = int(*)(const char *, int, sockaddr_in *);
|
||||
using NameFuncType = int(*)(const sockaddr_in *, char *, std::size_t);
|
||||
static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
|
||||
static constexpr NameFuncType nameFunc = &uv_ip4_name;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IpTraits<net::IPv6> {
|
||||
using Type = sockaddr_in6;
|
||||
using AddrFuncType = int(*)(const char *, int, sockaddr_in6 *);
|
||||
using NameFuncType = int(*)(const sockaddr_in6 *, char *, std::size_t);
|
||||
static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
|
||||
static constexpr NameFuncType nameFunc = &uv_ip6_name;
|
||||
};
|
||||
|
||||
|
||||
template<typename I>
|
||||
Addr address(const typename IpTraits<I>::Type *aptr, int len) noexcept {
|
||||
std::pair<std::string, unsigned int> addr{};
|
||||
char name[len];
|
||||
|
||||
int err = IpTraits<I>::nameFunc(aptr, name, len);
|
||||
|
||||
if(0 == err) {
|
||||
addr = { std::string{name}, ntohs(aptr->sin_port) };
|
||||
}
|
||||
|
||||
/**
|
||||
* See Boost/Mutant idiom:
|
||||
* https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant
|
||||
*/
|
||||
return reinterpret_cast<Addr&>(addr);
|
||||
}
|
||||
|
||||
|
||||
template<typename I, typename F, typename H>
|
||||
Addr address(F &&f, const H *handle) noexcept {
|
||||
sockaddr_storage ssto;
|
||||
int len = sizeof(ssto);
|
||||
Addr addr{};
|
||||
|
||||
int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
|
||||
|
||||
if(0 == err) {
|
||||
typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
|
||||
addr = address<I>(aptr, len);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
template<typename F, typename H, typename..., std::size_t N = 128>
|
||||
std::string path(F &&f, H *handle) noexcept {
|
||||
std::size_t size = N;
|
||||
char buf[size];
|
||||
std::string str{};
|
||||
auto err = std::forward<F>(f)(handle, buf, &size);
|
||||
|
||||
if(UV_ENOBUFS == err) {
|
||||
std::unique_ptr<char[]> data{new char[size]};
|
||||
err = std::forward<F>(f)(handle, data.get(), &size);
|
||||
|
||||
if(0 == err) {
|
||||
str = data.get();
|
||||
}
|
||||
} else {
|
||||
str.assign(buf, size);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
#include "event.hpp"
|
||||
#include "request.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
@ -148,7 +148,7 @@ public:
|
||||
*/
|
||||
HandleType receive() noexcept {
|
||||
auto type = uv_pipe_pending_type(get<uv_pipe_t>());
|
||||
return guessHandle(type);
|
||||
return Utilities::guessHandle(type);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include "event.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "event.hpp"
|
||||
#include "request.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
@ -32,7 +32,7 @@ enum class UVTcpFlags: std::underlying_type_t<uv_tcp_flags> {
|
||||
*
|
||||
* 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::net::IPv6`.
|
||||
* supports _IPv6_ out-of-the-box by using `uvw::IPv6`.
|
||||
*/
|
||||
class TcpHandle final: public StreamHandle<TcpHandle, uv_tcp_t> {
|
||||
explicit TcpHandle(std::shared_ptr<Loop> ref)
|
||||
@ -138,7 +138,7 @@ public:
|
||||
* @param port The port to which to bind.
|
||||
* @param flags Optional additional flags.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
@ -161,7 +161,7 @@ public:
|
||||
* @param addr A valid instance of Addr.
|
||||
* @param flags Optional additional flags.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
|
||||
bind<I>(addr.ip, addr.port, flags);
|
||||
}
|
||||
@ -170,7 +170,7 @@ public:
|
||||
* @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 = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
Addr sock() const noexcept {
|
||||
return details::address<I>(&uv_tcp_getsockname, get<uv_tcp_t>());
|
||||
}
|
||||
@ -179,7 +179,7 @@ public:
|
||||
* @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 = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
Addr peer() const noexcept {
|
||||
return details::address<I>(&uv_tcp_getpeername, get<uv_tcp_t>());
|
||||
}
|
||||
@ -194,7 +194,7 @@ public:
|
||||
* @param ip The address to which to bind.
|
||||
* @param port The port to which to bind.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void connect(std::string ip, unsigned int port) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
@ -218,7 +218,7 @@ public:
|
||||
*
|
||||
* @param addr A valid instance of Addr.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void connect(Addr addr) {
|
||||
connect<I>(addr.ip, addr.port);
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
#include <uv.h>
|
||||
#include "event.hpp"
|
||||
#include "stream.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
@ -117,23 +117,17 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Gets the current Window size.
|
||||
* @return The current Window size or `{0, 0}` in case of errors.
|
||||
* @return The current Window size or `{-1, -1}` in case of errors.
|
||||
*/
|
||||
WinSize getWinSize() {
|
||||
std::pair<int, int> size{0, 0};
|
||||
int width;
|
||||
int height;
|
||||
WinSize size;
|
||||
|
||||
if(0 == invoke(&uv_tty_get_winsize, get<uv_tty_t>(), &width, &height)) {
|
||||
size.first = width;
|
||||
size.second = height;
|
||||
if(0 != invoke(&uv_tty_get_winsize, get<uv_tty_t>(), &size.width, &size.height)) {
|
||||
size.width = -1;
|
||||
size.height = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* See Boost/Mutant idiom:
|
||||
* https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant
|
||||
*/
|
||||
return reinterpret_cast<WinSize&>(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "event.hpp"
|
||||
#include "request.hpp"
|
||||
#include "handle.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
|
||||
namespace uvw {
|
||||
@ -103,13 +103,12 @@ public:
|
||||
*
|
||||
* 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::net::IPv6`.
|
||||
* supports _IPv6_ out-of-the-box by using `uvw::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) {
|
||||
typename details::IpTraits<I>::Type *aptr = reinterpret_cast<const typename details::IpTraits<I>::Type *>(addr);
|
||||
int len = sizeof(*addr);
|
||||
|
||||
UDPHandle &udp = *(static_cast<UDPHandle*>(handle->data));
|
||||
// data will be destroyed no matter of what the value of nread is
|
||||
@ -117,12 +116,12 @@ class UDPHandle final: public Handle<UDPHandle, uv_udp_t> {
|
||||
|
||||
if(nread > 0) {
|
||||
// data available (can be truncated)
|
||||
udp.publish(UDPDataEvent{details::address<I>(aptr, len), std::move(data), nread, flags & UV_UDP_PARTIAL});
|
||||
udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), nread, flags & UV_UDP_PARTIAL});
|
||||
} else if(nread == 0 && addr == nullptr) {
|
||||
// no more data to be read, doing nothing is fine
|
||||
} else if(nread == 0 && addr != nullptr) {
|
||||
// empty udp packet
|
||||
udp.publish(UDPDataEvent{details::address<I>(aptr, len), std::move(data), nread, false});
|
||||
udp.publish(UDPDataEvent{details::address<I>(aptr), std::move(data), nread, false});
|
||||
} else {
|
||||
// transmission error
|
||||
udp.publish(ErrorEvent(nread));
|
||||
@ -201,7 +200,7 @@ public:
|
||||
* @param port The port to which to bind.
|
||||
* @param flags Optional additional flags.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void bind(std::string ip, unsigned int port, Flags<Bind> flags = Flags<Bind>{}) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
@ -223,7 +222,7 @@ public:
|
||||
* @param addr A valid instance of Addr.
|
||||
* @param flags Optional additional flags.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void bind(Addr addr, Flags<Bind> flags = Flags<Bind>{}) {
|
||||
bind<I>(addr.ip, addr.port, flags);
|
||||
}
|
||||
@ -232,7 +231,7 @@ public:
|
||||
* @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 = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
Addr sock() const noexcept {
|
||||
return details::address<I>(&uv_udp_getsockname, get<uv_udp_t>());
|
||||
}
|
||||
@ -249,7 +248,7 @@ public:
|
||||
* @param interface Interface address.
|
||||
* @param membership Action to be performed.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
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));
|
||||
}
|
||||
@ -277,7 +276,7 @@ public:
|
||||
* @brief Sets the multicast interface to send or receive data on.
|
||||
* @param interface Interface address.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void multicastInterface(std::string interface) {
|
||||
invoke(&uv_udp_set_multicast_interface, get<uv_udp_t>(), interface.data());
|
||||
}
|
||||
@ -313,7 +312,7 @@ public:
|
||||
* @param data The data to be sent.
|
||||
* @param len The lenght of the submitted data.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
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;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
@ -342,7 +341,7 @@ public:
|
||||
* @param len The lenght of the submitted data.
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
template<typename I = net::IPv4>
|
||||
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;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
@ -368,7 +367,7 @@ public:
|
||||
* 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 = net::IPv4>
|
||||
template<typename I = IPv4>
|
||||
void recv() {
|
||||
invoke(&uv_udp_recv_start, get<uv_udp_t>(), &allocCallback, &recvCallback<I>);
|
||||
}
|
||||
|
||||
307
src/uvw/util.hpp
307
src/uvw/util.hpp
@ -2,10 +2,12 @@
|
||||
|
||||
|
||||
#include <type_traits>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
@ -149,29 +151,13 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Address representation.
|
||||
*
|
||||
* Pair alias (see Boost/Mutant idiom) used to pack together an ip and a
|
||||
* port.<br/>
|
||||
* Instead of `first` and `second`, the two parameters are named:
|
||||
*
|
||||
* * `ip`, that is of type `std::string`
|
||||
* * `port`, that is of type `unsigned int`
|
||||
*/
|
||||
struct Addr { std::string ip; unsigned int port; };
|
||||
|
||||
/**
|
||||
* @brief Windows size representation.
|
||||
*
|
||||
* Pair alias (see Boost/Mutant idiom) used to pack together a width and a
|
||||
* height.<br/>
|
||||
* Instead of `first` and `second`, the two parameters are named:
|
||||
*
|
||||
* * `width`, that is of type `int`
|
||||
* * `height`, that is of type `int`
|
||||
*/
|
||||
struct WinSize { int width; int height; };
|
||||
struct WinSize {
|
||||
int width; /*!< The _width_ of the given window. */
|
||||
int height; /*!< The _height_ of the given window. */
|
||||
};
|
||||
|
||||
|
||||
using HandleType = details::UVHandleType;
|
||||
@ -187,67 +173,238 @@ using Gid = uv_gid_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the type of the stream to be used with the given descriptor.
|
||||
* @brief The IPv4 tag.
|
||||
*
|
||||
* Returns the type of stream that should be used with a given file
|
||||
* descriptor.<br/>
|
||||
* Usually this will be used during initialization to guess the type of the
|
||||
* stdio streams.
|
||||
*
|
||||
* @param file A valid descriptor.
|
||||
* @return One of the following types:
|
||||
*
|
||||
* * `HandleType::UNKNOWN`
|
||||
* * `HandleType::PIPE`
|
||||
* * `HandleType::TCP`
|
||||
* * `HandleType::TTY`
|
||||
* * `HandleType::UDP`
|
||||
* * `HandleType::FILE`
|
||||
* To be used as template parameter to switch between IPv4 and IPv6.
|
||||
*/
|
||||
HandleType guessHandle(FileHandle file) {
|
||||
auto type = uv_guess_handle(file);
|
||||
struct IPv4 { };
|
||||
|
||||
switch(type) {
|
||||
case UV_ASYNC:
|
||||
return HandleType::ASYNC;
|
||||
case UV_CHECK:
|
||||
return HandleType::CHECK;
|
||||
case UV_FS_EVENT:
|
||||
return HandleType::FS_EVENT;
|
||||
case UV_FS_POLL:
|
||||
return HandleType::FS_POLL;
|
||||
case UV_HANDLE:
|
||||
return HandleType::HANDLE;
|
||||
case UV_IDLE:
|
||||
return HandleType::IDLE;
|
||||
case UV_NAMED_PIPE:
|
||||
return HandleType::PIPE;
|
||||
case UV_POLL:
|
||||
return HandleType::POLL;
|
||||
case UV_PREPARE:
|
||||
return HandleType::PREPARE;
|
||||
case UV_PROCESS:
|
||||
return HandleType::PROCESS;
|
||||
case UV_STREAM:
|
||||
return HandleType::STREAM;
|
||||
case UV_TCP:
|
||||
return HandleType::TCP;
|
||||
case UV_TIMER:
|
||||
return HandleType::TIMER;
|
||||
case UV_TTY:
|
||||
return HandleType::TTY;
|
||||
case UV_UDP:
|
||||
return HandleType::UDP;
|
||||
case UV_SIGNAL:
|
||||
return HandleType::SIGNAL;
|
||||
case UV_FILE:
|
||||
return HandleType::FILE;
|
||||
default:
|
||||
return HandleType::UNKNOWN;
|
||||
|
||||
/**
|
||||
* @brief The IPv6 tag.
|
||||
*
|
||||
* To be used as template parameter to switch between IPv4 and IPv6.
|
||||
*/
|
||||
struct IPv6 { };
|
||||
|
||||
|
||||
/**
|
||||
* @brief Address representation.
|
||||
*/
|
||||
struct Addr {
|
||||
std::string ip; /*!< Either an IPv4 or an IPv6. */
|
||||
unsigned int port; /*!< A valid service identifier. */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Interface address.
|
||||
*/
|
||||
struct Interface {
|
||||
std::string name; /*!< The name of the interface (as an example _eth0_). */
|
||||
std::string physical; /*!< The physical address. */
|
||||
bool internal; /*!< True if it is an internal interface (as an example _loopback_), false otherwise. */
|
||||
Addr address; /*!< The address of the given interface. */
|
||||
Addr netmask; /*!< The netmask of the given interface. */
|
||||
};
|
||||
|
||||
|
||||
namespace details {
|
||||
|
||||
|
||||
template<typename>
|
||||
struct IpTraits;
|
||||
|
||||
|
||||
template<>
|
||||
struct IpTraits<IPv4> {
|
||||
using Type = sockaddr_in;
|
||||
using AddrFuncType = int(*)(const char *, int, Type *);
|
||||
using NameFuncType = int(*)(const Type *, char *, std::size_t);
|
||||
static constexpr AddrFuncType addrFunc = &uv_ip4_addr;
|
||||
static constexpr NameFuncType nameFunc = &uv_ip4_name;
|
||||
static constexpr auto sinPort(const Type *addr) { return addr->sin_port; }
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct IpTraits<IPv6> {
|
||||
using Type = sockaddr_in6;
|
||||
using AddrFuncType = int(*)(const char *, int, Type *);
|
||||
using NameFuncType = int(*)(const Type *, char *, std::size_t);
|
||||
static constexpr AddrFuncType addrFunc = &uv_ip6_addr;
|
||||
static constexpr NameFuncType nameFunc = &uv_ip6_name;
|
||||
static constexpr auto sinPort(const Type *addr) { return addr->sin6_port; }
|
||||
};
|
||||
|
||||
|
||||
template<typename I, typename..., std::size_t N = 128>
|
||||
Addr address(const typename details::IpTraits<I>::Type *aptr) noexcept {
|
||||
Addr addr;
|
||||
char name[N];
|
||||
|
||||
int err = details::IpTraits<I>::nameFunc(aptr, name, N);
|
||||
|
||||
if(0 == err) {
|
||||
addr.port = ntohs(details::IpTraits<I>::sinPort(aptr));
|
||||
addr.ip = std::string{name};
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
template<typename I, typename F, typename H>
|
||||
Addr address(F &&f, const H *handle) noexcept {
|
||||
sockaddr_storage ssto;
|
||||
int len = sizeof(ssto);
|
||||
Addr addr{};
|
||||
|
||||
int err = std::forward<F>(f)(handle, reinterpret_cast<sockaddr *>(&ssto), &len);
|
||||
|
||||
if(0 == err) {
|
||||
typename IpTraits<I>::Type *aptr = reinterpret_cast<typename IpTraits<I>::Type *>(&ssto);
|
||||
addr = address<I>(aptr);
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
template<typename F, typename H, typename..., std::size_t N = 128>
|
||||
std::string path(F &&f, H *handle) noexcept {
|
||||
std::size_t size = N;
|
||||
char buf[size];
|
||||
std::string str{};
|
||||
auto err = std::forward<F>(f)(handle, buf, &size);
|
||||
|
||||
if(UV_ENOBUFS == err) {
|
||||
std::unique_ptr<char[]> data{new char[size]};
|
||||
err = std::forward<F>(f)(handle, data.get(), &size);
|
||||
|
||||
if(0 == err) {
|
||||
str = data.get();
|
||||
}
|
||||
} else {
|
||||
str.assign(buf, size);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Miscellaneous utilities.
|
||||
*
|
||||
* Miscellaneous functions that don’t really belong to any other class.
|
||||
*/
|
||||
struct Utilities {
|
||||
/**
|
||||
* @brief Gets the type of the stream to be used with the given descriptor.
|
||||
*
|
||||
* Returns the type of stream that should be used with a given file
|
||||
* descriptor.<br/>
|
||||
* Usually this will be used during initialization to guess the type of the
|
||||
* stdio streams.
|
||||
*
|
||||
* @param file A valid descriptor.
|
||||
* @return One of the following types:
|
||||
*
|
||||
* * `HandleType::UNKNOWN`
|
||||
* * `HandleType::PIPE`
|
||||
* * `HandleType::TCP`
|
||||
* * `HandleType::TTY`
|
||||
* * `HandleType::UDP`
|
||||
* * `HandleType::FILE`
|
||||
*/
|
||||
static HandleType guessHandle(FileHandle file) {
|
||||
auto type = uv_guess_handle(file);
|
||||
|
||||
switch(type) {
|
||||
case UV_ASYNC:
|
||||
return HandleType::ASYNC;
|
||||
case UV_CHECK:
|
||||
return HandleType::CHECK;
|
||||
case UV_FS_EVENT:
|
||||
return HandleType::FS_EVENT;
|
||||
case UV_FS_POLL:
|
||||
return HandleType::FS_POLL;
|
||||
case UV_HANDLE:
|
||||
return HandleType::HANDLE;
|
||||
case UV_IDLE:
|
||||
return HandleType::IDLE;
|
||||
case UV_NAMED_PIPE:
|
||||
return HandleType::PIPE;
|
||||
case UV_POLL:
|
||||
return HandleType::POLL;
|
||||
case UV_PREPARE:
|
||||
return HandleType::PREPARE;
|
||||
case UV_PROCESS:
|
||||
return HandleType::PROCESS;
|
||||
case UV_STREAM:
|
||||
return HandleType::STREAM;
|
||||
case UV_TCP:
|
||||
return HandleType::TCP;
|
||||
case UV_TIMER:
|
||||
return HandleType::TIMER;
|
||||
case UV_TTY:
|
||||
return HandleType::TTY;
|
||||
case UV_UDP:
|
||||
return HandleType::UDP;
|
||||
case UV_SIGNAL:
|
||||
return HandleType::SIGNAL;
|
||||
case UV_FILE:
|
||||
return HandleType::FILE;
|
||||
default:
|
||||
return HandleType::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets a set of descriptors of all the available interfaces.
|
||||
*
|
||||
* This function can be used to query the underlying system and get a set of
|
||||
* descriptors of all the available interfaces, either internal or not.
|
||||
*
|
||||
* @return A set of descriptors of all the available interfaces.
|
||||
*/
|
||||
static std::vector<Interface> interfaces() noexcept {
|
||||
std::vector<Interface> interfaces;
|
||||
|
||||
uv_interface_address_t *ifaces;
|
||||
int count;
|
||||
|
||||
uv_interface_addresses(&ifaces, &count);
|
||||
|
||||
std::for_each(ifaces, ifaces+count, [&interfaces](const auto &iface) {
|
||||
Interface interface;
|
||||
|
||||
interface.name = iface.name;
|
||||
interface.physical = iface.phys_addr;
|
||||
interface.internal = iface.is_internal;
|
||||
|
||||
if(iface.address.address4.sin_family == AF_INET) {
|
||||
interface.address = details::address<IPv4>(&iface.address.address4);
|
||||
interface.netmask = details::address<IPv4>(&iface.netmask.netmask4);
|
||||
} else if(iface.address.address4.sin_family == AF_INET6) {
|
||||
interface.address = details::address<IPv6>(&iface.address.address6);
|
||||
interface.netmask = details::address<IPv6>(&iface.netmask.netmask6);
|
||||
}
|
||||
|
||||
interfaces.push_back(std::move(interface));
|
||||
});
|
||||
|
||||
uv_free_interface_addresses(ifaces, count);
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
@ -256,8 +413,6 @@ HandleType guessHandle(FileHandle file) {
|
||||
* * uv_getrusage
|
||||
* * uv_cpu_info
|
||||
* * uv_free_cpu_info
|
||||
* * uv_interface_addresses
|
||||
* * uv_free_interface_addresses
|
||||
* * uv_loadavg
|
||||
* * uv_exepath
|
||||
* * uv_cwd
|
||||
|
||||
@ -33,7 +33,7 @@ set(TARGET_WORK work)
|
||||
|
||||
# Test TARGET_MAIN
|
||||
|
||||
set(TARGET_MAIN_SOURCES main.cpp)
|
||||
set(TARGET_MAIN_SOURCES odr.cpp main.cpp)
|
||||
add_executable(${TARGET_MAIN} ${TARGET_MAIN_SOURCES})
|
||||
target_include_directories(${TARGET_MAIN} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_MAIN} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -41,7 +41,7 @@ add_test(NAME ${TARGET_MAIN} COMMAND ${TARGET_MAIN})
|
||||
|
||||
# Test TARGET_ASYNC
|
||||
|
||||
set(TARGET_ASYNC_SOURCES uvw/async.cpp)
|
||||
set(TARGET_ASYNC_SOURCES odr.cpp uvw/async.cpp)
|
||||
add_executable(${TARGET_ASYNC} ${TARGET_ASYNC_SOURCES})
|
||||
target_include_directories(${TARGET_ASYNC} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_ASYNC} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -49,7 +49,7 @@ add_test(NAME ${TARGET_ASYNC} COMMAND ${TARGET_ASYNC})
|
||||
|
||||
# Test TARGET_CHECK
|
||||
|
||||
set(TARGET_CHECK_SOURCES uvw/check.cpp)
|
||||
set(TARGET_CHECK_SOURCES odr.cpp uvw/check.cpp)
|
||||
add_executable(${TARGET_CHECK} ${TARGET_CHECK_SOURCES})
|
||||
target_include_directories(${TARGET_CHECK} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_CHECK} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -57,7 +57,7 @@ add_test(NAME ${TARGET_CHECK} COMMAND ${TARGET_CHECK})
|
||||
|
||||
# Test TARGET_EMITTER
|
||||
|
||||
set(TARGET_EMITTER_SOURCES uvw/emitter.cpp)
|
||||
set(TARGET_EMITTER_SOURCES odr.cpp uvw/emitter.cpp)
|
||||
add_executable(${TARGET_EMITTER} ${TARGET_EMITTER_SOURCES})
|
||||
target_include_directories(${TARGET_EMITTER} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_EMITTER} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -65,7 +65,7 @@ add_test(NAME ${TARGET_EMITTER} COMMAND ${TARGET_EMITTER})
|
||||
|
||||
# Test TARGET_IDLE
|
||||
|
||||
set(TARGET_IDLE_SOURCES uvw/idle.cpp)
|
||||
set(TARGET_IDLE_SOURCES odr.cpp uvw/idle.cpp)
|
||||
add_executable(${TARGET_IDLE} ${TARGET_IDLE_SOURCES})
|
||||
target_include_directories(${TARGET_IDLE} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_IDLE} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -73,7 +73,7 @@ add_test(NAME ${TARGET_IDLE} COMMAND ${TARGET_IDLE})
|
||||
|
||||
# Test TARGET_LOOP
|
||||
|
||||
set(TARGET_LOOP_SOURCES uvw/loop.cpp)
|
||||
set(TARGET_LOOP_SOURCES odr.cpp uvw/loop.cpp)
|
||||
add_executable(${TARGET_LOOP} ${TARGET_LOOP_SOURCES})
|
||||
target_include_directories(${TARGET_LOOP} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_LOOP} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -81,7 +81,7 @@ add_test(NAME ${TARGET_LOOP} COMMAND ${TARGET_LOOP})
|
||||
|
||||
# Test TARGET_PREPARE
|
||||
|
||||
set(TARGET_PREPARE_SOURCES uvw/prepare.cpp)
|
||||
set(TARGET_PREPARE_SOURCES odr.cpp uvw/prepare.cpp)
|
||||
add_executable(${TARGET_PREPARE} ${TARGET_PREPARE_SOURCES})
|
||||
target_include_directories(${TARGET_PREPARE} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_PREPARE} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -89,7 +89,7 @@ add_test(NAME ${TARGET_PREPARE} COMMAND ${TARGET_PREPARE})
|
||||
|
||||
# Test TARGET_SIGNAL
|
||||
|
||||
set(TARGET_SIGNAL_SOURCES uvw/signal.cpp)
|
||||
set(TARGET_SIGNAL_SOURCES odr.cpp uvw/signal.cpp)
|
||||
add_executable(${TARGET_SIGNAL} ${TARGET_SIGNAL_SOURCES})
|
||||
target_include_directories(${TARGET_SIGNAL} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_SIGNAL} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -97,7 +97,7 @@ add_test(NAME ${TARGET_SIGNAL} COMMAND ${TARGET_SIGNAL})
|
||||
|
||||
# Test TARGET_TIMER
|
||||
|
||||
set(TARGET_TIMER_SOURCES uvw/timer.cpp)
|
||||
set(TARGET_TIMER_SOURCES odr.cpp uvw/timer.cpp)
|
||||
add_executable(${TARGET_TIMER} ${TARGET_TIMER_SOURCES})
|
||||
target_include_directories(${TARGET_TIMER} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_TIMER} PRIVATE ${COMMON_LINK_LIBS})
|
||||
@ -105,7 +105,7 @@ add_test(NAME ${TARGET_TIMER} COMMAND ${TARGET_TIMER})
|
||||
|
||||
# Test TARGET_WORK
|
||||
|
||||
set(TARGET_WORK_SOURCES uvw/work.cpp)
|
||||
set(TARGET_WORK_SOURCES odr.cpp uvw/work.cpp)
|
||||
add_executable(${TARGET_WORK} ${TARGET_WORK_SOURCES})
|
||||
target_include_directories(${TARGET_WORK} PRIVATE ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_WORK} PRIVATE ${COMMON_LINK_LIBS})
|
||||
|
||||
1
test/odr.cpp
Normal file
1
test/odr.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include <uvw.hpp>
|
||||
Loading…
Reference in New Issue
Block a user