11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
31PROMEKI_NAMESPACE_BEGIN
71class DnsLookup :
public ObjectBase {
72 PROMEKI_OBJECT(DnsLookup, ObjectBase)
89 DnsLookup(DnsResolver *resolver,
const String &name,
90 const DnsRecordType &type,
91 const DnsRecordClass &klass = DnsRecordClass::In);
93 ~DnsLookup()
override;
96 const String &name()
const {
return _name; }
99 const DnsRecordType &type()
const {
return _type; }
102 const DnsRecordClass &klass()
const {
return _klass; }
111 const DnsRcode &rcode()
const {
return _rcode; }
126 bool isActive()
const {
return _active.value(); }
129 PROMEKI_SIGNAL(answered, List<DnsRecord>);
132 PROMEKI_SIGNAL(failed, Error);
136 void timerEvent(TimerEvent *e)
override;
139 friend class DnsResolver;
141 DnsResolver *_resolver =
nullptr;
143 DnsRecordType _type = DnsRecordType::A;
144 DnsRecordClass _klass = DnsRecordClass::In;
145 DnsRcode _rcode = DnsRcode::NoError;
146 Atomic<bool> _active;
147 Atomic<bool> _emitted;
202class DnsResolver :
public ObjectBase {
203 PROMEKI_OBJECT(DnsResolver, ObjectBase)
206 static constexpr int MaxCnameDepth = 16;
209 static constexpr uint16_t Edns0UdpSize = 1232;
212 static constexpr int64_t DefaultAttemptTimeoutMs = 3000;
225 static DnsResolver *defaultInstance();
239 explicit DnsResolver(ObjectBase *parent =
nullptr);
241 ~DnsResolver()
override;
251 void setNameservers(
const List<SocketAddress> &servers);
254 List<SocketAddress> nameservers()
const;
257 void setSearchDomains(
const StringList &domains);
260 StringList searchDomains()
const;
263 void setConfig(
const DnsConfig &cfg);
266 DnsConfig config()
const;
274 Error reloadSystemConfig();
277 DnsCache &cache() {
return _cache; }
279 const DnsCache &cache()
const {
return _cache; }
298 void setMdnsManager(MdnsManager *manager);
301 MdnsManager *mdnsManager()
const;
324 void setMdnsRoutingEnabled(
bool enable);
327 bool mdnsRoutingEnabled()
const;
345 DnsLookup *lookup(
const String &name,
346 const DnsRecordType &type = DnsRecordType::A,
347 const DnsRecordClass &klass = DnsRecordClass::In);
374 static Result<List<DnsRecord>> lookupSync(
376 const DnsRecordType &type = DnsRecordType::A,
377 const Duration &timeout = Duration::fromSeconds(5));
399 static Result<NetworkAddress> resolveSync(
401 NetworkAddress::FamilyPreference prefer = NetworkAddress::PreferIPv4,
402 const Duration &timeout = Duration::fromSeconds(5));
416 static Result<List<DnsRecord>> lookupReverseSync(
417 const NetworkAddress &addr,
418 const Duration &timeout = Duration::fromSeconds(5));
421 friend class DnsLookup;
425 Error openSocketsIfNeeded();
427 void beginLookup(DnsLookup *lookup);
428 void beginAttempt(Inflight *flight);
429 bool isMdnsName(
const String &name)
const;
430 Error beginMdnsLookup(Inflight *flight);
431 void handleMdnsPacket(Inflight *flight,
const Buffer &data);
432 MdnsManager *effectiveMdnsManager();
433 void onLookupTimeout(DnsLookup *lookup);
434 void failLookup(DnsLookup *lookup, Error err);
435 void succeedLookup(DnsLookup *lookup,
const List<DnsRecord> &records);
436 void handleSocketReadable(UdpSocket *sock);
437 void processResponseBytes(
const uint8_t *data,
size_t len);
438 void followCname(Inflight *flight,
const String &target);
439 void beginTcpFallback(Inflight *flight);
440 void removeInflight(DnsLookup *lookup);
441 uint16_t allocateTransactionId();
442 List<String> expandSearch(
const String &name)
const;
443 Error sendQueryUdp(Inflight *flight);
444 static List<DnsRecord> filterAnswerRecords(
445 const class DnsPacket &pkt,
446 const String &name, uint16_t type, uint16_t klass);
447 static Duration soaMinimumFromAuthority(
const class DnsPacket &pkt);
449 mutable Mutex _cfgMtx;
452 UniquePtr<UdpSocket> _socketV4;
453 UniquePtr<UdpSocket> _socketV6;
454 int _ioHandleV4 = -1;
455 int _ioHandleV6 = -1;
463 MdnsManager *_mdnsManager =
nullptr;
464 int _mdnsObserverHandle = -1;
465 bool _mdnsRoutingEnabled =
true;
473 Map<uint16_t, Inflight *> _inflight;
474 Map<DnsLookup *, Inflight *> _byLookup;
475 uint16_t _nextTxId = 0;