← Back to team overview

linuxdcpp-team team mailing list archive

[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);