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