• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "doh_frontend.h"
18 
19 #define LOG_TAG "DohFrontend"
20 
21 #include <thread>
22 
23 #include <android-base/chrono_utils.h>
24 #include <android-base/file.h>
25 #include <android-base/logging.h>
26 #include <gtest/gtest.h>
27 
28 #include "dns_tls_certificate.h"
29 
30 using std::chrono::milliseconds;
31 
32 namespace test {
33 
34 constexpr milliseconds kEventTimeoutMs{5000};
35 constexpr milliseconds kRetryIntervalMs{20};
36 
~DohFrontend()37 DohFrontend::~DohFrontend() {
38     if (mRustDoh) {
39         stopServer();
40         rust::frontend_delete(mRustDoh);
41     }
42 }
43 
startServer()44 bool DohFrontend::startServer() {
45     std::lock_guard guard(mMutex);
46     if (mRustDoh == nullptr) {
47         mRustDoh = rust::frontend_new(mAddress.c_str(), mService.c_str(), mBackendAddress.c_str(),
48                                       mBackendService.c_str());
49         if (mRustDoh == nullptr) {
50             LOG(ERROR) << "Failed to create rust DoH frontend";
51             return false;
52         }
53     }
54 
55     rust::frontend_set_certificate(mRustDoh, kCertificate);
56     rust::frontend_set_private_key(mRustDoh, kPrivatekey);
57 
58     return rust::frontend_start(mRustDoh);
59 }
60 
stopServer()61 bool DohFrontend::stopServer() {
62     std::lock_guard guard(mMutex);
63     if (!mRustDoh) return false;
64 
65     rust::frontend_stop(mRustDoh);
66     return true;
67 }
68 
queries() const69 int DohFrontend::queries() const {
70     std::lock_guard guard(mMutex);
71     if (!mRustDoh) return 0;
72 
73     rust::Stats stats;
74     rust::frontend_stats(mRustDoh, &stats);
75     return stats.queries_received;
76 }
77 
connections() const78 int DohFrontend::connections() const {
79     std::lock_guard guard(mMutex);
80     if (!mRustDoh) return 0;
81 
82     rust::Stats stats;
83     rust::frontend_stats(mRustDoh, &stats);
84     return stats.connections_accepted;
85 }
86 
aliveConnections() const87 int DohFrontend::aliveConnections() const {
88     std::lock_guard guard(mMutex);
89     if (!mRustDoh) return 0;
90 
91     rust::Stats stats;
92     rust::frontend_stats(mRustDoh, &stats);
93     return stats.alive_connections;
94 }
95 
resumedConnections() const96 int DohFrontend::resumedConnections() const {
97     std::lock_guard guard(mMutex);
98     if (!mRustDoh) return 0;
99 
100     rust::Stats stats;
101     rust::frontend_stats(mRustDoh, &stats);
102     return stats.resumed_connections;
103 }
104 
clearQueries()105 void DohFrontend::clearQueries() {
106     std::lock_guard guard(mMutex);
107     if (mRustDoh) {
108         frontend_stats_clear_queries(mRustDoh);
109 
110         // Because frontend_stats_clear_queries() is asynchronous, query the stat here to ensure
111         // that mRustDoh reset the query count before clearQueries() returns.
112         rust::Stats stats;
113         rust::frontend_stats(mRustDoh, &stats);
114         if (stats.queries_received != 0) {
115             LOG(ERROR) << "queries_received is not 0";
116         }
117     }
118 }
119 
setMaxIdleTimeout(uint64_t value)120 bool DohFrontend::setMaxIdleTimeout(uint64_t value) {
121     std::lock_guard guard(mMutex);
122     if (!mRustDoh) return false;
123 
124     frontend_set_max_idle_timeout(mRustDoh, value);
125     return true;
126 }
127 
setMaxBufferSize(uint64_t value)128 bool DohFrontend::setMaxBufferSize(uint64_t value) {
129     std::lock_guard guard(mMutex);
130     if (!mRustDoh) return false;
131 
132     frontend_set_max_buffer_size(mRustDoh, value);
133     return true;
134 }
135 
setMaxStreamsBidi(uint64_t value)136 bool DohFrontend::setMaxStreamsBidi(uint64_t value) {
137     std::lock_guard guard(mMutex);
138     if (!mRustDoh) return false;
139 
140     frontend_set_max_streams_bidi(mRustDoh, value);
141     return true;
142 }
143 
block_sending(bool block)144 bool DohFrontend::block_sending(bool block) {
145     std::lock_guard guard(mMutex);
146     if (!mRustDoh) return false;
147 
148     frontend_block_sending(mRustDoh, block);
149     return true;
150 }
151 
waitForAllClientsDisconnected() const152 bool DohFrontend::waitForAllClientsDisconnected() const {
153     android::base::Timer t;
154     while (t.duration() < kEventTimeoutMs) {
155         if (aliveConnections() == 0) return true;
156         std::this_thread::sleep_for(kRetryIntervalMs);
157     }
158     return false;
159 }
160 
161 }  // namespace test
162