blob: 18c98d2ae3e7cdf0bcee15c899bab9997d0df86a [file] [log] [blame]
/**
* Copyright (c) 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dns_metrics_listener.h"
#include <android-base/chrono_utils.h>
#include <thread>
namespace android {
namespace net {
namespace metrics {
using android::base::ScopedLockAssertion;
using std::chrono::milliseconds;
constexpr milliseconds kRetryIntervalMs{20};
constexpr milliseconds kEventTimeoutMs{5000};
::ndk::ScopedAStatus DnsMetricsListener::onNat64PrefixEvent(int32_t netId, bool added,
const std::string& prefixString,
int32_t /*prefixLength*/) {
std::lock_guard lock(mMutex);
if (netId == mNetId) mNat64Prefix = added ? prefixString : "";
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus DnsMetricsListener::onPrivateDnsValidationEvent(
int32_t netId, const std::string& ipAddress, const std::string& /*hostname*/,
bool validated) {
{
std::lock_guard lock(mMutex);
// keep updating the server to have latest validation status.
mValidationRecords.insert_or_assign({netId, ipAddress}, validated);
}
mCv.notify_one();
return ::ndk::ScopedAStatus::ok();
}
bool DnsMetricsListener::waitForNat64Prefix(ExpectNat64PrefixStatus status,
milliseconds timeout) const {
android::base::Timer t;
while (t.duration() < timeout) {
{
std::lock_guard lock(mMutex);
if ((status == EXPECT_FOUND && !mNat64Prefix.empty()) ||
(status == EXPECT_NOT_FOUND && mNat64Prefix.empty()))
return true;
}
std::this_thread::sleep_for(kRetryIntervalMs);
}
return false;
}
bool DnsMetricsListener::waitForPrivateDnsValidation(const std::string& serverAddr,
const bool validated) {
const auto now = std::chrono::steady_clock::now();
std::unique_lock lock(mMutex);
ScopedLockAssertion assume_lock(mMutex);
// onPrivateDnsValidationEvent() might already be invoked. Search for the record first.
do {
if (findAndRemoveValidationRecord({mNetId, serverAddr}, validated)) return true;
} while (mCv.wait_until(lock, now + kEventTimeoutMs) != std::cv_status::timeout);
// Timeout.
return false;
}
bool DnsMetricsListener::findAndRemoveValidationRecord(const ServerKey& key, const bool value) {
auto it = mValidationRecords.find(key);
if (it != mValidationRecords.end() && it->second == value) {
mValidationRecords.erase(it);
return true;
}
return false;
}
} // namespace metrics
} // namespace net
} // namespace android