@@ -130,13 +130,13 @@ namespace NDnsResolver {
130130 std::atomic<size_t > Activations{ 0 };
131131 };
132132
133- class TSimpleDnsResolver
134- : public TActor<TSimpleDnsResolver >
133+ class TAresDnsResolver
134+ : public TActor<TAresDnsResolver >
135135 , private TAresLibraryInitBase
136136 , private TCallbackQueueBase
137137 {
138138 public:
139- TSimpleDnsResolver (TSimpleDnsResolverOptions options) noexcept
139+ TAresDnsResolver (TSimpleDnsResolverOptions options) noexcept
140140 : TActor(&TThis::StateWork)
141141 , Options(std::move(options))
142142 , WorkerThread(&TThis::WorkerThreadStart, this )
@@ -146,7 +146,7 @@ namespace NDnsResolver {
146146 WorkerThread.Start ();
147147 }
148148
149- ~TSimpleDnsResolver () noexcept override {
149+ ~TAresDnsResolver () noexcept override {
150150 if (!Stopped) {
151151 PushCallback ([this ] {
152152 // Mark as stopped first
@@ -384,7 +384,7 @@ namespace NDnsResolver {
384384
385385 private:
386386 static void * WorkerThreadStart (void * arg) noexcept {
387- static_cast <TSimpleDnsResolver *>(arg)->WorkerThreadLoop ();
387+ static_cast <TAresDnsResolver *>(arg)->WorkerThreadLoop ();
388388 return nullptr ;
389389 }
390390
@@ -483,9 +483,159 @@ namespace NDnsResolver {
483483 bool Stopped = false ;
484484 };
485485
486+
487+ #if not defined(_win32_)
488+ class TLibcDnsResolver
489+ : public TActor<TLibcDnsResolver>
490+ , private TCallbackQueueBase
491+ {
492+ public:
493+ TLibcDnsResolver (TSimpleDnsResolverOptions options) noexcept
494+ : TActor(&TThis::StateWork)
495+ , WorkerThread(&TThis::WorkerThreadStart, this )
496+ , Options(options)
497+ {
498+ WorkerThread.Start ();
499+ }
500+
501+ ~TLibcDnsResolver () noexcept override {
502+ if (!Stopped) {
503+ PushCallback ([this ] {
504+ Stopped = true ;
505+ });
506+
507+ WorkerThread.Join ();
508+ }
509+ }
510+
511+ static constexpr EActivityType ActorActivityType () {
512+ return EActivityType::DNS_RESOLVER;
513+ }
514+
515+ private:
516+ STRICT_STFUNC (StateWork, {
517+ hFunc (TEvents::TEvPoison, Handle);
518+ hFunc (TEvDns::TEvGetHostByName, Handle);
519+ hFunc (TEvDns::TEvGetAddr, Handle);
520+ })
521+
522+ void Handle (TEvents::TEvPoison::TPtr&) {
523+ Y_ABORT_UNLESS (!Stopped);
524+
525+ PushCallback ([this ] {
526+ // Mark as stopped last
527+ Stopped = true ;
528+ });
529+
530+ WorkerThread.Join ();
531+ PassAway ();
532+ }
533+
534+ private:
535+ std::unique_ptr<TEvDns::TEvGetHostByNameResult> GetHostByName (TString name, int family) {
536+ auto result = std::make_unique<TEvDns::TEvGetHostByNameResult>();
537+
538+ struct addrinfo hints, *res;
539+ memset (&hints, 0 , sizeof (hints));
540+ hints.ai_family = family;
541+ hints.ai_socktype = Options.ForceTcp ? SOCK_STREAM : SOCK_DGRAM;
542+
543+ result->Status = getaddrinfo (name.c_str (), nullptr , &hints, &res);
544+ if (result->Status != 0 ) {
545+ result->ErrorText = gai_strerror (result->Status );
546+ return result;
547+ }
548+ Y_DEFER { freeaddrinfo (res); };
549+
550+ for (auto *node = res; node; node = node->ai_next ) {
551+ switch (node->ai_family ) {
552+ case AF_INET: {
553+ result->AddrsV4 .emplace_back (((sockaddr_in*)node->ai_addr )->sin_addr );
554+ break ;
555+ }
556+ case AF_INET6: {
557+ result->AddrsV6 .emplace_back (((sockaddr_in6*)node->ai_addr )->sin6_addr );
558+ break ;
559+ }
560+ default :
561+ Y_ABORT (" unknown address family in getaddrinfo callback" );
562+ }
563+ }
564+
565+ return result;
566+ }
567+
568+ std::unique_ptr<TEvDns::TEvGetAddrResult> GetAddr (TString name, int family) {
569+ auto result = std::make_unique<TEvDns::TEvGetAddrResult>();
570+ auto res = GetHostByName (name, family);
571+
572+ result->Status = res->Status ;
573+ result->ErrorText = res->ErrorText ;
574+ if (res->AddrsV4 .empty () && res->AddrsV6 .empty ()) {
575+ result->Status = EAI_NODATA;
576+ result->ErrorText = gai_strerror (result->Status );
577+ return result;
578+ }
579+ if (res->AddrsV4 .size () > 0 ) {
580+ result->Addr = res->AddrsV4 [0 ];
581+ }
582+ if (res->AddrsV6 .size () > 0 ) {
583+ result->Addr = res->AddrsV6 [0 ];
584+ }
585+ return result;
586+
587+ }
588+
589+ private:
590+ void Handle (TEvDns::TEvGetHostByName::TPtr& ev) {
591+ auto * msg = ev->Get ();
592+ PushCallback ([this , as = TActivationContext::ActorSystem (), name = std::move (msg->Name ), family = msg->Family , sender = ev->Sender , cookie = ev->Cookie ] () mutable {
593+ auto result = GetHostByName (name, family);
594+ as->Send (new IEventHandle (sender, SelfId (), result.release (), 0 , cookie));
595+ });
596+ }
597+
598+ void Handle (TEvDns::TEvGetAddr::TPtr& ev) {
599+ auto * msg = ev->Get ();
600+ PushCallback ([this , as = TActivationContext::ActorSystem (), name = std::move (msg->Name ), family = msg->Family , sender = ev->Sender , cookie = ev->Cookie ] () mutable {
601+ auto result = GetAddr (name, family);
602+ as->Send (new IEventHandle (sender, SelfId (), result.release (), 0 , cookie));
603+ });
604+ }
605+
606+ private:
607+ static void * WorkerThreadStart (void * arg) noexcept {
608+ static_cast <TLibcDnsResolver*>(arg)->WorkerThreadLoop ();
609+ return nullptr ;
610+ }
611+
612+ void WorkerThreadLoop () noexcept {
613+ TThread::SetCurrentThreadName (" DnsResolver" );
614+ while (!Stopped) {
615+ RunCallbacks ();
616+ }
617+ }
618+ private:
619+ TThread WorkerThread;
620+ bool Stopped = false ;
621+ TSimpleDnsResolverOptions Options;
622+ };
623+
624+ IActor* CreateSimpleDnsResolver (TSimpleDnsResolverOptions options) {
625+ switch (options.Type ) {
626+ case EDnsResolverType::Ares:
627+ return new TAresDnsResolver (std::move (options));
628+ case EDnsResolverType::Libc:
629+ return new TLibcDnsResolver (std::move (options));
630+ default :
631+ Y_ABORT_UNLESS (false , " Invalid dns resolver type: %" PRIu32, options.Type );
632+ }
633+ }
634+ #else
486635 IActor* CreateSimpleDnsResolver (TSimpleDnsResolverOptions options) {
487- return new TSimpleDnsResolver (std::move (options));
636+ return new TAresDnsResolver (std::move (options));
488637 }
638+ #endif
489639
490640} // namespace NDnsResolver
491641} // namespace NActors
0 commit comments