diff -u nzbget-0.4.0-testing/Connection.cpp nzbget-0.4.0-testing-ipv6/Connection.cpp --- nzbget-0.4.0-testing/Connection.cpp 2008-03-18 17:31:44.000000000 +0000 +++ nzbget-0.4.0-testing-ipv6/Connection.cpp 2008-04-18 14:23:52.000000000 +0100 @@ -278,90 +278,45 @@ int Connection::DoConnect() { - debug("Do connecting"); + debug("Do connecting"); - struct sockaddr_in sSocketAddress; - memset(&sSocketAddress, '\0', sizeof(sSocketAddress)); - sSocketAddress.sin_family = AF_INET; - sSocketAddress.sin_port = htons(m_pNetAddress->GetPort()); - sSocketAddress.sin_addr.s_addr = ResolveHostAddr(m_pNetAddress->GetHost()); - if (sSocketAddress.sin_addr.s_addr == (unsigned int)-1) - { - return -1; - } + int res; - m_iSocket = socket(PF_INET, SOCK_STREAM, 0); + struct addrinfo addr_hints, *addr_list, *addr; + char iPortStr[sizeof(int) * 4 + 1]; //is enough to hold any converted int - if (m_iSocket == INVALID_SOCKET) - { - ReportError("Socket creation failed for %s!", m_pNetAddress->GetHost(), 0); - return -1; - } + memset(&addr_hints, 0, sizeof(addr_hints)); + addr_hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + addr_hints.ai_socktype = SOCK_STREAM, - int res = connect(m_iSocket , (struct sockaddr *) & sSocketAddress, sizeof(sSocketAddress)); + sprintf(iPortStr, "%d", m_pNetAddress->GetPort()); - if (res < 0) - { - ReportError("Connection to %s failed!", m_pNetAddress->GetHost(), 0); - return -1; - } + res = ::getaddrinfo( m_pNetAddress->GetHost(), iPortStr, &addr_hints, &addr_list ); -#ifdef WIN32 - int MSecVal = m_iTimeout * 1000; - int err = setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&MSecVal, sizeof(MSecVal)); -#else - struct timeval TimeVal; - TimeVal.tv_sec = m_iTimeout; - TimeVal.tv_usec = 0; - int err = setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&TimeVal, sizeof(TimeVal)); -#endif - if (err != 0) - { - ReportError("setsockopt failed", NULL, 0); - } + if( res != 0 ) + { + error("Could not resolve hostname %s", m_pNetAddress->GetHost()); + return -1; + } - return 0; -} + for (addr = addr_list; addr != NULL; addr = addr->ai_next) + { + m_iSocket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (m_iSocket == -1) continue; -unsigned int Connection::ResolveHostAddr(const char* szHost) -{ - unsigned int uaddr = inet_addr(szHost); - if (uaddr == (unsigned int)-1) - { - struct hostent* hinfo; - bool err = false; - int h_errnop = 0; -#ifdef WIN32 - hinfo = gethostbyname(szHost); - err = hinfo == NULL; - h_errnop = WSAGetLastError(); -#else - struct hostent hinfobuf; - static const int strbuflen = 1024; - char* strbuf = (char*)malloc(strbuflen); -#ifdef HAVE_GETHOSTBYNAME_R_6 - err = gethostbyname_r(szHost, &hinfobuf, strbuf, strbuflen, &hinfo, &h_errnop); - err = err || (hinfo == NULL); // error on null hinfo (means 'no entry') -#else - hinfo = gethostbyname_r(szHost, &hinfobuf, strbuf, strbuflen, &h_errnop); - err = hinfo == NULL; -#endif -#endif - if (err) - { - ReportError("Could not resolve hostname %s", szHost, h_errnop); -#ifndef WIN32 - free(strbuf); -#endif - return (unsigned int)-1; - } + res = ::connect( m_iSocket , addr->ai_addr, addr->ai_addrlen ); + if (res != -1) break; /* Connection established */ + } - memcpy(&uaddr, hinfo->h_addr_list[0], sizeof(uaddr)); -#ifndef WIN32 - free(strbuf); -#endif - } - return uaddr; + if( addr == NULL ) + { + error("Socket creation or connection failed for %s!", m_pNetAddress->GetHost()); + return -1; + } + + freeaddrinfo( addr_list ); /* No longer needed */ + + return 0; } int Connection::DoDisconnect() @@ -459,37 +414,42 @@ { debug("Do binding"); - m_iSocket = socket(PF_INET, SOCK_STREAM, 0); - if (m_iSocket == INVALID_SOCKET) - { - ReportError("Socket creation failed for %s!", m_pNetAddress->GetHost(), 0); - return -1; - } + int res; - struct sockaddr_in sSocketAddress; - memset(&sSocketAddress, '\0', sizeof(sSocketAddress)); - sSocketAddress.sin_family = AF_INET; - if (!m_pNetAddress->GetHost() || strlen(m_pNetAddress->GetHost()) == 0) - { - sSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY); - } - else - { - sSocketAddress.sin_addr.s_addr = ResolveHostAddr(m_pNetAddress->GetHost()); - if (sSocketAddress.sin_addr.s_addr == (unsigned int)-1) - { - return -1; - } - } - sSocketAddress.sin_port = htons(m_pNetAddress->GetPort()); + struct addrinfo addr_hints, *addr_list, *addr; + char iPortStr[sizeof(int) * 4 + 1]; //is enough to hold any converted int + + memset(&addr_hints, 0, sizeof(addr_hints)); + addr_hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + addr_hints.ai_socktype = SOCK_STREAM, + addr_hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + + sprintf(iPortStr, "%d", m_pNetAddress->GetPort()); + + res = ::getaddrinfo( m_pNetAddress->GetHost(), iPortStr, &addr_hints, &addr_list ); + + if( res != 0 ) + { + error( "Could not resolve hostname %s", m_pNetAddress->GetHost() ); + return -1; + } + + for (addr = addr_list; addr != NULL; addr = addr->ai_next) + { + m_iSocket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (m_iSocket == -1) continue; int opt = 1; setsockopt(m_iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)); + res = ::bind( m_iSocket , addr->ai_addr, addr->ai_addrlen ); + if (res != -1) break; /* Connection established */ + } + + if( addr == NULL ) + { + error("Socket creation or binding failed for %s!", m_pNetAddress->GetHost() ); + return -1; + } - if (bind(m_iSocket, (struct sockaddr *) &sSocketAddress, sizeof(sSocketAddress)) < 0) - { - ReportError("Binding socket failed for %s", m_pNetAddress->GetHost(), 0); - return -1; - } if (listen(m_iSocket, 10) < 0) { diff -u nzbget-0.4.0-testing/Connection.h nzbget-0.4.0-testing-ipv6/Connection.h --- nzbget-0.4.0-testing/Connection.h 2008-03-18 17:31:31.000000000 +0000 +++ nzbget-0.4.0-testing-ipv6/Connection.h 2008-04-18 14:13:50.000000000 +0100 @@ -51,7 +51,6 @@ bool m_bSuppressErrors; bool m_bAutoClose; - unsigned int ResolveHostAddr(const char* szHost); void ReportError(const char* szMsgPrefix, const char* szMsgArg, int ErrCode); virtual int DoConnect(); virtual int DoDisconnect();