diff options
| author | Arseny Smirnov <arseny30@gmail.com> | 2019-01-24 13:47:54 +0400 |
|---|---|---|
| committer | Arseny Smirnov <arseny30@gmail.com> | 2019-01-24 13:47:54 +0400 |
| commit | dd190c7d7932abfac6449f508312c67833b96f6a (patch) | |
| tree | 1e2fbf1c9d69547e14e647e6b1b515239bc53128 /tdnet/td/net/GetHostByNameActor.cpp | |
| parent | fc3717109dfcaeb626435e8246e8af3df09f1827 (diff) | |
DnsOverHttps class with a test
GitOrigin-RevId: 4f8785377ddbe47a59fe6e03628685902503e1f6
Diffstat (limited to 'tdnet/td/net/GetHostByNameActor.cpp')
| -rw-r--r-- | tdnet/td/net/GetHostByNameActor.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/tdnet/td/net/GetHostByNameActor.cpp b/tdnet/td/net/GetHostByNameActor.cpp index c98d366d2..9cd33a5b8 100644 --- a/tdnet/td/net/GetHostByNameActor.cpp +++ b/tdnet/td/net/GetHostByNameActor.cpp @@ -8,8 +8,57 @@ #include "td/utils/logging.h" #include "td/utils/Time.h" +#include "td/utils/JsonBuilder.h" +#include "td/net/Wget.h" namespace td { +namespace detail { +class GoogleDnsResolver : public Actor { + public: + GoogleDnsResolver(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise) { + const int timeout = 10; + const int ttl = 3; + wget_ = create_actor<Wget>( + "Wget", create_result_handler(std::move(promise), port), + PSTRING() << "https://www.google.com/resolve?name=" << url_encode(host) << "&type=" << (prefer_ipv6 ? 28 : 1), + std::vector<std::pair<string, string>>({{"Host", "dns.google.com"}}), timeout, ttl, prefer_ipv6, + SslStream::VerifyPeer::Off); + } + + private: + ActorOwn<Wget> wget_; + + Promise<HttpQueryPtr> create_result_handler(Promise<IPAddress> promise, int port) { + return PromiseCreator::lambda([promise = std::move(promise), port](Result<HttpQueryPtr> r_http_query) mutable { + promise.set_result([&]() -> Result<IPAddress> { + TRY_RESULT(http_query, std::move(r_http_query)); + LOG(ERROR) << *http_query; + TRY_RESULT(json_value, json_decode(http_query->content_)); + if (json_value.type() != JsonValue::Type::Object) { + return Status::Error("Failed to parse dns result: not an object"); + } + TRY_RESULT(answer, get_json_object_field(json_value.get_object(), "Answer", JsonValue::Type::Array, false)); + if (answer.get_array().size() == 0) { + return Status::Error("Failed to parse dns result: Answer is an empty array"); + } + if (answer.get_array()[0].type() != JsonValue::Type::Object) { + return Status::Error("Failed to parse dns result: Answer[0] is not an object"); + } + auto &answer_0 = answer.get_array()[0].get_object(); + TRY_RESULT(ip_str, get_json_object_string_field(answer_0, "data", false)); + IPAddress ip; + TRY_STATUS(ip.init_host_port(ip_str, port)); + return ip; + }()); + }); + } +}; +} // namespace detail + +ActorOwn<> DnsOverHttps::resolve(std::string host, int port, bool prefer_ipv6, td::Promise<td::IPAddress> promise) { + return ActorOwn<>(create_actor<detail::GoogleDnsResolver>("GoogleDnsResolver", std::move(host), port, prefer_ipv6, + std::move(promise))); +} GetHostByNameActor::GetHostByNameActor(int32 ok_timeout, int32 error_timeout) : ok_timeout_(ok_timeout), error_timeout_(error_timeout) { |
