Electroneum
Loading...
Searching...
No Matches
tools::dns_utils Namespace Reference

Functions

std::string address_from_txt_record (const std::string &s)
std::vector< std::string > addresses_from_url (const std::string &url, bool &dnssec_valid)
 gets a electroneum address from the TXT record of a DNS entry
std::string get_account_address_as_str_from_url (const std::string &url, bool &dnssec_valid, std::function< std::string(const std::string &, const std::vector< std::string > &, bool)> dns_confirm)
bool load_txt_records_from_dns (std::vector< std::string > &good_records, const std::vector< std::string > &dns_urls, std::string type)
std::vector< std::string > parse_dns_public (const char *s)

Function Documentation

◆ address_from_txt_record()

std::string tools::dns_utils::address_from_txt_record ( const std::string & s)

Definition at line 411 of file dns_utils.cpp.

412{
413 // make sure the txt record has "oa1:etn" and find it
414 auto pos = s.find("oa1:etn");
415 if (pos == std::string::npos)
416 return {};
417 // search from there to find "recipient_address="
418 pos = s.find("recipient_address=", pos);
419 if (pos == std::string::npos)
420 return {};
421 pos += 18; // move past "recipient_address="
422 // find the next semicolon
423 auto pos2 = s.find(";", pos);
424 if (pos2 != std::string::npos)
425 {
426 // length of address == 98, we can at least validate that much here
427 if (pos2 - pos == 98)
428 {
429 return s.substr(pos, 98);
430 }
431 else if (pos2 - pos == 109) // length of address == 109 --> integrated address
432 {
433 return s.substr(pos, 109);
434 }
435 }
436 return {};
437}
Here is the caller graph for this function:

◆ addresses_from_url()

std::vector< std::string > tools::dns_utils::addresses_from_url ( const std::string & url,
bool & dnssec_valid )

gets a electroneum address from the TXT record of a DNS entry

gets the electroneum address from the TXT record of the DNS entry associated with <url>. If this lookup fails, or the TXT record does not contain an ETN address in the correct format, returns an empty string. <dnssec_valid> will be set true or false according to whether or not the DNS query passes DNSSEC validation.

Parameters
urlthe url to look up
dnssec_validreturn-by-reference for DNSSEC status of query
Returns
a electroneum address (as a string) or an empty string

Definition at line 452 of file dns_utils.cpp.

453{
454 std::vector<std::string> addresses;
455 // get txt records
456 bool dnssec_available, dnssec_isvalid;
457 std::string oa_addr = DNSResolver::instance().get_dns_format_from_oa_address(url);
458 auto records = DNSResolver::instance().get_txt_record(oa_addr, dnssec_available, dnssec_isvalid);
459
460 // TODO: update this to allow for conveying that dnssec was not available
461 if (dnssec_available && dnssec_isvalid)
462 {
463 dnssec_valid = true;
464 }
465 else dnssec_valid = false;
466
467 // for each txt record, try to find a electroneum address in it.
468 for (auto& rec : records)
469 {
470 std::string addr = address_from_txt_record(rec);
471 if (addr.size())
472 {
473 addresses.push_back(addr);
474 }
475 }
476 return addresses;
477}
static DNSResolver & instance()
Gets the singleton instance of DNSResolver.
std::vector< std::string > get_txt_record(const std::string &url, bool &dnssec_available, bool &dnssec_valid)
gets all TXT records from a DNS query for the supplied URL; if no TXT record present returns an empty...
std::string get_dns_format_from_oa_address(const std::string &oa_addr)
Gets a DNS address from OpenAlias format.
std::string address_from_txt_record(const std::string &s)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_account_address_as_str_from_url()

std::string tools::dns_utils::get_account_address_as_str_from_url ( const std::string & url,
bool & dnssec_valid,
std::function< std::string(const std::string &, const std::vector< std::string > &, bool)> dns_confirm )

Definition at line 479 of file dns_utils.cpp.

480{
481 // attempt to get address from dns query
482 auto addresses = addresses_from_url(url, dnssec_valid);
483 if (addresses.empty())
484 {
485 LOG_ERROR("wrong address: " << url);
486 return {};
487 }
488 return dns_confirm(url, addresses, dnssec_valid);
489}
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
std::vector< std::string > addresses_from_url(const std::string &url, bool &dnssec_valid)
gets a electroneum address from the TXT record of a DNS entry
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_txt_records_from_dns()

bool tools::dns_utils::load_txt_records_from_dns ( std::vector< std::string > & good_records,
const std::vector< std::string > & dns_urls,
std::string type )

Definition at line 515 of file dns_utils.cpp.

516{
517 // Prevent infinite recursion when distributing
518 if (dns_urls.empty()) return false;
519
520 std::vector<std::vector<std::string> > records;
521 records.resize(dns_urls.size());
522
523 size_t first_index = crypto::rand_idx(dns_urls.size());
524
525 // send all requests in parallel
526 std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false);
529 for (size_t n = 0; n < dns_urls.size(); ++n)
530 {
531 tpool.submit(&waiter,[n, dns_urls, &records, &avail, &valid](){
532 records[n] = tools::DNSResolver::instance().get_txt_record(dns_urls[n], avail[n], valid[n]);
533 });
534 }
535 waiter.wait(&tpool);
536
537 size_t cur_index = first_index;
538 do
539 {
540 const std::string &url = dns_urls[cur_index];
541 if (!avail[cur_index])
542 {
543 records[cur_index].clear();
544 LOG_PRINT_L2("DNSSEC not available for " << type << " at URL: " << url << ", skipping.");
545 }
546 if (!valid[cur_index])
547 {
548 records[cur_index].clear();
549 LOG_PRINT_L2("DNSSEC validation failed for " << type << " at URL: " << url << ", skipping.");
550 }
551
552 cur_index++;
553 if (cur_index == dns_urls.size())
554 {
555 cur_index = 0;
556 }
557 } while (cur_index != first_index);
558
559 size_t num_valid_records = 0;
560
561 for( const auto& record_set : records)
562 {
563 if (record_set.size() != 0)
564 {
565 num_valid_records++;
566 }
567 }
568
569 if (num_valid_records < 2)
570 {
571 LOG_PRINT_L1("WARNING: no two valid ElectroneumPulse DNS " << type << " records were received, only " << num_valid_records);
572 return false;
573 }
574
575 int good_records_index = -1;
576 for (size_t i = 0; i < records.size() - 1; ++i)
577 {
578 if (records[i].size() == 0) continue;
579
580 for (size_t j = i + 1; j < records.size(); ++j)
581 {
582 if (dns_records_match(records[i], records[j]))
583 {
584 good_records_index = i;
585 break;
586 }
587 }
588 if (good_records_index >= 0) break;
589 }
590
591 if (good_records_index < 0)
592 {
593 LOG_PRINT_L1("WARNING: no two ElectroneumPulse DNS " << type << " records matched");
594 return false;
595 }
596
597 good_records = records[good_records_index];
598 return true;
599}
void wait(threadpool *tpool)
A global thread pool.
Definition threadpool.h:44
void submit(waiter *waiter, std::function< void()> f, bool leaf=false)
static threadpool & getInstance()
Definition threadpool.h:46
#define LOG_PRINT_L1(x)
#define LOG_PRINT_L2(x)
std::enable_if< std::is_unsigned< T >::value, T >::type rand_idx(T sz)
Definition crypto.h:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_dns_public()

std::vector< std::string > tools::dns_utils::parse_dns_public ( const char * s)

Definition at line 601 of file dns_utils.cpp.

602{
603 unsigned ip0, ip1, ip2, ip3;
604 char c;
605 std::vector<std::string> dns_public_addr;
606 if (!strcmp(s, "tcp"))
607 {
608 for (size_t i = 0; i < sizeof(DEFAULT_DNS_PUBLIC_ADDR) / sizeof(DEFAULT_DNS_PUBLIC_ADDR[0]); ++i)
609 dns_public_addr.push_back(DEFAULT_DNS_PUBLIC_ADDR[i]);
610 LOG_PRINT_L0("Using default public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
611 }
612 else if (sscanf(s, "tcp://%u.%u.%u.%u%c", &ip0, &ip1, &ip2, &ip3, &c) == 4)
613 {
614 if (ip0 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255)
615 {
616 MERROR("Invalid IP: " << s << ", using default");
617 }
618 else
619 {
620 dns_public_addr.push_back(std::string(s + strlen("tcp://")));
621 }
622 }
623 else
624 {
625 MERROR("Invalid DNS_PUBLIC contents, ignored");
626 }
627 return dns_public_addr;
628}
#define MERROR(x)
Definition misc_log_ex.h:73
#define LOG_PRINT_L0(x)
Definition misc_log_ex.h:99
Here is the caller graph for this function: