------------------------------------------------------------ revno: 2605 committer: Jacek Sieka <arnethed...@gmail.com> 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);
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp