improved low-level interface for tcp/udp/dns
This commit is contained in:
parent
38414e3063
commit
1e2c566295
@ -201,6 +201,15 @@ class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
|
||||
public:
|
||||
using Request::Request;
|
||||
|
||||
/**
|
||||
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
|
||||
* @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*/
|
||||
void nameInfo(const sockaddr &addr, int flags = 0) {
|
||||
invoke(&uv_getnameinfo, parent(), get(), &nameInfoCallback, &addr, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
|
||||
* @param ip A valid IP address.
|
||||
@ -211,8 +220,7 @@ public:
|
||||
void nameInfo(std::string ip, unsigned int port, int flags = 0) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
auto saddr = reinterpret_cast<const sockaddr *>(&addr);
|
||||
invoke(&uv_getnameinfo, parent(), get(), &nameInfoCallback, saddr, flags);
|
||||
nameInfo(reinterpret_cast<const sockaddr &>(addr), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,7 +230,26 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void nameInfo(Addr addr, int flags = 0) {
|
||||
nameInfo<I>(addr.ip, addr.port, flags);
|
||||
nameInfo<I>(std::move(addr.ip), addr.port, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
|
||||
*
|
||||
* @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @param flags Optional flags that modify the behavior of `getnameinfo`.
|
||||
*
|
||||
* @return A `std::pair` composed as it follows:
|
||||
* * A boolean value that is true in case of success, false otherwise.
|
||||
* * A `std::pair` composed as it follows:
|
||||
* * A `const char *` containing a valid hostname.
|
||||
* * A `const char *` containing a valid service name.
|
||||
*/
|
||||
std::pair<bool, std::pair<const char *, const char *>>
|
||||
nameInfoSync(const sockaddr &addr, int flags = 0) {
|
||||
auto req = get();
|
||||
auto err = uv_getnameinfo(parent(), req, nullptr, &addr, flags);
|
||||
return std::make_pair(!err, std::make_pair(req->host, req->service));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,10 +270,7 @@ public:
|
||||
nameInfoSync(std::string ip, unsigned int port, int flags = 0) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
auto req = get();
|
||||
auto saddr = reinterpret_cast<const sockaddr *>(&addr);
|
||||
auto err = uv_getnameinfo(parent(), req, nullptr, saddr, flags);
|
||||
return std::make_pair(!err, std::make_pair(req->host, req->service));
|
||||
return nameInfoSync(reinterpret_cast<const sockaddr &>(addr), flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,7 +288,7 @@ public:
|
||||
template<typename I = IPv4>
|
||||
std::pair<bool, std::pair<const char *, const char *>>
|
||||
nameInfoSync(Addr addr, int flags = 0) {
|
||||
return nameInfoSync<I>(addr.ip, addr.port, flags);
|
||||
return nameInfoSync<I>(std::move(addr.ip), addr.port, flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -130,7 +130,7 @@ public:
|
||||
* @param opts Optional additional flags.
|
||||
*/
|
||||
void bind(const sockaddr &addr, Flags<Bind> opts = Flags<Bind>{}) {
|
||||
invoke(&uv_tcp_bind, get(), reinterpret_cast<const sockaddr *>(&addr), opts);
|
||||
invoke(&uv_tcp_bind, get(), &addr, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -175,7 +175,7 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void bind(Addr addr, Flags<Bind> opts = Flags<Bind>{}) {
|
||||
bind<I>(addr.ip, addr.port, opts);
|
||||
bind<I>(std::move(addr.ip), addr.port, std::move(opts));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,7 +244,7 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void connect(Addr addr) {
|
||||
connect<I>(addr.ip, addr.port);
|
||||
connect<I>(std::move(addr.ip), addr.port);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
183
src/uvw/udp.hpp
183
src/uvw/udp.hpp
@ -157,6 +157,25 @@ public:
|
||||
invoke(&uv_udp_open, get(), socket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @param opts Optional additional flags.
|
||||
*/
|
||||
void bind(const sockaddr &addr, Flags<Bind> opts = Flags<Bind>{}) {
|
||||
invoke(&uv_udp_bind, get(), &addr, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Binds the UDP handle to an IP address and port.
|
||||
*
|
||||
@ -177,7 +196,7 @@ public:
|
||||
void bind(std::string ip, unsigned int port, Flags<Bind> opts = Flags<Bind>{}) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
invoke(&uv_udp_bind, get(), reinterpret_cast<const sockaddr *>(&addr), opts);
|
||||
bind(reinterpret_cast<const sockaddr &>(addr), std::move(opts));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -197,7 +216,7 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void bind(Addr addr, Flags<Bind> opts = Flags<Bind>{}) {
|
||||
bind<I>(addr.ip, addr.port, opts);
|
||||
bind<I>(std::move(addr.ip), addr.port, std::move(opts));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,16 +308,11 @@ public:
|
||||
* 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 addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @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, unsigned int len) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
|
||||
void send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
|
||||
auto req = loop().resource<details::SendReq>(
|
||||
std::unique_ptr<char[], details::SendReq::Deleter>{
|
||||
data.release(), [](char *ptr) { delete[] ptr; }
|
||||
@ -310,7 +324,32 @@ public:
|
||||
|
||||
req->once<ErrorEvent>(listener);
|
||||
req->once<SendEvent>(listener);
|
||||
req->send(get(), reinterpret_cast<const sockaddr *>(&addr));
|
||||
req->send(get(), &addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* The handle takes the ownership of the data and it is in charge of delete
|
||||
* them.
|
||||
*
|
||||
* 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, unsigned int len) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
send(reinterpret_cast<const sockaddr &>(addr), std::move(data), len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -332,7 +371,39 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void send(Addr addr, std::unique_ptr<char[]> data, unsigned int len) {
|
||||
send<I>(addr.ip, addr.port, std::move(data), len);
|
||||
send<I>(std::move(addr.ip), addr.port, std::move(data), len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* The handle doesn't take the ownership of the data. Be sure that their
|
||||
* lifetime overcome the one of the request.
|
||||
*
|
||||
* A SendEvent event will be emitted when the data have been sent.<br/>
|
||||
* An ErrorEvent event will be emitted in case of errors.
|
||||
*
|
||||
* @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @param data The data to be sent.
|
||||
* @param len The lenght of the submitted data.
|
||||
*/
|
||||
void send(const sockaddr &addr, char *data, unsigned int len) {
|
||||
auto req = loop().resource<details::SendReq>(
|
||||
std::unique_ptr<char[], details::SendReq::Deleter>{
|
||||
data, [](char *) {}
|
||||
}, len);
|
||||
|
||||
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
|
||||
ptr->publish(event);
|
||||
};
|
||||
|
||||
req->once<ErrorEvent>(listener);
|
||||
req->once<SendEvent>(listener);
|
||||
req->send(get(), &addr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,19 +428,7 @@ public:
|
||||
void send(std::string ip, unsigned int port, char *data, unsigned int len) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
|
||||
auto req = loop().resource<details::SendReq>(
|
||||
std::unique_ptr<char[], details::SendReq::Deleter>{
|
||||
data, [](char *) {}
|
||||
}, len);
|
||||
|
||||
auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
|
||||
ptr->publish(event);
|
||||
};
|
||||
|
||||
req->once<ErrorEvent>(listener);
|
||||
req->once<SendEvent>(listener);
|
||||
req->send(get(), reinterpret_cast<const sockaddr *>(&addr));
|
||||
send(reinterpret_cast<const sockaddr &>(addr), data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,7 +450,31 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
void send(Addr addr, char *data, unsigned int len) {
|
||||
send<I>(addr.ip, addr.port, data, len);
|
||||
send<I>(std::move(addr.ip), addr.port, data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @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(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
|
||||
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
|
||||
auto bw = uv_udp_try_send(get(), bufs, 1, &addr);
|
||||
|
||||
if(bw < 0) {
|
||||
publish(ErrorEvent{bw});
|
||||
bw = 0;
|
||||
}
|
||||
|
||||
return bw;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,16 +493,7 @@ public:
|
||||
int trySend(std::string ip, unsigned int port, std::unique_ptr<char[]> data, unsigned int len) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
|
||||
uv_buf_t bufs[] = { uv_buf_init(data.get(), len) };
|
||||
auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
|
||||
|
||||
if(bw < 0) {
|
||||
publish(ErrorEvent{bw});
|
||||
bw = 0;
|
||||
}
|
||||
|
||||
return bw;
|
||||
return trySend(reinterpret_cast<const sockaddr &>(addr), std::move(data), len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -435,7 +509,31 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
int trySend(Addr addr, std::unique_ptr<char[]> data, unsigned int len) {
|
||||
return trySend<I>(addr.ip, addr.port, std::move(data), len);
|
||||
return trySend<I>(std::move(addr.ip), addr.port, std::move(data), len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
|
||||
* @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(const sockaddr &addr, char *data, unsigned int len) {
|
||||
uv_buf_t bufs[] = { uv_buf_init(data, len) };
|
||||
auto bw = uv_udp_try_send(get(), bufs, 1, &addr);
|
||||
|
||||
if(bw < 0) {
|
||||
publish(ErrorEvent{bw});
|
||||
bw = 0;
|
||||
}
|
||||
|
||||
return bw;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,16 +552,7 @@ public:
|
||||
int trySend(std::string ip, unsigned int port, char *data, unsigned int len) {
|
||||
typename details::IpTraits<I>::Type addr;
|
||||
details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
|
||||
|
||||
uv_buf_t bufs[] = { uv_buf_init(data, len) };
|
||||
auto bw = uv_udp_try_send(get(), bufs, 1, reinterpret_cast<const sockaddr *>(&addr));
|
||||
|
||||
if(bw < 0) {
|
||||
publish(ErrorEvent{bw});
|
||||
bw = 0;
|
||||
}
|
||||
|
||||
return bw;
|
||||
return trySend(reinterpret_cast<const sockaddr &>(addr), data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -479,7 +568,7 @@ public:
|
||||
*/
|
||||
template<typename I = IPv4>
|
||||
int trySend(Addr addr, char *data, unsigned int len) {
|
||||
return trySend<I>(addr.ip, addr.port, data, len);
|
||||
return trySend<I>(std::move(addr.ip), addr.port, data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user