Loading ResolverController.cpp +21 −3 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,8 @@ #include "stats.h" #include "stats.h" using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; namespace android { namespace android { Loading @@ -45,14 +47,30 @@ namespace net { namespace { namespace { void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) { void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) { LOG(DEBUG) << "Sending Nat64Prefix " << (args.added ? "added" : "removed") << " event on netId " << args.netId << " with address {" << args.prefixString << "(" << args.prefixLength << ")}"; // Send a nat64 prefix event to NetdEventListenerService. const auto& listeners = ResolverEventReporter::getInstance().getListeners(); const auto& listeners = ResolverEventReporter::getInstance().getListeners(); if (listeners.size() == 0) { if (listeners.empty()) { LOG(ERROR) << __func__ << ": No available listener. dropping NAT64 prefix event"; LOG(ERROR) << __func__ << ": No available listener. Skipping NAT64 prefix event"; return; } } for (const auto& it : listeners) { for (const auto& it : listeners) { it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength); it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength); } } const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners(); const Nat64PrefixEventParcel nat64PrefixEvent = { .netId = static_cast<int32_t>(args.netId), .prefixOperation = args.added ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED, .prefixAddress = args.prefixString, .prefixLength = args.prefixLength, }; for (const auto& it : unsolEventListeners) { it->onNat64PrefixEvent(nat64PrefixEvent); } } } int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, Loading tests/resolv_integration_test.cpp +8 −1 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,7 @@ using aidl::android::net::INetd; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::Error; using android::base::Error; using android::base::ParseInt; using android::base::ParseInt; Loading Loading @@ -258,7 +259,12 @@ class ResolverTest : public ::testing::Test { bool WaitForNat64Prefix(ExpectNat64PrefixStatus status, bool WaitForNat64Prefix(ExpectNat64PrefixStatus status, std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) { std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) { return sDnsMetricsListener->waitForNat64Prefix(status, timeout); return sDnsMetricsListener->waitForNat64Prefix(status, timeout) && sUnsolicitedEventListener->waitForNat64Prefix( status == EXPECT_FOUND ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED, timeout); } } bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated) { bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated) { Loading Loading @@ -4031,6 +4037,7 @@ TEST_F(ResolverTest, SetAndClearNat64Prefix) { EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND)); EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND)); EXPECT_EQ(0, sDnsMetricsListener->getUnexpectedNat64PrefixUpdates()); EXPECT_EQ(0, sDnsMetricsListener->getUnexpectedNat64PrefixUpdates()); EXPECT_EQ(0, sUnsolicitedEventListener->getUnexpectedNat64PrefixUpdates()); } } namespace { namespace { Loading tests/unsolicited_listener/unsolicited_event_listener.cpp +30 −2 Original line number Original line Diff line number Diff line Loading @@ -23,11 +23,14 @@ namespace android::net::resolv::aidl { namespace android::net::resolv::aidl { using ::aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::ScopedLockAssertion; using android::base::ScopedLockAssertion; using std::chrono::milliseconds; using std::chrono::milliseconds; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kRetryIntervalMs{20}; ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { Loading @@ -36,8 +39,15 @@ constexpr milliseconds kEventTimeoutMs{5000}; } } ::ndk::ScopedAStatus UnsolicitedEventListener::onNat64PrefixEvent( ::ndk::ScopedAStatus UnsolicitedEventListener::onNat64PrefixEvent( const ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel&) { const Nat64PrefixEventParcel& event) { // default no-op std::lock_guard lock(mMutex); mUnexpectedNat64PrefixUpdates++; if (event.netId == mNetId) { mNat64PrefixAddress = (event.prefixOperation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED) ? event.prefixAddress : ""; } return ::ndk::ScopedAStatus::ok(); return ::ndk::ScopedAStatus::ok(); } } Loading Loading @@ -77,4 +87,22 @@ bool UnsolicitedEventListener::findAndRemoveValidationRecord(const ServerKey& ke return false; return false; } } bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseconds& timeout) { android::base::Timer t; while (t.duration() < timeout) { { std::lock_guard lock(mMutex); if ((operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED && !mNat64PrefixAddress.empty()) || (operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED && mNat64PrefixAddress.empty())) { mUnexpectedNat64PrefixUpdates--; return true; } } std::this_thread::sleep_for(kRetryIntervalMs); } return false; } } // namespace android::net::resolv::aidl } // namespace android::net::resolv::aidl tests/unsolicited_listener/unsolicited_event_listener.h +21 −0 Original line number Original line Diff line number Diff line Loading @@ -44,15 +44,26 @@ class UnsolicitedEventListener // Wait for the expected private DNS validation result until timeout. // Wait for the expected private DNS validation result until timeout. bool waitForPrivateDnsValidation(const std::string& serverAddr, int validation); bool waitForPrivateDnsValidation(const std::string& serverAddr, int validation); // Wait for expected NAT64 prefix operation until timeout. bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout) EXCLUDES(mMutex); // Return true if a validation result for |serverAddr| is found; otherwise, return false. // Return true if a validation result for |serverAddr| is found; otherwise, return false. bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end(); return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end(); } } // Returns the number of updates to the NAT64 prefix that have not yet been waited for. int getUnexpectedNat64PrefixUpdates() const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); return mUnexpectedNat64PrefixUpdates; } void reset() EXCLUDES(mMutex) { void reset() EXCLUDES(mMutex) { std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); mValidationRecords.clear(); mValidationRecords.clear(); mUnexpectedNat64PrefixUpdates = 0; } } private: private: Loading @@ -68,6 +79,16 @@ class UnsolicitedEventListener // Used to store the data from onPrivateDnsValidationEvent. // Used to store the data from onPrivateDnsValidationEvent. std::map<ServerKey, int> mValidationRecords GUARDED_BY(mMutex); std::map<ServerKey, int> mValidationRecords GUARDED_BY(mMutex); // The NAT64 prefix address of the network |mNetId|. It is updated by onNat64PrefixEvent(). std::string mNat64PrefixAddress GUARDED_BY(mMutex); // The number of updates to the NAT64 prefix of network |mNetId| that have not yet been waited // for. Increases by 1 every time onNat64PrefixEvent is called, and decreases by 1 every time // waitForNat64Prefix returns true. // This allows tests to check that no unexpected events have been received without having to // resort to timeouts that make the tests slower and flakier. int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex); mutable std::mutex mMutex; mutable std::mutex mMutex; std::condition_variable mCv; std::condition_variable mCv; }; }; Loading Loading
ResolverController.cpp +21 −3 Original line number Original line Diff line number Diff line Loading @@ -35,6 +35,8 @@ #include "stats.h" #include "stats.h" using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; namespace android { namespace android { Loading @@ -45,14 +47,30 @@ namespace net { namespace { namespace { void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) { void sendNat64PrefixEvent(const Dns64Configuration::Nat64PrefixInfo& args) { LOG(DEBUG) << "Sending Nat64Prefix " << (args.added ? "added" : "removed") << " event on netId " << args.netId << " with address {" << args.prefixString << "(" << args.prefixLength << ")}"; // Send a nat64 prefix event to NetdEventListenerService. const auto& listeners = ResolverEventReporter::getInstance().getListeners(); const auto& listeners = ResolverEventReporter::getInstance().getListeners(); if (listeners.size() == 0) { if (listeners.empty()) { LOG(ERROR) << __func__ << ": No available listener. dropping NAT64 prefix event"; LOG(ERROR) << __func__ << ": No available listener. Skipping NAT64 prefix event"; return; } } for (const auto& it : listeners) { for (const auto& it : listeners) { it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength); it->onNat64PrefixEvent(args.netId, args.added, args.prefixString, args.prefixLength); } } const auto& unsolEventListeners = ResolverEventReporter::getInstance().getUnsolEventListeners(); const Nat64PrefixEventParcel nat64PrefixEvent = { .netId = static_cast<int32_t>(args.netId), .prefixOperation = args.added ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED, .prefixAddress = args.prefixString, .prefixLength = args.prefixLength, }; for (const auto& it : unsolEventListeners) { it->onNat64PrefixEvent(nat64PrefixEvent); } } } int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, int getDnsInfo(unsigned netId, std::vector<std::string>* servers, std::vector<std::string>* domains, Loading
tests/resolv_integration_test.cpp +8 −1 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,7 @@ using aidl::android::net::INetd; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::ResolverParamsParcel; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::metrics::INetdEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::Error; using android::base::Error; using android::base::ParseInt; using android::base::ParseInt; Loading Loading @@ -258,7 +259,12 @@ class ResolverTest : public ::testing::Test { bool WaitForNat64Prefix(ExpectNat64PrefixStatus status, bool WaitForNat64Prefix(ExpectNat64PrefixStatus status, std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) { std::chrono::milliseconds timeout = std::chrono::milliseconds(1000)) { return sDnsMetricsListener->waitForNat64Prefix(status, timeout); return sDnsMetricsListener->waitForNat64Prefix(status, timeout) && sUnsolicitedEventListener->waitForNat64Prefix( status == EXPECT_FOUND ? IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED : IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED, timeout); } } bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated) { bool WaitForPrivateDnsValidation(std::string serverAddr, bool validated) { Loading Loading @@ -4031,6 +4037,7 @@ TEST_F(ResolverTest, SetAndClearNat64Prefix) { EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND)); EXPECT_TRUE(WaitForNat64Prefix(EXPECT_NOT_FOUND)); EXPECT_EQ(0, sDnsMetricsListener->getUnexpectedNat64PrefixUpdates()); EXPECT_EQ(0, sDnsMetricsListener->getUnexpectedNat64PrefixUpdates()); EXPECT_EQ(0, sUnsolicitedEventListener->getUnexpectedNat64PrefixUpdates()); } } namespace { namespace { Loading
tests/unsolicited_listener/unsolicited_event_listener.cpp +30 −2 Original line number Original line Diff line number Diff line Loading @@ -23,11 +23,14 @@ namespace android::net::resolv::aidl { namespace android::net::resolv::aidl { using ::aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener; using ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using ::aidl::android::net::resolv::aidl::PrivateDnsValidationEventParcel; using android::base::ScopedLockAssertion; using android::base::ScopedLockAssertion; using std::chrono::milliseconds; using std::chrono::milliseconds; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kEventTimeoutMs{5000}; constexpr milliseconds kRetryIntervalMs{20}; ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( ::ndk::ScopedAStatus UnsolicitedEventListener::onDnsHealthEvent( const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { const ::aidl::android::net::resolv::aidl::DnsHealthEventParcel&) { Loading @@ -36,8 +39,15 @@ constexpr milliseconds kEventTimeoutMs{5000}; } } ::ndk::ScopedAStatus UnsolicitedEventListener::onNat64PrefixEvent( ::ndk::ScopedAStatus UnsolicitedEventListener::onNat64PrefixEvent( const ::aidl::android::net::resolv::aidl::Nat64PrefixEventParcel&) { const Nat64PrefixEventParcel& event) { // default no-op std::lock_guard lock(mMutex); mUnexpectedNat64PrefixUpdates++; if (event.netId == mNetId) { mNat64PrefixAddress = (event.prefixOperation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED) ? event.prefixAddress : ""; } return ::ndk::ScopedAStatus::ok(); return ::ndk::ScopedAStatus::ok(); } } Loading Loading @@ -77,4 +87,22 @@ bool UnsolicitedEventListener::findAndRemoveValidationRecord(const ServerKey& ke return false; return false; } } bool UnsolicitedEventListener::waitForNat64Prefix(int operation, const milliseconds& timeout) { android::base::Timer t; while (t.duration() < timeout) { { std::lock_guard lock(mMutex); if ((operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_ADDED && !mNat64PrefixAddress.empty()) || (operation == IDnsResolverUnsolicitedEventListener::PREFIX_OPERATION_REMOVED && mNat64PrefixAddress.empty())) { mUnexpectedNat64PrefixUpdates--; return true; } } std::this_thread::sleep_for(kRetryIntervalMs); } return false; } } // namespace android::net::resolv::aidl } // namespace android::net::resolv::aidl
tests/unsolicited_listener/unsolicited_event_listener.h +21 −0 Original line number Original line Diff line number Diff line Loading @@ -44,15 +44,26 @@ class UnsolicitedEventListener // Wait for the expected private DNS validation result until timeout. // Wait for the expected private DNS validation result until timeout. bool waitForPrivateDnsValidation(const std::string& serverAddr, int validation); bool waitForPrivateDnsValidation(const std::string& serverAddr, int validation); // Wait for expected NAT64 prefix operation until timeout. bool waitForNat64Prefix(int operation, const std::chrono::milliseconds& timeout) EXCLUDES(mMutex); // Return true if a validation result for |serverAddr| is found; otherwise, return false. // Return true if a validation result for |serverAddr| is found; otherwise, return false. bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end(); return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end(); } } // Returns the number of updates to the NAT64 prefix that have not yet been waited for. int getUnexpectedNat64PrefixUpdates() const EXCLUDES(mMutex) { std::lock_guard lock(mMutex); return mUnexpectedNat64PrefixUpdates; } void reset() EXCLUDES(mMutex) { void reset() EXCLUDES(mMutex) { std::lock_guard lock(mMutex); std::lock_guard lock(mMutex); mValidationRecords.clear(); mValidationRecords.clear(); mUnexpectedNat64PrefixUpdates = 0; } } private: private: Loading @@ -68,6 +79,16 @@ class UnsolicitedEventListener // Used to store the data from onPrivateDnsValidationEvent. // Used to store the data from onPrivateDnsValidationEvent. std::map<ServerKey, int> mValidationRecords GUARDED_BY(mMutex); std::map<ServerKey, int> mValidationRecords GUARDED_BY(mMutex); // The NAT64 prefix address of the network |mNetId|. It is updated by onNat64PrefixEvent(). std::string mNat64PrefixAddress GUARDED_BY(mMutex); // The number of updates to the NAT64 prefix of network |mNetId| that have not yet been waited // for. Increases by 1 every time onNat64PrefixEvent is called, and decreases by 1 every time // waitForNat64Prefix returns true. // This allows tests to check that no unexpected events have been received without having to // resort to timeouts that make the tests slower and flakier. int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex); mutable std::mutex mMutex; mutable std::mutex mMutex; std::condition_variable mCv; std::condition_variable mCv; }; }; Loading