1#ifndef NEFORCE_NETWORK_DNS_DNS_CLIENT_HPP__
2#define NEFORCE_NETWORK_DNS_DNS_CLIENT_HPP__
25NEFORCE_BEGIN_NAMESPACE__
73 atomic<bool> fired_{
false};
77 steady_clock::time_point start_time_;
80 void on_response(error_code ec, dns_query_result result);
85 struct pending_entry {
86 weak_ptr<dns_query_op> op;
88 steady_clock::time_point created_at{steady_clock::now()};
92 unordered_map<string, pair<dns_query_result, steady_clock::time_point>> cache_;
93 mutable shared_mutex cache_mutex_;
95 bool use_tcp_ =
false;
97 bool recursion_desired_ =
true;
98 uint16_t edns_udp_payload_{edns::DEFAULT_UDP_PAYLOAD};
99 bool dnssec_ok_ =
false;
101 udp_socket shared_socket_;
102 unordered_map<uint16_t, pending_entry> pending_queries_;
103 mutable mutex pending_mutex_;
104 mutable mutex send_mutex_;
105 io_context* ctx_{
nullptr};
106 atomic<bool> io_running_{
false};
109 void ensure_io_started();
112 void register_shared_receive();
113 void on_udp_readable(error_code ec);
114 void process_udp_receive();
115 void dispatch_to_op(uint16_t txid, byte_vector response);
116 void unregister_query(uint16_t txid);
118 void send_query(
const byte_vector& query);
119 byte_vector send_tcp_query(
const byte_vector& query);
121 optional<dns_query_result> check_cache(
const string& key);
122 void update_cache(
const string& key,
const dns_query_result& result);
164 void set_use_tcp(
const bool use_tcp)
noexcept { use_tcp_ = use_tcp; }
245 template <
typename Token,
268#ifdef NEFORCE_STANDARD_20
385 promise_->set_value(move(result));
393struct async_result<use_future_t, void(error_code, dns_query_result)> {
394 using handler_type = inner::future_handler<error_code, dns_query_result>;
395 using return_type = future<dns_query_result>;
396 handler_type handler_;
397 explicit async_result(use_future_t ) { handler_.promise_ = make_shared<promise<dns_query_result>>(); }
398 handler_type get_handler() {
return handler_; }
399 return_type
get() {
return handler_.promise_->get_future(); }
404NEFORCE_END_NAMESPACE__
auto async_query(string_view domain, dns_record::raw type, dns_class qclass, use_future_t)
异步DNS查询——use_future
void set_dnssec_ok(const bool ok) noexcept
设置是否请求DNSSEC(DO)
void async_query(string_view domain, dns_record::raw type, dns_class qclass, detached_t)
异步DNS查询——detached(即发即忘)
optional< dns_soa_record > resolve_soa(string_view domain)
解析SOA记录(授权区域起始)
dns_client()=default
默认构造函数
dns_query_result query(string_view domain, dns_record::raw type=dns_record::A, dns_class qclass=dns_class::INTERNET)
执行DNS查询
static dns_query_result parse_response(const byte_vector &response, uint16_t expected_id=0)
解析DNS响应消息
void set_use_tcp(const bool use_tcp) noexcept
设置是否使用TCP
void clear_cache() noexcept
清空缓存
vector< string > resolve_mx(string_view domain)
解析MX记录(邮件交换器)
void set_cache_ttl(const seconds ttl) noexcept
设置缓存TTL
vector< dns_query_result > batch_query(const vector< string > &domains, dns_record::raw type=dns_record::A)
批量查询
vector< string > resolve_aaaa(string_view domain)
解析AAAA记录(IPv6地址)
static byte_vector build_query(string_view domain, dns_record::raw type=dns_record::A, dns_class qclass=dns_class::INTERNET, bool rd=true, bool edns_enable=true, bool dnssec_ok=false, uint16_t edns_payload=edns::DEFAULT_UDP_PAYLOAD)
构建DNS查询消息
vector< string > resolve_cname(string_view domain)
解析CNAME记录(别名)
dns_client(config cfg, io_context &ctx, bool use_tcp=false)
构造函数
void async_query(string_view domain, dns_record::raw type, dns_class qclass, function< void(error_code, dns_query_result)> handler)
异步DNS查询——回调完成
void set_config(config cfg) noexcept
设置客户端配置
future< dns_query_result > query_async(const string &domain, dns_record::raw type=dns_record::A, dns_class qclass=dns_class::INTERNET)
异步DNS查询(遗留 API——返回 future)
void async_query(string_view domain, dns_record::raw type, dns_class qclass, Token &&token)
异步DNS查询——任意完成令牌
void set_recursion_desired(const bool rd)
设置是否期望递归查询(RD)
vector< string > resolve_a(string_view domain)
解析A记录(IPv4地址)
vector< string > resolve_txt(string_view domain)
解析TXT记录(文本记录)
void set_edns_udp_payload(const uint16_t payload_size) noexcept
设置EDNS0 UDP载荷大小
void set_timeout(const milliseconds timeout) noexcept
设置超时时间
string reverse_query(string_view ip)
反向查询(从IP获取域名)
auto async_query(string_view domain, dns_record::raw type, dns_class qclass, use_awaitable_t)
异步DNS查询——use_awaitable
void async_query(string_view domain, dns_record::raw type, dns_class qclass, cancellation_slot &slot, function< void(error_code, dns_query_result)> handler)
异步DNS查询——回调完成 + 取消槽
vector< dns_srv_record > resolve_srv(string_view domain)
解析SRV记录(服务定位器)
constexpr uint16_t DEFAULT_UDP_PAYLOAD
默认UDP载荷大小(RFC 6891 建议值)
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
vector< byte_t > byte_vector
字节向量类型别名
unsigned short uint16_t
16位无符号整数类型
duration< int64_t > seconds
秒持续时间
duration< int64_t, milli > milliseconds
毫秒持续时间
exception_ptr make_exception_ptr(Ex ex) noexcept
创建异常指针
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
basic_string_view< char > string_view
字符字符串视图
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
milliseconds timeout
查询超时时间