# HG changeset patch # User František Kučera # Date 1659572002 -7200 # Node ID 6a6b9350785629bc9d5cce8d1688ed78cd6b4064 # Parent de48b927821149149dcd54ba64c9eb52ad3eb13b use getaddrinfo(), inet_ntop(), some DNS and IPv4 support diff -r de48b9278211 -r 6a6b93507856 src/Socket.cpp --- a/src/Socket.cpp Sat Jul 30 23:25:23 2022 +0200 +++ b/src/Socket.cpp Thu Aug 04 02:13:22 2022 +0200 @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "Socket.h" @@ -62,6 +64,53 @@ else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message); } +template static T* castAddress(addrinfo* ai, sa_family_t family) { + if (ai && ai->ai_family == family && sizeof (T) == ai->ai_addrlen) return (T*) ai->ai_addr; + else return nullptr; +} + +static std::string ip2string(const addrinfo* ai) { + //char buffer[INET_ADDRSTRLEN] = {0}; + char buffer[INET6_ADDRSTRLEN] = {0}; + //return inet_ntop(ai->ai_family, &ai->ai_addr, buffer, sizeof (buffer)); + //return inet_ntop(ai->ai_family, &ai->ai_addr->sa_data, buffer, sizeof (buffer)); + if (ai->ai_family == AF_INET) return inet_ntop(ai->ai_family, &((sockaddr_in const *) ai->ai_addr)->sin_addr, buffer, sizeof (buffer)); // TODO: check 0 result + else if (ai->ai_family == AF_INET6) return inet_ntop(ai->ai_family, &((sockaddr_in6 const *) ai->ai_addr)->sin6_addr, buffer, sizeof (buffer)); // TODO: check 0 result + else throw std::logic_error("Invalid address family: " + std::to_string(ai->ai_family)); +} + +static in_addr_t getAddress(const std::string& host) { + + struct addrinfo* addrInfo; + check(getaddrinfo(host.c_str(), "", nullptr, &addrInfo), "getaddrinfo"); + + std::cerr << "found: " << addrInfo << std::endl; + if (addrInfo) { + for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) { + std::cerr << "address info: family=" << std::to_string(ai->ai_addr->sa_family); + if (sockaddr_in * sa = castAddress(ai, AF_INET)) std::cerr << " IPv4=" << ip2string(ai); + else if (sockaddr_in6 * sa = castAddress(ai, AF_INET6)) std::cerr << " IPv6=" << ip2string(ai); + std::cerr << std::endl; + } + } + + if (addrInfo) { + for (addrinfo* ai = addrInfo; ai; ai = ai->ai_next) { + if (sockaddr_in * sa = castAddress(ai, AF_INET)) { + in_addr_t address = sa->sin_addr.s_addr; + freeaddrinfo(addrInfo); + return address; + + } + } + } + + freeaddrinfo(addrInfo); + + // TODO: rather throw exception – requires IP address in the host string: + return inet_addr(host.c_str()); +} + class UDPClientSocket : public Socket { private: struct sockaddr_in remoteAddress; @@ -73,7 +122,7 @@ std::shared_ptr s = std::make_shared(); memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); s->remoteAddress.sin_family = AF_INET; - s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) + s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true)); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); auto protocol = findOption(options, OPTION_PROTOCOL); @@ -106,7 +155,7 @@ std::shared_ptr s = std::make_shared(); memset((char *) &s->remoteAddress, 0, sizeof (s->remoteAddress)); s->remoteAddress.sin_family = AF_INET; - s->remoteAddress.sin_addr.s_addr = inet_addr(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) + s->remoteAddress.sin_addr.s_addr = getAddress(findOption(options, OPTION_HOST, true).c_str()); // TODO: use getaddrinfo() instead (because of error -1 = 255.255.255.255) s->remoteAddress.sin_port = htons(std::stoi(findOption(options, OPTION_PORT, true))); return s; } @@ -144,17 +193,17 @@ static std::vector> factories { std::make_shared> (), - std::make_shared> (), // TODO: correct class - std::make_shared> (), - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class - std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class + std::make_shared> (), // TODO: correct class }; std::shared_ptr SocketFactory::find(const SocketOptions& options) {