blob: c32bde2a2f8b315b0d6bcc29c8a96f61704c2c9f [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#ifndef _DNS_DNSTLSDISPATCHER_H
18#define _DNS_DNSTLSDISPATCHER_H
19
20#include <memory>
21#include <map>
22#include <mutex>
23
24#include <android-base/thread_annotations.h>
25
26#include "dns/DnsTlsServer.h"
27#include "dns/DnsTlsTransport.h"
28
29namespace android {
30namespace net {
31
32// This is a totally static class that manages the collection of active DnsTlsTransports.
33// Queries made here are dispatched to an existing or newly constructed DnsTlsTransport.
34class DnsTlsDispatcher {
35public:
36 // Given a |query| of length |qlen|, sends it to the server on the network indicated by |mark|,
37 // and writes the response into |ans|, which can accept up to |anssiz| bytes. Indicates
38 // the number of bytes written in |resplen|. If |resplen| is zero, an
39 // error has occurred.
40 static DnsTlsTransport::Response query(const DnsTlsServer& server, unsigned mark,
41 const uint8_t *query, size_t qlen, uint8_t *ans, size_t anssiz, int *resplen);
42
43private:
44 static std::mutex sLock;
45
46 typedef std::pair<unsigned, const DnsTlsServer> Key;
47
48 // Transport is a thin wrapper around DnsTlsTransport, adding reference counting and
49 // idle monitoring so we can expire unused sessions from the cache.
50 struct Transport {
51 Transport(const DnsTlsServer& server, unsigned mark) : transport(server, mark) {}
52 // DnsTlsSession is thread-safe (internally locked), so it doesn't need to be guarded.
53 DnsTlsTransport transport;
54 // This use counter and timestamp are used to ensure that only idle sessions are
55 // destroyed.
56 int useCount GUARDED_BY(sLock) = 0;
57 std::chrono::time_point<std::chrono::steady_clock> lastUsed GUARDED_BY(sLock);
58 };
59
60 // Cache of reusable DnsTlsTransports. Transports stay in cache as long as
61 // they are in use and for a few minutes after.
62 // The key is a (netid, server) pair. The netid is first for lexicographic comparison speed.
63 static std::map<Key, std::unique_ptr<Transport>> sStore GUARDED_BY(sLock);
64
65 // The last time we did a cleanup. For efficiency, we only perform a cleanup once every
66 // few minutes.
67 static std::chrono::time_point<std::chrono::steady_clock> sLastCleanup GUARDED_BY(sLock);
68
69 // Drop any cache entries whose useCount is zero and which have not been used recently.
70 static void cleanup(std::chrono::time_point<std::chrono::steady_clock> now) REQUIRES(sLock);
71};
72
73} // namespace net
74} // namespace android
75
76#endif // _DNS_DNSTLSDISPATCHER_H