! * \ingroup network * \brief Parse a textual IPv4 or IPv6 address * \return true If successful * * From http://rosettacode.org/wiki/Parse_an_IP_Address * Parse a textual IPv4 or IPv6 address, optionally with port, into a binary * array (for the address, in host order), and an optionally provided port. * Also, indicate which of those forms (4 or 6) was parsed. * * \param addressPtr C-str
| 201 | * \remark Produces a NazaraAssert if result is invalid |
| 202 | */ |
| 203 | bool ParseIPAddress(const char* addressPtr, UInt8 result[16], UInt16* port, bool* isIPv6, const char** endOfRead) |
| 204 | { |
| 205 | NazaraAssert(addressPtr, "Invalid address string"); |
| 206 | NazaraAssert(result, "Invalid result pointer"); |
| 207 | |
| 208 | //find first colon, dot, and open bracket |
| 209 | const char* colonPtr = std::strchr(addressPtr, ':'); |
| 210 | const char* dotPtr = std::strchr(addressPtr, '.'); |
| 211 | const char* openBracketPtr = std::strchr(addressPtr, '['); |
| 212 | |
| 213 | // we'll consider this to (probably) be IPv6 if we find an open |
| 214 | // bracket, or an absence of dots, or if there is a colon, and it |
| 215 | // precedes any dots that may or may not be there |
| 216 | bool detectedIPv6 = openBracketPtr || !dotPtr || (colonPtr && (!dotPtr || colonPtr < dotPtr)); |
| 217 | |
| 218 | // OK, now do a little further sanity check our initial guess... |
| 219 | if (detectedIPv6) |
| 220 | { |
| 221 | // if open bracket, then must have close bracket that follows somewhere |
| 222 | const char* closeBracketPtr = std::strchr(addressPtr, ']'); |
| 223 | if (openBracketPtr && (!closeBracketPtr || closeBracketPtr < openBracketPtr)) |
| 224 | return false; |
| 225 | } |
| 226 | else // probably ipv4 |
| 227 | { |
| 228 | // dots must exist, and precede any colons |
| 229 | if (!dotPtr || (colonPtr && colonPtr < dotPtr)) |
| 230 | return false; |
| 231 | } |
| 232 | |
| 233 | // OK, there should be no correctly formed strings which are miscategorized, |
| 234 | // and now any format errors will be found out as we continue parsing |
| 235 | // according to plan. |
| 236 | if (!detectedIPv6) //try to parse as IPv4 |
| 237 | { |
| 238 | // 4 dotted quad decimal; optional port if there is a colon |
| 239 | // since there are just 4, and because the last one can be terminated |
| 240 | // differently, I'm just going to unroll any potential loop. |
| 241 | UInt8* resultPtr = result; |
| 242 | |
| 243 | for (unsigned int i = 0; i < 4; ++i) |
| 244 | { |
| 245 | unsigned int value; |
| 246 | if (!Detail::ParseDecimal(addressPtr, &value, &addressPtr) || value > 255) //must be in range and followed by dot and nonempty |
| 247 | return false; |
| 248 | |
| 249 | if (i != 3) |
| 250 | { |
| 251 | if (*addressPtr != '.') |
| 252 | return false; |
| 253 | |
| 254 | addressPtr++; |
| 255 | } |
| 256 | |
| 257 | *resultPtr++ = static_cast<UInt8>(value); |
| 258 | } |
| 259 | } |
| 260 | else // try to parse as IPv6 |
no test coverage detected