blob: 6fed9f0c59b03f78e6cd473ad6fd740372d764a1 [file] [log] [blame]
Ben Schwartz66810f62017-10-16 19:27:46 -04001/*
2 * Copyright (C) 2017 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 "dns/DnsTlsDispatcher.h"
18
19namespace android {
20namespace net {
21
22// static
23std::mutex DnsTlsDispatcher::sLock;
24std::map<DnsTlsDispatcher::Key, std::unique_ptr<DnsTlsDispatcher::Transport>> DnsTlsDispatcher::sStore;
25DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, unsigned mark,
26 const uint8_t *query, size_t qlen, uint8_t *response, size_t limit, int *resplen) {
27 const Key key = std::make_pair(mark, server);
28 Transport* xport;
29 {
30 std::lock_guard<std::mutex> guard(sLock);
31 auto it = sStore.find(key);
32 if (it == sStore.end()) {
33 xport = new Transport(server, mark);
34 if (!xport->transport.initialize()) {
35 return DnsTlsTransport::Response::internal_error;
36 }
37 sStore[key].reset(xport);
38 } else {
39 xport = it->second.get();
40 }
41 ++xport->useCount;
42 }
43
44 DnsTlsTransport::Response res = xport->transport.query(query, qlen, response, limit, resplen);
45 auto now = std::chrono::steady_clock::now();
46 {
47 std::lock_guard<std::mutex> guard(sLock);
48 --xport->useCount;
49 xport->lastUsed = now;
50 cleanup(now);
51 }
52 return res;
53}
54
55static constexpr std::chrono::minutes IDLE_TIMEOUT(5);
56std::chrono::time_point<std::chrono::steady_clock> DnsTlsDispatcher::sLastCleanup;
57void DnsTlsDispatcher::cleanup(std::chrono::time_point<std::chrono::steady_clock> now) {
58 if (now - sLastCleanup < IDLE_TIMEOUT) {
59 return;
60 }
61 for (auto it = sStore.begin(); it != sStore.end(); ) {
62 auto& s = it->second;
63 if (s->useCount == 0 && now - s->lastUsed > IDLE_TIMEOUT) {
64 it = sStore.erase(it);
65 } else {
66 ++it;
67 }
68 }
69 sLastCleanup = now;
70}
71
72} // namespace net
73} // namespace android