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_RESOLVER_H 26 #define SHRPX_DNS_RESOLVER_H 27 28 #include "shrpx.h" 29 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 33 #include <vector> 34 35 #include <ev.h> 36 #include <ares.h> 37 38 #include "template.h" 39 #include "network.h" 40 41 using namespace nghttp2; 42 43 namespace shrpx { 44 45 enum class DNSResolverStatus { 46 // Resolver is in initial status 47 IDLE, 48 // Resolver is currently resolving host name 49 RUNNING, 50 // Resolver successfully resolved host name 51 OK, 52 // Resolver failed to resolve host name 53 ERROR, 54 }; 55 56 // Callback function called when host name lookup is finished. 57 // |status| is either DNSResolverStatus::OK, or 58 // DNSResolverStatus::ERROR. If |status| is DNSResolverStatus::OK, 59 // |result| points to the resolved address. Note that port portion of 60 // |result| is undefined, and must be initialized by application. 61 // This callback function is not called if name lookup finishes in 62 // DNSResolver::resolve() completely. In this case, application 63 // should call DNSResolver::get_status() to get current status and 64 // result. In other words, callback is called if get_status() returns 65 // DNSResolverStatus::RUNNING. 66 using CompleteCb = 67 std::function<void(DNSResolverStatus status, const Address *result)>; 68 69 // DNSResolver is asynchronous name resolver, backed by c-ares 70 // library. 71 class DNSResolver { 72 public: 73 DNSResolver(struct ev_loop *loop); 74 ~DNSResolver(); 75 76 // Starts resolving hostname |name|. 77 int resolve(const StringRef &name, int family); 78 // Returns status. If status_ is DNSResolverStatus::SUCCESS && 79 // |result| is not nullptr, |*result| is filled. 80 DNSResolverStatus get_status(Address *result) const; 81 // Sets callback function when name lookup finishes. The callback 82 // function is called in a way that it can destroy this DNSResolver. 83 void set_complete_cb(CompleteCb cb); 84 CompleteCb get_complete_cb() const; 85 86 // Calls these functions when read/write event occurred respectively. 87 int on_read(int fd); 88 int on_write(int fd); 89 int on_timeout(); 90 // Calls this function when DNS query finished. 91 void on_result(int staus, hostent *hostent); 92 void reset_timeout(); 93 94 void start_rev(int fd); 95 void stop_rev(int fd); 96 void start_wev(int fd); 97 void stop_wev(int fd); 98 99 private: 100 int handle_event(int rfd, int wfd); 101 102 std::vector<std::unique_ptr<ev_io>> revs_, wevs_; 103 Address result_; 104 CompleteCb completeCb_; 105 ev_timer timer_; 106 StringRef name_; 107 struct ev_loop *loop_; 108 // ares_channel is pointer type 109 ares_channel channel_; 110 // AF_INET or AF_INET6. AF_INET for A record lookup, and AF_INET6 111 // for AAAA record lookup. 112 int family_; 113 DNSResolverStatus status_; 114 }; 115 116 } // namespace shrpx 117 118 #endif // SHRPX_DNS_RESOLVER_H 119