• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <list>
21 #include <map>
22 #include <memory>
23 #include <mutex>
24 
25 #include <android-base/thread_annotations.h>
26 #include <netdutils/Slice.h>
27 
28 #include "DnsTlsServer.h"
29 #include "DnsTlsTransport.h"
30 #include "IDnsTlsSocketFactory.h"
31 
32 namespace android {
33 namespace net {
34 
35 // This is a singleton class that manages the collection of active DnsTlsTransports.
36 // Queries made here are dispatched to an existing or newly constructed DnsTlsTransport.
37 class DnsTlsDispatcher {
38   public:
39     // Default constructor.
40     DnsTlsDispatcher();
41 
42     // Constructor with dependency injection for testing.
DnsTlsDispatcher(std::unique_ptr<IDnsTlsSocketFactory> factory)43     explicit DnsTlsDispatcher(std::unique_ptr<IDnsTlsSocketFactory> factory)
44         : mFactory(std::move(factory)) {}
45 
46     // Enqueues |query| for resolution via the given |tlsServers| on the
47     // network indicated by |mark|; writes the response into |ans|, and stores
48     // the count of bytes written in |resplen|. Returns a success or error code.
49     // The order in which servers from |tlsServers| are queried may not be the
50     // order passed in by the caller.
51     DnsTlsTransport::Response query(const std::list<DnsTlsServer>& tlsServers, unsigned mark,
52                                     const netdutils::Slice query, const netdutils::Slice ans,
53                                     int* _Nonnull resplen);
54 
55     // Given a |query|, sends it to the server on the network indicated by |mark|,
56     // and writes the response into |ans|,  and indicates
57     // the number of bytes written in |resplen|.  Returns a success or error code.
58     DnsTlsTransport::Response query(const DnsTlsServer& server, unsigned mark,
59                                     const netdutils::Slice query, const netdutils::Slice ans,
60                                     int* _Nonnull resplen);
61 
62   private:
63     // This lock is static so that it can be used to annotate the Transport struct.
64     // DnsTlsDispatcher is a singleton in practice, so making this static does not change
65     // the locking behavior.
66     static std::mutex sLock;
67 
68     // Key = <mark, server>
69     typedef std::pair<unsigned, const DnsTlsServer> Key;
70 
71     // Transport is a thin wrapper around DnsTlsTransport, adding reference counting and
72     // usage monitoring so we can expire idle sessions from the cache.
73     struct Transport {
TransportTransport74         Transport(const DnsTlsServer& server, unsigned mark, IDnsTlsSocketFactory* _Nonnull factory)
75             : transport(server, mark, factory) {}
76         // DnsTlsTransport is thread-safe, so it doesn't need to be guarded.
77         DnsTlsTransport transport;
78         // This use counter and timestamp are used to ensure that only idle sessions are
79         // destroyed.
80         int useCount GUARDED_BY(sLock) = 0;
81         // lastUsed is only guaranteed to be meaningful after useCount is decremented to zero.
82         std::chrono::time_point<std::chrono::steady_clock> lastUsed GUARDED_BY(sLock);
83     };
84 
85     // Cache of reusable DnsTlsTransports.  Transports stay in cache as long as
86     // they are in use and for a few minutes after.
87     // The key is a (netid, server) pair.  The netid is first for lexicographic comparison speed.
88     std::map<Key, std::unique_ptr<Transport>> mStore GUARDED_BY(sLock);
89 
90     // The last time we did a cleanup.  For efficiency, we only perform a cleanup once every
91     // few minutes.
92     std::chrono::time_point<std::chrono::steady_clock> mLastCleanup GUARDED_BY(sLock);
93 
94     // Drop any cache entries whose useCount is zero and which have not been used recently.
95     // This function performs a linear scan of mStore.
96     void cleanup(std::chrono::time_point<std::chrono::steady_clock> now) REQUIRES(sLock);
97 
98     // Return a sorted list of DnsTlsServers in preference order.
99     std::list<DnsTlsServer> getOrderedServerList(const std::list<DnsTlsServer>& tlsServers,
100                                                  unsigned mark) const;
101 
102     // Trivial factory for DnsTlsSockets.  Dependency injection is only used for testing.
103     std::unique_ptr<IDnsTlsSocketFactory> mFactory;
104 };
105 
106 }  // end of namespace net
107 }  // end of namespace android
108 
109 #endif  // _DNS_DNSTLSDISPATCHER_H
110