linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #04499
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2605: Socket fixes
------------------------------------------------------------
revno: 2605
committer: Jacek Sieka <arnetheduck@xxxxxxxxx>
branch nick: dcplusplus
timestamp: Sun 2011-09-04 17:20:46 +0200
message:
Socket fixes
modified:
dcpp/AdcHub.cpp
dcpp/BufferedSocket.cpp
dcpp/ClientManager.cpp
dcpp/ClientManager.h
dcpp/ConnectionManager.cpp
dcpp/SSLSocket.cpp
dcpp/SSLSocket.h
dcpp/SearchManager.cpp
dcpp/Socket.cpp
dcpp/Socket.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/AdcHub.cpp'
--- dcpp/AdcHub.cpp 2011-08-22 20:33:02 +0000
+++ dcpp/AdcHub.cpp 2011-09-04 15:20:46 +0000
@@ -60,7 +60,8 @@
const vector<StringList> AdcHub::searchExts;
-AdcHub::AdcHub(const string& aHubURL, bool secure) : Client(aHubURL, '\n', secure), oldPassword(false), sid(0) {
+AdcHub::AdcHub(const string& aHubURL, bool secure) :
+ Client(aHubURL, '\n', secure), oldPassword(false), udp(Socket::TYPE_UDP), sid(0) {
TimerManager::getInstance()->addListener(this);
}
=== modified file 'dcpp/BufferedSocket.cpp'
--- dcpp/BufferedSocket.cpp 2011-08-11 13:02:19 +0000
+++ dcpp/BufferedSocket.cpp 2011-09-04 15:20:46 +0000
@@ -89,7 +89,7 @@
void BufferedSocket::accept(const Socket& srv, bool secure, bool allowUntrusted) {
dcdebug("BufferedSocket::accept() %p\n", (void*)this);
- std::unique_ptr<Socket> s(secure ? CryptoManager::getInstance()->getServerSocket(allowUntrusted) : new Socket);
+ std::unique_ptr<Socket> s(secure ? CryptoManager::getInstance()->getServerSocket(allowUntrusted) : new Socket(Socket::TYPE_TCP));
s->accept(srv);
@@ -106,7 +106,7 @@
void BufferedSocket::connect(const string& aAddress, const string& aPort, const string& localPort, NatRoles natRole, bool secure, bool allowUntrusted, bool proxy) {
dcdebug("BufferedSocket::connect() %p\n", (void*)this);
- std::unique_ptr<Socket> s(secure ? (natRole == NAT_SERVER ? CryptoManager::getInstance()->getServerSocket(allowUntrusted) : CryptoManager::getInstance()->getClientSocket(allowUntrusted)) : new Socket);
+ std::unique_ptr<Socket> s(secure ? (natRole == NAT_SERVER ? CryptoManager::getInstance()->getServerSocket(allowUntrusted) : CryptoManager::getInstance()->getClientSocket(allowUntrusted)) : new Socket(Socket::TYPE_TCP));
s->setLocalIp4(SETTING(BIND_ADDRESS));
s->setLocalIp6(SETTING(BIND_ADDRESS6));
@@ -368,11 +368,11 @@
}
} else {
while(!disconnecting) {
- int w = sock->wait(POLL_TIMEOUT, Socket::WAIT_WRITE | Socket::WAIT_READ);
- if(w & Socket::WAIT_READ) {
+ auto w = sock->wait(POLL_TIMEOUT, true, true);
+ if(w.first) {
threadRead();
}
- if(w & Socket::WAIT_WRITE) {
+ if(w.second) {
break;
}
}
@@ -411,13 +411,13 @@
return;
}
- int w = sock->wait(POLL_TIMEOUT, Socket::WAIT_READ | Socket::WAIT_WRITE);
+ auto w = sock->wait(POLL_TIMEOUT, true, true);
- if(w & Socket::WAIT_READ) {
+ if(w.first) {
threadRead();
}
- if(w & Socket::WAIT_WRITE) {
+ if(w.second) {
int n = sock->write(&sendBuf[done], left);
if(n > 0) {
left -= n;
@@ -470,9 +470,9 @@
}
void BufferedSocket::checkSocket() {
- int waitFor = sock->wait(POLL_TIMEOUT, Socket::WAIT_READ);
+ auto w = sock->wait(POLL_TIMEOUT, true, false);
- if(waitFor & Socket::WAIT_READ) {
+ if(w.first) {
threadRead();
}
}
=== modified file 'dcpp/ClientManager.cpp'
--- dcpp/ClientManager.cpp 2011-08-11 13:02:19 +0000
+++ dcpp/ClientManager.cpp 2011-09-04 15:20:46 +0000
@@ -33,6 +33,14 @@
namespace dcpp {
+ClientManager::ClientManager() : udp(Socket::TYPE_UDP) {
+ TimerManager::getInstance()->addListener(this);
+}
+
+ClientManager::~ClientManager() {
+ TimerManager::getInstance()->removeListener(this);
+}
+
Client* ClientManager::getClient(const string& aHubURL) {
Client* c;
if(Util::strnicmp("adc://", aHubURL.c_str(), 6) == 0) {
=== modified file 'dcpp/ClientManager.h'
--- dcpp/ClientManager.h 2011-08-11 13:02:19 +0000
+++ dcpp/ClientManager.h 2011-09-04 15:20:46 +0000
@@ -158,13 +158,8 @@
friend class Singleton<ClientManager>;
- ClientManager() {
- TimerManager::getInstance()->addListener(this);
- }
-
- virtual ~ClientManager() {
- TimerManager::getInstance()->removeListener(this);
- }
+ ClientManager();
+ virtual ~ClientManager();
void updateNick(const OnlineUser& user) noexcept;
=== modified file 'dcpp/ConnectionManager.cpp'
--- dcpp/ConnectionManager.cpp 2011-08-19 18:07:56 +0000
+++ dcpp/ConnectionManager.cpp 2011-09-04 15:20:46 +0000
@@ -211,7 +211,9 @@
static const uint32_t FLOOD_TRIGGER = 20000;
static const uint32_t FLOOD_ADD = 2000;
-ConnectionManager::Server::Server(bool secure_, uint16_t aPort, const string& ip) : port(0), secure(secure_), die(false) {
+ConnectionManager::Server::Server(bool secure_, uint16_t aPort, const string& ip) :
+ sock(Socket::TYPE_TCP), port(0), secure(secure_), die(false)
+{
sock.setLocalIp4(ip);
port = sock.listen(Util::toString(aPort));
@@ -224,8 +226,8 @@
while(!die) {
try {
while(!die) {
- auto ret = sock.wait(POLL_TIMEOUT, Socket::WAIT_READ);
- if(ret == Socket::WAIT_READ) {
+ auto ret = sock.wait(POLL_TIMEOUT, true, false);
+ if(ret.first) {
ConnectionManager::getInstance()->accept(sock, secure);
}
}
@@ -273,7 +275,7 @@
floodCounter = now + FLOOD_ADD;
} else {
if(false && now + FLOOD_TRIGGER < floodCounter) {
- Socket s;
+ Socket s(Socket::TYPE_TCP);
try {
s.accept(sock);
} catch(const SocketException&) {
=== modified file 'dcpp/SSLSocket.cpp'
--- dcpp/SSLSocket.cpp 2011-08-04 09:57:32 +0000
+++ dcpp/SSLSocket.cpp 2011-09-04 15:20:46 +0000
@@ -27,7 +27,7 @@
namespace dcpp {
-SSLSocket::SSLSocket(SSL_CTX* context) : ctx(context), ssl(0) {
+SSLSocket::SSLSocket(SSL_CTX* context) : Socket(TYPE_TCP), ctx(context), ssl(0) {
}
@@ -103,9 +103,9 @@
int err = SSL_get_error(ssl, ret);
switch(err) {
case SSL_ERROR_WANT_READ:
- return wait(millis, Socket::WAIT_READ) == WAIT_READ;
+ return wait(millis, true, false).first;
case SSL_ERROR_WANT_WRITE:
- return wait(millis, Socket::WAIT_WRITE) == WAIT_WRITE;
+ return wait(millis, true, false).second;
// Check if this is a fatal error...
default: checkSSL(ret);
}
@@ -164,14 +164,14 @@
return ret;
}
-int SSLSocket::wait(uint32_t millis, int waitFor) {
- if(ssl && (waitFor & Socket::WAIT_READ)) {
+std::pair<bool, bool> SSLSocket::wait(uint32_t millis, bool checkRead, bool checkWrite) {
+ if(ssl && checkRead) {
/** @todo Take writing into account as well if reading is possible? */
char c;
if(SSL_peek(ssl, &c, 1) > 0)
- return WAIT_READ;
+ return std::make_pair(true, false);
}
- return Socket::wait(millis, waitFor);
+ return Socket::wait(millis, checkRead, checkWrite);
}
bool SSLSocket::isTrusted() const noexcept {
=== modified file 'dcpp/SSLSocket.h'
--- dcpp/SSLSocket.h 2011-08-04 09:57:32 +0000
+++ dcpp/SSLSocket.h 2011-09-04 15:20:46 +0000
@@ -51,7 +51,7 @@
virtual void connect(const string& aIp, const string& aPort);
virtual int read(void* aBuffer, int aBufLen);
virtual int write(const void* aBuffer, int aLen);
- virtual int wait(uint32_t millis, int waitFor);
+ virtual std::pair<bool, bool> wait(uint32_t millis, bool checkRead, bool checkWrite);
virtual void shutdown() noexcept;
virtual void close() noexcept;
=== modified file 'dcpp/SearchManager.cpp'
--- dcpp/SearchManager.cpp 2011-08-19 18:07:56 +0000
+++ dcpp/SearchManager.cpp 2011-09-04 15:20:46 +0000
@@ -94,7 +94,6 @@
socket.reset(new Socket(Socket::TYPE_UDP));
socket->setLocalIp4(SETTING(BIND_ADDRESS));
port = socket->listen(Util::toString(SETTING(UDP_PORT)));
- socket->setBlocking(true);
start();
} catch(...) {
socket.reset();
@@ -124,13 +123,13 @@
while(!stop) {
try {
- while ( true ) {
- // @todo: remove this workaround for http://bugs.winehq.org/show_bug.cgi?id=22291
- // if that's fixed by reverting to simpler while (read(...) > 0) {...} code.
- while (socket->wait(400, Socket::WAIT_READ) != Socket::WAIT_READ);
- if (stop || (len = socket->read(&buf[0], BUFSIZE, remoteAddr)) <= 0)
- break;
+ if(!socket->wait(400, true, false).first) {
+ continue;
+ }
+
+ if((len = socket->read(&buf[0], BUFSIZE, remoteAddr)) > 0) {
onData(&buf[0], len, remoteAddr);
+ continue;
}
} catch(const SocketException& e) {
dcdebug("SearchManager::run Error: %s\n", e.getError().c_str());
@@ -141,7 +140,6 @@
try {
socket->disconnect();
port = socket->listen(Util::toString(SETTING(UDP_PORT)));
- socket->setBlocking(true);
if(failed) {
LogManager::getInstance()->message(_("Search enabled again"));
failed = false;
=== modified file 'dcpp/Socket.cpp'
--- dcpp/Socket.cpp 2011-08-27 17:42:11 +0000
+++ dcpp/Socket.cpp 2011-09-04 15:20:46 +0000
@@ -211,11 +211,8 @@
dcassert(sock4 == INVALID_SOCKET);
sock4 = s;
} else if(af == AF_INET6) {
-#ifdef IPV6_V6ONLY
+ dcassert(sock6 == INVALID_SOCKET);
setSocketOpt2(s, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-#endif
-
- dcassert(sock6 == INVALID_SOCKET);
sock6 = s;
} else {
throw SocketException(str(F_("Unknown protocol %d") % af));
@@ -248,7 +245,8 @@
}
void Socket::setBlocking(bool block) noexcept {
- setBlocking2(getSock(), block);
+ if(sock4.valid()) setBlocking2(sock4, block);
+ if(sock6.valid()) setBlocking2(sock6, block);
}
socket_t Socket::create(const addrinfo& ai) {
@@ -261,9 +259,8 @@
addr sock_addr = { { 0 } };
socklen_t sz = sizeof(sock_addr);
- auto sock = setSock(check([&] {
- return ::accept(readable(listeningSocket.sock4, listeningSocket.sock6), &sock_addr.sa, &sz);
- }), sock_addr.sa.sa_family);
+ auto sock = check([&] { return ::accept(readable(listeningSocket.sock4, listeningSocket.sock6), &sock_addr.sa, &sz); });
+ setSock(sock, sock_addr.sa.sa_family);
#ifdef _WIN32
// Make sure we disable any inherited windows message things for this socket.
@@ -280,7 +277,7 @@
auto ai = resolveAddr(/*localIp*/ "", port, AF_UNSPEC, AI_PASSIVE | AI_ADDRCONFIG);
- uint16_t p = 0;
+ uint16_t ret = 0;
// For server sockets we create both ipv4 and ipv6 if possible
// We use the same port for both sockets to deal with the fact that
@@ -288,13 +285,13 @@
for(auto a = ai.get(); a; a = a->ai_next) {
if(!sock4.valid() && a->ai_family == AF_INET) {
create(*a);
- if(p != 0) {
- ((sockaddr_in*)a->ai_addr)->sin_port = p;
+ if(ret != 0) {
+ ((sockaddr_in*)a->ai_addr)->sin_port = ret;
}
check([&] { return ::bind(sock4, a->ai_addr, a->ai_addrlen); });
check([&] { return ::getsockname(sock4, a->ai_addr, (socklen_t*)&a->ai_addrlen); });
- p = ((sockaddr_in*)a->ai_addr)->sin_port;
+ ret = ((sockaddr_in*)a->ai_addr)->sin_port;
if(type == TYPE_TCP) {
check([&] { return ::listen(sock4, 20); });
@@ -303,13 +300,13 @@
if(!sock6.valid() && a->ai_family == AF_INET6) {
create(*a);
- if(p != 0) {
- ((sockaddr_in6*)a->ai_addr)->sin6_port = p;
+ if(ret != 0) {
+ ((sockaddr_in6*)a->ai_addr)->sin6_port = ret;
}
check([&] { return ::bind(sock6, a->ai_addr, a->ai_addrlen); });
check([&] { return ::getsockname(sock6, a->ai_addr, (socklen_t*)&a->ai_addrlen); });
- p = ((sockaddr_in6*)a->ai_addr)->sin6_port;
+ ret = ((sockaddr_in6*)a->ai_addr)->sin6_port;
if(type == TYPE_TCP) {
check([&] { return ::listen(sock6, 20); });
@@ -317,10 +314,10 @@
}
}
- if(p == 0) {
+ if(ret == 0) {
throw SocketException(_("Could not open port for listening"));
}
- return ntohs(p);
+ return ntohs(ret);
}
void Socket::connect(const string& aAddr, const string& aPort, const string& localPort) {
@@ -367,7 +364,7 @@
connect(SETTING(SOCKS_SERVER), Util::toString(SETTING(SOCKS_PORT)));
- if(wait(timeLeft(start, timeout), WAIT_CONNECT) != WAIT_CONNECT) {
+ if(!waitConnected(timeLeft(start, timeout))) {
throw SocketException(_("The socks server failed establish a connection"));
}
@@ -492,7 +489,7 @@
auto len = check([&] {
return type == TYPE_TCP
? ::recv(getSock(), (char*)aBuffer, aBufLen, 0)
- : ::recvfrom(getSock(), (char*)aBuffer, aBufLen, 0, NULL, NULL);
+ : ::recvfrom(readable(sock4, sock6), (char*)aBuffer, aBufLen, 0, NULL, NULL);
}, true);
if(len > 0) {
@@ -530,7 +527,7 @@
if(j == 0) {
return i;
} else if(j == -1) {
- if(wait(timeout, WAIT_READ) != WAIT_READ) {
+ if(!wait(timeout, true, false).first) {
return i;
}
continue;
@@ -550,7 +547,7 @@
while(pos < aLen) {
int i = write(buf+pos, (int)std::min(aLen-pos, sendSize));
if(i == -1) {
- wait(timeout, WAIT_WRITE);
+ wait(timeout, false, true);
} else {
pos+=i;
stats.totalUp += i;
@@ -633,121 +630,100 @@
/**
* Blocks until timeout is reached one of the specified conditions have been fulfilled
* @param millis Max milliseconds to block.
- * @param waitFor WAIT_*** flags that set what we're waiting for, set to the combination of flags that
- * triggered the wait stop on return (==WAIT_NONE on timeout)
- * @return WAIT_*** ored together of the current state.
+ * @param checkRead Check for reading
+ * @param checkWrite Check for writing
+ * @return pair with read/write state respectively
* @throw SocketException Select or the connection attempt failed.
*/
-int Socket::wait(uint32_t millis, int waitFor) {
- timeval tv;
+std::pair<bool, bool> Socket::wait(uint32_t millis, bool checkRead, bool checkWrite) {
+ timeval tv { millis/1000, (millis%1000)*1000 };
fd_set rfd, wfd;
fd_set *rfdp = NULL, *wfdp = NULL;
- tv.tv_sec = millis/1000;
- tv.tv_usec = (millis%1000)*1000;
-
- if(waitFor & WAIT_CONNECT) {
- dcassert(!(waitFor & WAIT_READ) && !(waitFor & WAIT_WRITE));
-
- check([&] () -> int {
- FD_ZERO(&wfd);
-
- int nfds = -1;
- if(sock4.valid()) {
- FD_SET(sock4, &wfd);
- nfds = std::max((int)sock4, nfds);
- }
-
- if(sock6.valid()) {
- FD_SET(sock6, &wfd);
- nfds = std::max((int)sock6, nfds);
- }
-
- return ::select(nfds + 1, NULL, &wfd, NULL, &tv);
- });
-
- if(sock6.valid() && FD_ISSET(sock6, &wfd)) {
- int err6 = getSocketOptInt2(sock6, SO_ERROR);
- if(err6 == 0) {
- sock4.reset(); // We won't be needing this any more...
-
- return WAIT_CONNECT;
- }
-
- if(!sock4.valid()) {
- throw SocketException(err6);
- }
-
- sock6.reset();
- }
-
- if(sock4.valid() && FD_ISSET(sock4, &wfd)) {
- int err4 = getSocketOptInt2(sock4, SO_ERROR);
- if(err4 == 0) {
- sock6.reset(); // We won't be needing this any more...
- return WAIT_CONNECT;
- }
-
- if(!sock6.valid()) {
- throw SocketException(err4);
- }
-
- sock4.reset();
- }
-
- return 0;
- }
-
- check([&] () -> int {
- int nfds = -1;
-
- if(waitFor & WAIT_READ) {
- dcassert(!(waitFor & WAIT_CONNECT));
- rfdp = &rfd;
- FD_ZERO(rfdp);
- if(sock4.valid()) {
- FD_SET(sock4, &rfd);
- nfds = std::max((int)sock4, nfds);
- }
-
- if(sock6.valid()) {
- FD_SET(sock6, &rfd);
- nfds = std::max((int)sock6, nfds);
- }
- }
-
- if(waitFor & WAIT_WRITE) {
- dcassert(!(waitFor & WAIT_CONNECT));
- wfdp = &wfd;
- FD_ZERO(wfdp);
- if(sock4.valid()) {
- FD_SET(sock4, &wfd);
- nfds = std::max((int)sock4, nfds);
- }
-
- if(sock6.valid()) {
- FD_SET(sock6, &wfd);
- nfds = std::max((int)sock6, nfds);
- }
- }
-
- return ::select(nfds + 1, rfdp, wfdp, NULL, &tv);
- });
-
- waitFor = WAIT_NONE;
-
- if(rfdp && ((sock4.valid() && FD_ISSET(sock4, rfdp)) || (sock6.valid() && FD_ISSET(sock6, rfdp)))) {
- waitFor |= WAIT_READ;
- }
-
- if(wfdp && ((sock4.valid() && FD_ISSET(sock4, wfdp)) || (sock6.valid() && FD_ISSET(sock6, wfdp)))) {
- waitFor |= WAIT_WRITE;
- }
-
- return waitFor;
+
+ int nfds = -1;
+
+ if(checkRead) {
+ rfdp = &rfd;
+ FD_ZERO(rfdp);
+ if(sock4.valid()) {
+ FD_SET(sock4, &rfd);
+ nfds = std::max((int)sock4, nfds);
+ }
+
+ if(sock6.valid()) {
+ FD_SET(sock6, &rfd);
+ nfds = std::max((int)sock6, nfds);
+ }
+ }
+
+ if(checkWrite) {
+ wfdp = &wfd;
+ FD_ZERO(wfdp);
+ if(sock4.valid()) {
+ FD_SET(sock4, &wfd);
+ nfds = std::max((int)sock4, nfds);
+ }
+
+ if(sock6.valid()) {
+ FD_SET(sock6, &wfd);
+ nfds = std::max((int)sock6, nfds);
+ }
+ }
+
+ check([&] { return ::select(nfds + 1, rfdp, wfdp, NULL, &tv); });
+
+ return std::make_pair(
+ rfdp && ((sock4.valid() && FD_ISSET(sock4, rfdp)) || (sock6.valid() && FD_ISSET(sock6, rfdp))),
+ wfdp && ((sock4.valid() && FD_ISSET(sock4, wfdp)) || (sock6.valid() && FD_ISSET(sock6, wfdp))));
}
bool Socket::waitConnected(uint32_t millis) {
- return wait(millis, Socket::WAIT_CONNECT) == WAIT_CONNECT;
+ timeval tv = { millis/1000, (millis%1000)*1000 };
+ fd_set fd;
+ FD_ZERO(&fd);
+
+ int nfds = -1;
+ if(sock4.valid()) {
+ FD_SET(sock4, &fd);
+ nfds = sock4;
+ }
+
+ if(sock6.valid()) {
+ FD_SET(sock6, &fd);
+ nfds = std::max((int)sock6, nfds);
+ }
+
+ check([&] { return ::select(nfds + 1, NULL, &fd, NULL, &tv); });
+
+ if(sock6.valid() && FD_ISSET(sock6, &fd)) {
+ int err6 = getSocketOptInt2(sock6, SO_ERROR);
+ if(err6 == 0) {
+ sock4.reset(); // We won't be needing this any more...
+ return true;
+ }
+
+ if(!sock4.valid()) {
+ throw SocketException(err6);
+ }
+
+ sock6.reset();
+ }
+
+ if(sock4.valid() && FD_ISSET(sock4, &fd)) {
+ int err4 = getSocketOptInt2(sock4, SO_ERROR);
+ if(err4 == 0) {
+ sock6.reset(); // We won't be needing this any more...
+ return true;
+ }
+
+ if(!sock6.valid()) {
+ throw SocketException(err4);
+ }
+
+ sock4.reset();
+ }
+
+ return false;
}
bool Socket::waitAccepted(uint32_t millis) {
@@ -838,7 +814,7 @@
if(SETTING(OUTGOING_CONNECTIONS) == SettingsManager::OUTGOING_SOCKS5) {
try {
- Socket s;
+ Socket s(TYPE_TCP);
s.setBlocking(false);
s.connect(SETTING(SOCKS_SERVER), static_cast<uint16_t>(SETTING(SOCKS_PORT)));
s.socksAuth(SOCKS_TIMEOUT);
@@ -874,7 +850,8 @@
}
void Socket::shutdown() noexcept {
- ::shutdown(getSock(), 2);
+ if(sock4.valid()) ::shutdown(sock4, 2);
+ if(sock6.valid()) ::shutdown(sock6, 2);
}
void Socket::close() noexcept {
=== modified file 'dcpp/Socket.h'
--- dcpp/Socket.h 2011-08-19 18:07:56 +0000
+++ dcpp/Socket.h 2011-09-04 15:20:46 +0000
@@ -83,19 +83,12 @@
class Socket : boost::noncopyable
{
public:
- enum {
- WAIT_NONE = 0x00,
- WAIT_CONNECT = 0x01,
- WAIT_READ = 0x02,
- WAIT_WRITE = 0x04
- };
-
enum SocketType {
TYPE_TCP = IPPROTO_TCP,
TYPE_UDP = IPPROTO_UDP
};
- Socket(SocketType type = TYPE_TCP) : type(type) { }
+ explicit Socket(SocketType type) : type(type) { }
virtual ~Socket() { }
@@ -157,7 +150,7 @@
*/
int readAll(void* aBuffer, int aBufLen, uint32_t timeout = 0);
- virtual int wait(uint32_t millis, int waitFor);
+ virtual std::pair<bool, bool> wait(uint32_t millis, bool checkRead, bool checkWrite);
typedef std::unique_ptr<addrinfo, decltype(&freeaddrinfo)> addrinfo_p;
static string resolve(const string& aDns, int af = AF_UNSPEC);