--- 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 <vector>
#include <memory>
#include <regex>
+#include <iostream>
+#include <netdb.h>
#include "Socket.h"
@@ -62,6 +64,53 @@
else throw std::logic_error("Got error result: " + std::to_string(result) + " - " + message);
}
+template <typename T> 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<sockaddr_in>(ai, AF_INET)) std::cerr << " IPv4=" << ip2string(ai);
+ else if (sockaddr_in6 * sa = castAddress<sockaddr_in6>(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<sockaddr_in>(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<UDPClientSocket> s = std::make_shared<UDPClientSocket>();
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<TCPClientSocket> s = std::make_shared<TCPClientSocket>();
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<std::shared_ptr<SocketFactory>> factories
{
std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_CLIENT, MODE_STREAM, TCPClientSocket >> (),
- std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
- std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_TCP, ROLE_SERVER, MODE_STREAM, TCPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (),
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_SCTP, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_CLIENT, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_STREAM, UDPClientSocket >> (), // TODO: correct class
+ std::make_shared<TemplateSocketFactory<PROTOCOL_UDS, ROLE_SERVER, MODE_DATAGRAM, UDPClientSocket >> (), // TODO: correct class
};
std::shared_ptr<SocketFactory> SocketFactory::find(const SocketOptions& options) {