| 104 | } |
| 105 | |
| 106 | void HostAddress::set(String const& address) { |
| 107 | if (address.empty()) |
| 108 | return; |
| 109 | |
| 110 | if (address.compare("*") == 0 || address.compare("0.0.0.0") == 0) { |
| 111 | uint8_t inaddr_any[4]; |
| 112 | memset(inaddr_any, 0, sizeof(inaddr_any)); |
| 113 | set(NetworkMode::IPv4, inaddr_any); |
| 114 | } else if (address.compare("::") == 0) { |
| 115 | // NOTE: This will likely bind to both IPv6 and IPv4, but it does depending |
| 116 | // on the OS settings |
| 117 | uint8_t inaddr_any[16]; |
| 118 | memset(inaddr_any, 0, sizeof(inaddr_any)); |
| 119 | set(NetworkMode::IPv6, inaddr_any); |
| 120 | } else { |
| 121 | struct addrinfo* result = NULL; |
| 122 | struct addrinfo* ptr = NULL; |
| 123 | struct addrinfo hints; |
| 124 | |
| 125 | memset(&hints, 0, sizeof(hints)); |
| 126 | hints.ai_family = AF_UNSPEC; |
| 127 | // Eliminate duplicates being returned one for each socket type. |
| 128 | // As we're not using the return socket type or protocol this doesn't effect |
| 129 | // us. |
| 130 | hints.ai_socktype = SOCK_STREAM; |
| 131 | hints.ai_protocol = IPPROTO_TCP; |
| 132 | // Request only usable addresses e.g. IPv6 only if IPv6 is available |
| 133 | hints.ai_flags = AI_ADDRCONFIG; |
| 134 | |
| 135 | if (::getaddrinfo(address.utf8Ptr(), NULL, &hints, &result) != 0) |
| 136 | throw NetworkException(strf("Failed to determine address for '{}' ({})", address, netErrorString())); |
| 137 | |
| 138 | for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { |
| 139 | NetworkMode mode; |
| 140 | switch (ptr->ai_family) { |
| 141 | case AF_INET: |
| 142 | mode = NetworkMode::IPv4; |
| 143 | break; |
| 144 | case AF_INET6: |
| 145 | mode = NetworkMode::IPv6; |
| 146 | break; |
| 147 | default: |
| 148 | continue; |
| 149 | } |
| 150 | if (mode == NetworkMode::IPv4) { |
| 151 | struct sockaddr_in* info = (struct sockaddr_in*)ptr->ai_addr; |
| 152 | set(mode, (uint8_t*)(&info->sin_addr)); |
| 153 | } else { |
| 154 | struct sockaddr_in6* info = (struct sockaddr_in6*)ptr->ai_addr; |
| 155 | set(mode, (uint8_t*)(&info->sin6_addr)); |
| 156 | } |
| 157 | break; |
| 158 | } |
| 159 | freeaddrinfo(result); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | void HostAddress::set(NetworkMode mode, uint8_t const* addr) { |