1 /* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2016 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef SHRPX_DNS_TRACKER_H 26 #define SHRPX_DNS_TRACKER_H 27 28 #include "shrpx.h" 29 30 #include <map> 31 32 #include "shrpx_dual_dns_resolver.h" 33 34 using namespace nghttp2; 35 36 namespace shrpx { 37 38 struct DNSQuery { DNSQueryDNSQuery39 DNSQuery(StringRef host, CompleteCb cb) 40 : host(std::move(host)), 41 cb(std::move(cb)), 42 dlnext(nullptr), 43 dlprev(nullptr), 44 status(DNSResolverStatus::IDLE), 45 in_qlist(false) {} 46 47 // Host name we lookup for. 48 StringRef host; 49 // Callback function called when name lookup finished. This 50 // callback is not called if name lookup finishes within 51 // DNSTracker::resolve(). 52 CompleteCb cb; 53 DNSQuery *dlnext, *dlprev; 54 DNSResolverStatus status; 55 // true if this object is in linked list ResolverEntry::qlist. 56 bool in_qlist; 57 }; 58 59 struct ResolverEntry { 60 // Host name this entry lookups for. 61 ImmutableString host; 62 // DNS resolver. Only non-nullptr if status is 63 // DNSResolverStatus::RUNNING. 64 std::unique_ptr<DualDNSResolver> resolv; 65 // DNSQuery interested in this name lookup result. The result is 66 // notified to them all. 67 DList<DNSQuery> qlist; 68 // Use the same enum with DNSResolverStatus 69 DNSResolverStatus status; 70 // result and its expiry time 71 Address result; 72 // time point when cached result expires. 73 ev_tstamp expiry; 74 }; 75 76 class DNSTracker { 77 public: 78 DNSTracker(struct ev_loop *loop); 79 ~DNSTracker(); 80 81 // Lookups host name described in |dnsq|. If name lookup finishes 82 // within this function (either it came from /etc/hosts, host name 83 // is numeric, lookup result is cached, etc), it returns 84 // DNSResolverStatus::OK or DNSResolverStatus::ERROR. If lookup is 85 // successful, DNSResolverStatus::OK is returned, and |result| is 86 // filled. If lookup failed, DNSResolverStatus::ERROR is returned. 87 // If name lookup is being done background, it returns 88 // DNSResolverStatus::RUNNING. Its completion is notified by 89 // calling dnsq->cb. 90 DNSResolverStatus resolve(Address *result, DNSQuery *dnsq); 91 // Cancels name lookup requested by |dnsq|. 92 void cancel(DNSQuery *dnsq); 93 // Removes expired entries from ents_. 94 void gc(); 95 // Starts GC timer. 96 void start_gc_timer(); 97 98 private: 99 ResolverEntry make_entry(std::unique_ptr<DualDNSResolver> resolv, 100 ImmutableString host, DNSResolverStatus status, 101 const Address *result); 102 103 void update_entry(ResolverEntry &ent, std::unique_ptr<DualDNSResolver> resolv, 104 DNSResolverStatus status, const Address *result); 105 106 void add_to_qlist(ResolverEntry &ent, DNSQuery *dnsq); 107 108 std::map<StringRef, ResolverEntry> ents_; 109 // Periodically iterates ents_, and removes expired entries to avoid 110 // excessive use of memory. Since only backend API can potentially 111 // increase memory consumption, interval could be very long. 112 ev_timer gc_timer_; 113 struct ev_loop *loop_; 114 }; 115 116 } // namespace shrpx 117 118 #endif // SHRPX_DNS_TRACKER_H 119