|
| 1 | +#include "pingtest.h" |
| 2 | +#include <skyr/url.hpp> |
| 3 | +#include "utils/urlquery_utils.h" |
| 4 | +#include "utils/utils.h" |
| 5 | + |
| 6 | +namespace wsnet { |
| 7 | + |
| 8 | +PingTest::PingTest(WSNetHttpNetworkManager *httpNetworkManager) : httpNetworkManager_(httpNetworkManager) |
| 9 | +{ |
| 10 | + auto tunnelTestEndpoints = Settings::instance().tunnelTestEndpoints(); |
| 11 | + for (const std::string &it : tunnelTestEndpoints) { |
| 12 | + auto url = skyr::url("https://" + it); |
| 13 | + auto &sp = url.search_parameters(); |
| 14 | + urlquery_utils::addPlatformQueryItems(sp); |
| 15 | + endpoints_.push_back(url); |
| 16 | + } |
| 17 | +} |
| 18 | + |
| 19 | +void PingTest::doPingTest(std::uint32_t timeoutMs, RequestFinishedCallback callback) |
| 20 | +{ |
| 21 | + assert(!endpoints_.empty()); |
| 22 | + assert(callback != nullptr); |
| 23 | + // Do the first ping test through the primary domain |
| 24 | + auto httpRequest = httpNetworkManager_->createGetRequest(endpoints_[0].c_str(), timeoutMs, false); |
| 25 | + // We do not use DNS cache, as we need to verify the functionality of the connected VPN's DNS. |
| 26 | + httpRequest->setUseDnsCache(false); |
| 27 | + httpRequest->setIsWhiteListIps(false); |
| 28 | + |
| 29 | + using namespace std::placeholders; |
| 30 | + std::uint64_t requestId = curUniqueId_++; |
| 31 | + RequestInfo ri { callback, 0, timeoutMs}; |
| 32 | + activeRequests_[requestId] = ri; |
| 33 | + httpNetworkManager_->executeRequestEx(httpRequest, requestId, std::bind(&PingTest::onHttpNetworkRequestFinished, this, _1, _2, _3, _4)); |
| 34 | +} |
| 35 | + |
| 36 | +void PingTest::onHttpNetworkRequestFinished(std::uint64_t requestId, std::uint32_t elapsedMs, std::shared_ptr<WSNetRequestError> error, const std::string &data) |
| 37 | +{ |
| 38 | + auto it = activeRequests_.find(requestId); |
| 39 | + assert(it != activeRequests_.end()); |
| 40 | + |
| 41 | + if (it->second.callback->isCanceled()) { |
| 42 | + activeRequests_.erase(it); |
| 43 | + return; |
| 44 | + } |
| 45 | + |
| 46 | + bool bSuccess = false; |
| 47 | + if (error->isSuccess()) { |
| 48 | + auto trimmedData = utils::trim(data); |
| 49 | + if (utils::isIpAddress(trimmedData)) { |
| 50 | + it->second.callback->call(ApiRetCode::kSuccess, trimmedData); |
| 51 | + bSuccess = true; |
| 52 | + } else if (it->second.curEndpointInd < (endpoints_.size() - 1)) { |
| 53 | + // try next backup endpoint |
| 54 | + it->second.curEndpointInd++; |
| 55 | + auto httpRequest = httpNetworkManager_->createGetRequest(endpoints_[it->second.curEndpointInd].c_str(), it->second.timeoutMs, false); |
| 56 | + httpRequest->setUseDnsCache(false); |
| 57 | + httpRequest->setIsWhiteListIps(false); |
| 58 | + using namespace std::placeholders; |
| 59 | + httpNetworkManager_->executeRequestEx(httpRequest, requestId, std::bind(&PingTest::onHttpNetworkRequestFinished, this, _1, _2, _3, _4)); |
| 60 | + return; |
| 61 | + } |
| 62 | + } |
| 63 | + if (!bSuccess) { |
| 64 | + it->second.callback->call(ApiRetCode::kNetworkError, ""); |
| 65 | + } |
| 66 | + activeRequests_.erase(it); |
| 67 | +} |
| 68 | + |
| 69 | + |
| 70 | +} // namespace wsnet |
| 71 | + |
0 commit comments