#include "../include/sibs/IpAddress.hpp" #include #if OS_FAMILY == OS_FAMILY_WINDOWS // Source: https://stackoverflow.com/questions/15370033/how-to-use-inet-pton-with-the-mingw-compiler #define NS_INADDRSZ 4 #define NS_IN6ADDRSZ 16 #define NS_INT16SZ 2 int inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: return inet_pton4(src, dst); case AF_INET6: return inet_pton6(src, dst); default: return -1; } } int inet_pton4(const char *src, void *_dst) { char *dst = (char*)_dst; uint8_t tmp[NS_INADDRSZ], *tp; int saw_digit = 0; int octets = 0; *(tp = tmp) = 0; int ch; while ((ch = *src++) != '\0') { if (ch >= '0' && ch <= '9') { uint32_t n = *tp * 10 + (ch - '0'); if (saw_digit && *tp == 0) return 0; if (n > 255) return 0; *tp = n; if (!saw_digit) { if (++octets > 4) return 0; saw_digit = 1; } } else if (ch == '.' && saw_digit) { if (octets == 4) return 0; *++tp = 0; saw_digit = 0; } else return 0; } if (octets < 4) return 0; memcpy(dst, tmp, NS_INADDRSZ); return 1; } int inet_pton6(const char *src, void *_dst) { char *dst = (char*)_dst; static const char xdigits[] = "0123456789abcdef"; uint8_t tmp[NS_IN6ADDRSZ]; uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); uint8_t *endp = tp + NS_IN6ADDRSZ; uint8_t *colonp = NULL; /* Leading :: requires some special handling. */ if (*src == ':') { if (*++src != ':') return 0; } const char *curtok = src; int saw_xdigit = 0; uint32_t val = 0; int ch; while ((ch = tolower(*src++)) != '\0') { const char *pch = strchr(xdigits, ch); if (pch != NULL) { val <<= 4; val |= (pch - xdigits); if (val > 0xffff) return 0; saw_xdigit = 1; continue; } if (ch == ':') { curtok = src; if (!saw_xdigit) { if (colonp) return 0; colonp = tp; continue; } else if (*src == '\0') { return 0; } if (tp + NS_INT16SZ > endp) return 0; *tp++ = (uint8_t) (val >> 8) & 0xff; *tp++ = (uint8_t) val & 0xff; saw_xdigit = 0; val = 0; continue; } if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, (char*) tp) > 0) { tp += NS_INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } return 0; } if (saw_xdigit) { if (tp + NS_INT16SZ > endp) return 0; *tp++ = (uint8_t) (val >> 8) & 0xff; *tp++ = (uint8_t) val & 0xff; } if (colonp != NULL) { /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const int n = tp - colonp; if (tp == endp) return 0; for (int i = 1; i <= n; i++) { endp[-i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if (tp != endp) return 0; memcpy(dst, tmp, NS_IN6ADDRSZ); return 1; } #endif namespace sibs { Ipv4::Ipv4() : Ipv4(nullptr, 0) { } Ipv4::Ipv4(const char *ip, unsigned short port) { address.sin_family = AF_INET; address.sin_port = htons(port); if(ip) { if(strlen(ip) > 15) throw InvalidAddressException("Ip address is too long"); if(inet_pton(AF_INET, ip, &address.sin_addr.s_addr) != 1) { std::string errMsg = "Ip "; errMsg += ip; errMsg += " is not a valid ip"; throw InvalidAddressException(errMsg); } } else address.sin_addr.s_addr = INADDR_ANY; memset(address.sin_zero, 0, sizeof(address.sin_zero)); } Ipv4::Ipv4(u16 family, u32 addr, u16 port) { address.sin_family = family; address.sin_addr.s_addr = addr; address.sin_port = port; memset(address.sin_zero, 0, sizeof(address.sin_zero)); } Ipv4::Ipv4(const Ipv4 &other) { memcpy(&address, &other.address, sizeof(address)); } Ipv4& Ipv4::operator = (const Ipv4 &other) { memcpy(&address, &other.address, sizeof(address)); return *this; } std::string Ipv4::getAddress() const { std::string result; const int addrLen = sizeof(address); char host[NI_MAXHOST]; char service[NI_MAXSERV]; getnameinfo((sockaddr *)&address, addrLen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); result += host; return result; } unsigned short Ipv4::getPort() const { return ntohs(address.sin_port); } bool Ipv4::operator == (const Ipv4 &other) const { return address.sin_addr.s_addr == other.address.sin_addr.s_addr && address.sin_port == other.address.sin_port; } bool Ipv4::operator != (const Ipv4 &other) const { return !(*this == other); } }