MCPcopy Create free account
hub / github.com/SFML/SFML / getPublicAddress

Method getPublicAddress

src/SFML/Network/IpAddress.cpp:332–412  ·  view source on GitHub ↗

///////////////////////////////////////////////////////

Source from the content-addressed store, hash-verified

330
331////////////////////////////////////////////////////////////
332std::optional<IpAddress> IpAddress::getPublicAddress(Time timeout, std::optional<Type> type, bool secure)
333{
334 // The trick here is more complicated, because the only way
335 // to get our public IP address is to get it from a distant computer.
336
337 // Our own DNS implementation does not support DNSSEC, DNS-over-TLS or DNS-over-HTTPS
338 // Both DoT and DoH require communication over a TLS connection anyway
339 // so there is no advantage when using DNS to perform secure queries instead of HTTPS
340 if (!secure)
341 {
342 // Try first via DNS query
343 if (!type.has_value())
344 {
345 // No type preference, try IPv6 then IPv4
346 if (const auto addressViaDns = Dns::getPublicAddress(timeout, IpAddress::Type::IpV6); addressViaDns)
347 return addressViaDns;
348
349 if (const auto addressViaDns = Dns::getPublicAddress(timeout, IpAddress::Type::IpV4); addressViaDns)
350 return addressViaDns;
351 }
352 else
353 {
354 if (const auto addressViaDns = Dns::getPublicAddress(timeout, *type); addressViaDns)
355 return addressViaDns;
356 }
357 }
358
359 // DNS query wasn't successful, try via HTTP
360 // Here we get the web page from e.g. http://ifconfig.co/ip
361 // and parse the result to extract our IP address
362 // (not very hard: the web page contains only our IP address).
363 for (const auto provider : {"ifconfig.co"sv, "ifconfig.me"sv, "icanhazip.com"sv, "ipinfo.io"sv, "v6.ipinfo.io"sv})
364 {
365 if (type.has_value())
366 {
367 // Make sure the provider has addresses that match the query type
368 if (const auto providerAddresses = Dns::resolve(provider);
369 providerAddresses.has_value() &&
370 (std::find_if(providerAddresses->begin(),
371 providerAddresses->end(),
372 [&type](const auto& address) { return address.getType() == type; }) ==
373 providerAddresses->end()))
374 continue;
375 }
376
377 const Http server((secure ? "https://" : "http://") + std::string(provider), 0, type);
378 const Http::Request request("/ip", Http::Request::Method::Get);
379 const Http::Response page = server.sendRequest(request, timeout, secure);
380 const Http::Response::Status status = page.getStatus();
381
382 if (status == Http::Response::Status::Ok)
383 {
384 static constexpr std::array charset = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
385 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f', '.', ':'};
386 auto body = page.getBody();
387 body.erase(std::remove_if(body.begin(),
388 body.end(),
389 [](char c) {

Callers

nothing calls this directly

Calls 8

getTypeMethod · 0.80
sendRequestMethod · 0.80
eraseMethod · 0.80
isV6Method · 0.80
isV4Method · 0.80
beginMethod · 0.45
endMethod · 0.45
getStatusMethod · 0.45

Tested by

no test coverage detected