The problem is the following: I wrote a general initNetAddressFromEndpoint which by IP address (IPv4, IPv6, domain name) and the port gives us the sockaddr_storage structure. Later this structure is passed to the connect method (it is cast to sockaddr before). I transfer to this f-ii the domain name of the machine on which the dual tcp / ip stack is - so we can connect to it both via IPv4 and IPv6 (the server listens to both unspec addresses: 0.0.0.0 and :: :). Connection over IPv4 is successful, over IPv6 - without success. Maybe doing something wrong?
PS Something I am doing wrong - rather, it is worth interpreting as "point to obvious mistakes, if any". I understand that this code is not enough to create a complete picture of the work of software.
Source:
#if defined( _WIN32 ) && ( NTDDI_VERSION >= NTDDI_VISTA ) typedef sockaddr_in *psockaddr_in4, *psockaddr_out4; typedef sockaddr_in6 *psockaddr_in6, *psockaddr_out6; #define from_storage( SOSKADDRSTORAGE ) \ const_cast<sockaddr_storage*>( SOSKADDRSTORAGE ) #else typedef sockaddr_in const *psockaddr_in4; typedef sockaddr_in *psockaddr_out4; typedef sockaddr_in6 const *psockaddr_in6; typedef sockaddr_in6 *psockaddr_out6; #define from_storage( SOSKADDRSTORAGE ) \ SOSKADDRSTORAGE #endif void CNetUtils::initNetAddressFromEndpoint( int inFamily , sockaddr_storage *outAddrPtr , CStringUtf8 const& inAddrStr , unsigned inPort ) { memset( outAddrPtr, 0, sizeof( sockaddr_storage ) ); struct addrinfo hints; memset( &hints, 0, sizeof( hints ) ); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if( inFamily == AF_INET6 ) { psockaddr_out6 addr6 = reinterpret_cast<psockaddr_out6>( outAddrPtr ); addr6->sin6_family = AF_INET6; addr6->sin6_port = htons( static_cast<unsigned short>( inPort ) ); if( inAddrStr == UNSPEC_IPV6_ADDRESS ) { addr6->sin6_addr = in6addr_any; return; } } else { psockaddr_out4 addr4 = reinterpret_cast<psockaddr_out4>( outAddrPtr ); addr4->sin_family = AF_INET; addr4->sin_port = htons( static_cast<unsigned short>( inPort ) ); if( inAddrStr == UNSPEC_IPV4_ADDRESS ) { #ifdef _WIN32 addr4->sin_addr = in4addr_any; #else addr4->sin_addr.s_addr = INADDR_ANY; #endif return; } } sockaddr_storage saddr; int rc = 0; if( inFamily == AF_INET6 ) rc = ::inet_pton( inFamily, inAddrStr.c_str(), &reinterpret_cast<psockaddr_out6>(&saddr)->sin6_addr ); else rc = ::inet_pton( inFamily, inAddrStr.c_str(), &reinterpret_cast<psockaddr_out4>(&saddr)->sin_addr ); if( rc ) { hints.ai_family = inFamily; hints.ai_flags |= AI_NUMERICHOST; } InetAddressFormat iaf_dummy = iafUnknown; SockAddresses sockAddrs; getAvailableSockAddresses( sockAddrs, iaf_dummy, inAddrStr, inPort ); if( sockAddrs.empty() ) { #ifdef _WIN32 ENetStatusException e( "CSimpleSocket: getaddrinfo failed", getSocketErrorCode() ); #else const char *err_str = gai_strerror( rc ); ENetException e( err_str ); #endif throw e; } SockAddresses::const_iterator saIt = std::find_if( sockAddrs.cbegin(), sockAddrs.cend(), [=]( SockAddrInfo const& sa ) -> bool { return sa.p_family == inFamily; } ); // this shouldn't happen if( saIt == sockAddrs.cend() ) { CStringBuilder buf; buf << "Error in CNetUtils::initNetAddressFromEndpoint: \n" << "attempt to init netaddress for unreachable inet family [ " << "inetFamilyCode=" << inFamily << " ] "; throw ENetException( buf.text() ); } SockAddrInfo const& sa = *saIt; if( inFamily == AF_INET6 ) { memcpy( &reinterpret_cast<psockaddr_out6>( outAddrPtr )->sin6_addr , &sa.p_addr , sa.p_addr_len ); } else { memcpy( &reinterpret_cast<psockaddr_out4>( outAddrPtr )->sin_addr , &sa.p_addr , sa.p_addr_len ); } if( inFamily == AF_INET6 ) { psockaddr_out6 addr6 = reinterpret_cast<psockaddr_out6>( outAddrPtr ); addr6->sin6_family = AF_INET6; addr6->sin6_port = htons( static_cast<unsigned short>( inPort ) ); } else { psockaddr_out4 addr4 = reinterpret_cast<psockaddr_out4>( outAddrPtr ); addr4->sin_family = AF_INET; addr4->sin_port = htons( static_cast<unsigned short>( inPort ) ); } } getAvailableSockAddresses - by IP / port gives us all possible sockaddr's
void CNetUtils::getAvailableSockAddresses( SockAddresses& outAddresses , InetAddressFormat& outUnspecAddr , CStringUtf8 const& inAddrStr , unsigned inPort ) { if( inAddrStr == UNSPEC_IPV4_ADDRESS ) { outUnspecAddr = iafIPv4; return; } if( inAddrStr == UNSPEC_IPV6_ADDRESS ) { outUnspecAddr = iafIPv6; return; } struct addrinfo hints, *resaddr = 0; memset( &hints, 0, sizeof( hints ) ); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; int rc = getaddrinfo( inAddrStr.c_str(), CStringUtf8::fromInt32( inPort ).c_str(), &hints, &resaddr ); if( rc == 0 ) { struct addrinfo *ai = resaddr; while( ai != 0 ) { SockAddrInfo sa; sa.p_family = ai->ai_family; sa.p_sock_type = ai->ai_socktype; sa.p_addr_len = ai->ai_addrlen; memcpy( &sa.p_addr, ai->ai_addr, sizeof( struct sockaddr ) ); outAddresses.push_back( sa ); ai = ai->ai_next; } } if( resaddr ) freeaddrinfo( resaddr ); }