#include "interconnect.h" #include "interconnect_address.h" #include "events_local.h" #include #include #include namespace NActors { using namespace NActors::NDnsResolver; class TInterconnectResolveActor : public TActorBootstrapped { public: TInterconnectResolveActor( const TString& host, ui16 port, ui32 nodeId, const TString& defaultAddress, const TActorId& replyTo, const TActorId& replyFrom, TInstant deadline) : Host(host) , NodeId(nodeId) , Port(port) , DefaultAddress(defaultAddress) , ReplyTo(replyTo) , ReplyFrom(replyFrom) , Deadline(deadline) { } TInterconnectResolveActor( const TString& host, ui16 port, const TActorId& replyTo, const TActorId& replyFrom, TInstant deadline) : Host(host) , Port(port) , ReplyTo(replyTo) , ReplyFrom(replyFrom) , Deadline(deadline) { } static constexpr EActivityType ActorActivityType() { return NAMESERVICE; } void Bootstrap() { TMaybe errorText; if (auto addr = ExtractDefaultAddr(errorText)) { return SendAddrAndDie(std::move(addr)); } if (errorText) { SendErrorAndDie(*errorText); } auto now = TActivationContext::Now(); if (Deadline < now) { SendErrorAndDie("Deadline"); return; } Send(MakeDnsResolverActorId(), new TEvDns::TEvGetAddr(Host, AF_UNSPEC), IEventHandle::FlagTrackDelivery); if (Deadline != TInstant::Max()) { Schedule(Deadline, new TEvents::TEvWakeup); } Become(&TThis::StateWork); } STRICT_STFUNC(StateWork, { sFunc(TEvents::TEvWakeup, HandleTimeout); sFunc(TEvents::TEvUndelivered, HandleUndelivered); hFunc(TEvDns::TEvGetAddrResult, Handle); }); void HandleTimeout() { SendErrorAndDie("Deadline"); } void HandleUndelivered() { SendErrorAndDie("Dns resolver is unavailable"); } void Handle(TEvDns::TEvGetAddrResult::TPtr& ev) { if (auto addr = ExtractAddr(ev->Get())) { return SendAddrAndDie(std::move(addr)); } SendErrorAndDie(ev->Get()->ErrorText); } void SendAddrAndDie(NAddr::IRemoteAddrPtr addr) { if (NodeId) { auto reply = new TEvLocalNodeInfo; reply->NodeId = *NodeId; reply->Address = std::move(addr); TActivationContext::Send(new IEventHandle(ReplyTo, ReplyFrom, reply)); } else { auto reply = new TEvAddressInfo; reply->Address = std::move(addr); TActivationContext::Send(new IEventHandle(ReplyTo, ReplyFrom, reply)); } PassAway(); } void SendErrorAndDie(const TString& errorText) { auto *event = new TEvResolveError; event->Explain = errorText; TActivationContext::Send(new IEventHandle(ReplyTo, ReplyFrom, event)); PassAway(); } NAddr::IRemoteAddrPtr ExtractAddr(TEvDns::TEvGetAddrResult* msg) { if (msg->Status == 0) { if (msg->IsV6()) { struct sockaddr_in6 sin6; Zero(sin6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = msg->GetAddrV6(); sin6.sin6_port = HostToInet(Port); return MakeHolder(sin6); } if (msg->IsV4()) { return MakeHolder(TIpAddress(msg->GetAddrV4().s_addr, Port)); } Y_FAIL("Unexpected result address family"); } return nullptr; } NAddr::IRemoteAddrPtr ExtractDefaultAddr(TMaybe& errorText) { if (DefaultAddress) { NInterconnect::TAddress address(DefaultAddress.data(), Port); switch (address.GetFamily()) { case AF_INET: return MakeHolder(*(sockaddr_in*)address.SockAddr()); case AF_INET6: return MakeHolder(*(sockaddr_in6*)address.SockAddr()); default: errorText = "Unsupported default address: " + DefaultAddress; break; } } return nullptr; } private: const TString Host; const std::optional NodeId; const ui16 Port; const TString DefaultAddress; const TActorId ReplyTo; const TActorId ReplyFrom; const TInstant Deadline; }; IActor* CreateResolveActor( const TString& host, ui16 port, ui32 nodeId, const TString& defaultAddress, const TActorId& replyTo, const TActorId& replyFrom, TInstant deadline) { return new TInterconnectResolveActor(host, port, nodeId, defaultAddress, replyTo, replyFrom, deadline); } IActor* CreateResolveActor( const TString& host, ui16 port, const TActorId& replyTo, const TActorId& replyFrom, TInstant deadline) { return new TInterconnectResolveActor(host, port, replyTo, replyFrom, deadline); } } // namespace NActors