1 /**
2  * Copyright (c) 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <condition_variable>
20 #include <map>
21 #include <queue>
22 #include <utility>
23 
24 #include <android-base/thread_annotations.h>
25 
26 #include "base_metrics_listener.h"
27 
28 enum ExpectNat64PrefixStatus : bool {
29     EXPECT_FOUND,
30     EXPECT_NOT_FOUND,
31 };
32 
33 namespace android::net::metrics {
34 
35 // TODO: Perhaps create a queue to monitor the event changes. That improves the unit test which can
36 // verify the event count, the event change order, and so on.
37 class DnsMetricsListener : public BaseMetricsListener {
38   public:
39     struct DnsEvent {
40         int32_t netId;
41         int32_t eventType;
42         int32_t returnCode;
43         std::string hostname;
44         std::vector<std::string> ipAddresses;
45         int32_t ipAddressesCount;
46 
47         bool operator==(const DnsEvent& o) const;
48 
49         // Informative for debugging.
50         friend std::ostream& operator<<(std::ostream& os, const DnsEvent& data);
51     };
52 
53     DnsMetricsListener() = delete;
DnsMetricsListener(int32_t netId)54     DnsMetricsListener(int32_t netId) : mNetId(netId){};
55 
56     // Override DNS metrics event(s).
57     ::ndk::ScopedAStatus onNat64PrefixEvent(int32_t netId, bool added,
58                                             const std::string& prefixString,
59                                             int32_t /*prefixLength*/) override;
60 
61     ::ndk::ScopedAStatus onPrivateDnsValidationEvent(int32_t netId, const std::string& ipAddress,
62                                                      const std::string& /*hostname*/,
63                                                      bool validated) override;
64 
65     ::ndk::ScopedAStatus onDnsEvent(int32_t netId, int32_t eventType, int32_t returnCode,
66                                     int32_t /*latencyMs*/, const std::string& hostname,
67                                     const std::vector<std::string>& ipAddresses,
68                                     int32_t ipAddressesCount, int32_t /*uid*/) override;
69 
70     // Wait for expected NAT64 prefix status until timeout.
71     bool waitForNat64Prefix(ExpectNat64PrefixStatus status, std::chrono::milliseconds timeout)
72             EXCLUDES(mMutex);
73 
74     // Returns the number of updates to the NAT64 prefix that have not yet been waited for.
getUnexpectedNat64PrefixUpdates()75     int getUnexpectedNat64PrefixUpdates() const EXCLUDES(mMutex) {
76         std::lock_guard lock(mMutex);
77         return mUnexpectedNat64PrefixUpdates;
78     }
79 
80     // Wait for the expected private DNS validation result until timeout.
81     bool waitForPrivateDnsValidation(const std::string& serverAddr, const bool validated);
82 
83     // Return true if a validation result for |serverAddr| is found; otherwise, return false.
84     // Only exists for testing.
findValidationRecord(const std::string & serverAddr)85     bool findValidationRecord(const std::string& serverAddr) const EXCLUDES(mMutex) {
86         std::lock_guard lock(mMutex);
87         return mValidationRecords.find({mNetId, serverAddr}) != mValidationRecords.end();
88     }
89 
90     std::optional<DnsEvent> popDnsEvent() EXCLUDES(mMutex);
91 
reset()92     void reset() EXCLUDES(mMutex) {
93         std::lock_guard lock(mMutex);
94         mUnexpectedNat64PrefixUpdates = 0;
95         mValidationRecords.clear();
96 
97         std::queue<DnsEvent> emptyQueue;
98         std::swap(mDnsEventRecords, emptyQueue);
99     }
100 
101   private:
102     typedef std::pair<int32_t, std::string> ServerKey;
103 
104     // Search mValidationRecords. Return true if |key| exists and its value is equal to
105     // |value|, and then remove it; otherwise, return false.
106     bool findAndRemoveValidationRecord(const ServerKey& key, const bool value) REQUIRES(mMutex);
107 
108     // Monitor the event which was fired on specific network id.
109     const int32_t mNetId;
110 
111     // The NAT64 prefix of the network |mNetId|. It is updated by the event onNat64PrefixEvent().
112     std::string mNat64Prefix GUARDED_BY(mMutex);
113 
114     // The number of updates to the NAT64 prefix of network |mNetId| that have not yet been waited
115     // for. Increases by 1 every time onNat64PrefixEvent is called, and decreases by 1 every time
116     // waitForNat64Prefix returns true.
117     // This allows tests to check that no unexpected events have been received without having to
118     // resort to timeouts that make the tests slower and flakier.
119     int mUnexpectedNat64PrefixUpdates GUARDED_BY(mMutex);
120 
121     // Used to store the data from onPrivateDnsValidationEvent.
122     std::map<ServerKey, bool> mValidationRecords GUARDED_BY(mMutex);
123 
124     // Used to store the data from onDnsEvent.
125     std::queue<DnsEvent> mDnsEventRecords GUARDED_BY(mMutex);
126 
127     mutable std::mutex mMutex;
128     std::condition_variable mCv;
129 };
130 
131 }  // namespace android::net::metrics
132