176 uint16_t
id = htons (packet.id);
177 data.write (
reinterpret_cast<const char*
> (&
id),
sizeof (
id));
179 uint16_t flags = htons (packet.flags);
180 data.write (
reinterpret_cast<const char*
> (&flags),
sizeof (flags));
182 uint16_t qcount = htons (
static_cast<uint16_t
> (packet.questions.size ()));
183 data.write (
reinterpret_cast<const char*
> (&qcount),
sizeof (qcount));
185 uint16_t ancount = htons (
static_cast<uint16_t
> (packet.answers.size ()));
186 data.write (
reinterpret_cast<const char*
> (&ancount),
sizeof (ancount));
188 uint16_t nscount = htons (
static_cast<uint16_t
> (packet.authorities.size ()));
189 data.write (
reinterpret_cast<const char*
> (&nscount),
sizeof (nscount));
191 uint16_t arcount = htons (
static_cast<uint16_t
> (packet.additionals.size ()));
192 data.write (
reinterpret_cast<const char*
> (&arcount),
sizeof (arcount));
194 for (
auto const& question : packet.questions)
196 if (encodeQuestion (question, data) == -1)
202 for (
auto const& answer : packet.answers)
204 if (encodeResource (answer, data) == -1)
210 for (
auto const& authority : packet.authorities)
212 if (encodeResource (authority, data) == -1)
218 for (
auto const& additional : packet.additionals)
220 if (encodeResource (additional, data) == -1)
237 data.read (
reinterpret_cast<char*
> (&packet.
id), sizeof (packet.
id));
238 packet.
id = ntohs (packet.
id);
240 data.read (
reinterpret_cast<char*
> (&packet.
flags), sizeof (packet.
flags));
244 data.read (
reinterpret_cast<char*
> (&qcount),
sizeof (qcount));
245 qcount = ntohs (qcount);
247 uint16_t ancount = 0;
248 data.read (
reinterpret_cast<char*
> (&ancount),
sizeof (ancount));
249 ancount = ntohs (ancount);
251 uint16_t nscount = 0;
252 data.read (
reinterpret_cast<char*
> (&nscount),
sizeof (nscount));
253 nscount = ntohs (nscount);
255 uint16_t arcount = 0;
256 data.read (
reinterpret_cast<char*
> (&arcount),
sizeof (arcount));
257 arcount = ntohs (arcount);
260 for (uint16_t i = 0; i < qcount; ++i)
263 if (decodeQuestion (question, data) == -1)
267 packet.
questions.emplace_back (std::move (question));
271 for (uint16_t i = 0; i < ancount; ++i)
274 if (decodeResource (answer, data) == -1)
278 packet.
answers.emplace_back (std::move (answer));
282 for (uint16_t i = 0; i < nscount; ++i)
285 if (decodeResource (authority, data) == -1)
289 packet.
authorities.emplace_back (std::move (authority));
293 for (uint16_t i = 0; i < arcount; ++i)
296 if (decodeResource (additional, data) == -1)
300 packet.
additionals.emplace_back (std::move (additional));
362 switch (recordClass & 0x7FFF)
377 int encodeName (
const std::string& name, std::stringstream& data)
const
379 std::istringstream iss (name);
381 for (std::string token; std::getline (iss, token,
'.');)
383 data << static_cast<uint8_t> (token.size ());
399 int decodeName (std::string& name, std::stringstream& data,
int depth = 0)
const
408 auto pos = data.tellg ();
411 data.read (
reinterpret_cast<char*
> (&offset),
sizeof (offset));
412 offset = ntohs (offset);
417 data.seekg (offset & 0x3FFF);
418 if (decodeName (name, data, depth + 1) == -1)
430 data.read (
reinterpret_cast<char*
> (&size),
sizeof (size));
434 if (!name.empty () && name.back () ==
'.')
441 name.resize (name.size () + size);
442 data.read (&name[name.size () - size], size);
456 int encodeMail (
const std::string& mail, std::stringstream& data)
const
458 std::string encodedMail = mail;
459 size_t atPos = encodedMail.find (
'@');
461 if (atPos != std::string::npos)
463 encodedMail.replace (atPos, 1,
".");
466 encodeName (encodedMail, data);
477 int decodeMail (std::string& mail, std::stringstream& data)
const
479 if (decodeName (mail, data) == -1)
484 auto pos = mail.find (
'.');
485 if (pos != std::string::npos)
499 int encodeQuestion (
const QuestionRecord& question, std::stringstream& data)
const
501 encodeName (question.host, data);
503 uint16_t type = htons (question.type);
504 data.write (
reinterpret_cast<const char*
> (&type),
sizeof (type));
506 uint16_t dnsclass = htons (question.dnsclass);
507 data.write (
reinterpret_cast<const char*
> (&dnsclass),
sizeof (dnsclass));
518 int decodeQuestion (QuestionRecord& question, std::stringstream& data)
const
520 if (decodeName (question.host, data) == -1)
525 data.read (
reinterpret_cast<char*
> (&question.type), sizeof (question.type));
526 question.type = ntohs (question.type);
528 data.read (
reinterpret_cast<char*
> (&question.dnsclass), sizeof (question.dnsclass));
529 question.dnsclass = ntohs (question.dnsclass);
540 int encodeResource (
const ResourceRecord& resource, std::stringstream& data)
const
542 encodeName (resource.host, data);
544 uint16_t type = htons (resource.type);
545 data.write (
reinterpret_cast<const char*
> (&type),
sizeof (type));
547 uint16_t dnsclass = htons (resource.dnsclass);
548 data.write (
reinterpret_cast<const char*
> (&dnsclass),
sizeof (dnsclass));
550 uint32_t ttl = htonl (resource.ttl);
551 data.write (
reinterpret_cast<const char*
> (&ttl),
sizeof (ttl));
553 uint16_t dataLen = 0;
554 auto dataLenPos = data.tellp ();
555 data.write (
reinterpret_cast<const char*
> (&dataLen),
sizeof (dataLen));
557 auto dataBegPos = data.tellp ();
561 data.write (
reinterpret_cast<const char*
> (resource.addr.addr ()), sizeof (in_addr));
565 data.write (
reinterpret_cast<const char*
> (resource.addr.addr ()), sizeof (in6_addr));
569 encodeName (resource.name, data);
573 encodeName (resource.name, data);
577 encodeName (resource.name, data);
581 uint16_t mxpref = htons (resource.mxpref);
582 data.write (
reinterpret_cast<const char*
> (&mxpref),
sizeof (mxpref));
583 encodeName (resource.name, data);
587 encodeName (resource.name, data);
588 encodeMail (resource.mail, data);
590 uint32_t serial = htonl (resource.serial);
591 data.write (
reinterpret_cast<const char*
> (&serial),
sizeof (serial));
593 uint32_t refresh = htonl (resource.refresh);
594 data.write (
reinterpret_cast<const char*
> (&refresh),
sizeof (refresh));
596 uint32_t retry = htonl (resource.retry);
597 data.write (
reinterpret_cast<const char*
> (&retry),
sizeof (retry));
599 uint32_t expire = htonl (resource.expire);
600 data.write (
reinterpret_cast<const char*
> (&expire),
sizeof (expire));
602 uint32_t minimum = htonl (resource.minimum);
603 data.write (
reinterpret_cast<const char*
> (&minimum),
sizeof (minimum));
607 for (
auto const& txt : resource.txts)
609 uint8_t size =
static_cast<uint8_t
> (txt.size ());
610 data.write (
reinterpret_cast<const char*
> (&size),
sizeof (size));
611 data.write (txt.data (), size);
616 uint16_t priority = htons (resource.priority);
617 data.write (
reinterpret_cast<const char*
> (&priority),
sizeof (priority));
619 uint16_t weight = htons (resource.weight);
620 data.write (
reinterpret_cast<const char*
> (&weight),
sizeof (weight));
622 uint16_t
port = htons (resource.port);
623 data.write (
reinterpret_cast<const char*
> (&
port),
sizeof (
port));
625 encodeName (resource.name, data);
628 auto dataEndPos = data.tellp ();
629 dataLen =
static_cast<uint16_t
> (dataEndPos - dataBegPos);
631 data.seekp (dataLenPos);
632 dataLen = htons (dataLen);
633 data.write (
reinterpret_cast<const char*
> (&dataLen),
sizeof (dataLen));
634 data.seekp (dataEndPos);
645 int decodeResource (ResourceRecord& resource, std::stringstream& data)
const
647 if (decodeName (resource.host, data) == -1)
652 data.read (
reinterpret_cast<char*
> (&resource.type), sizeof (resource.type));
653 resource.type = ntohs (resource.type);
655 data.read (
reinterpret_cast<char*
> (&resource.dnsclass), sizeof (resource.dnsclass));
656 resource.dnsclass = ntohs (resource.dnsclass);
658 data.read (
reinterpret_cast<char*
> (&resource.ttl), sizeof (resource.ttl));
659 resource.ttl = ntohl (resource.ttl);
661 uint16_t dataLen = 0;
662 data.read (
reinterpret_cast<char*
> (&dataLen),
sizeof (dataLen));
663 dataLen = ntohs (dataLen);
665 auto dataBegPos = data.tellg ();
670 data.read (
reinterpret_cast<char*
> (&addr),
sizeof (addr));
671 resource.addr = IpAddress (&addr,
sizeof (
struct in_addr));
675 struct in6_addr addr;
676 data.read (
reinterpret_cast<char*
> (&addr),
sizeof (addr));
677 resource.addr = IpAddress (&addr,
sizeof (
struct in6_addr));
681 if (decodeName (resource.name, data) == -1)
688 if (decodeName (resource.name, data) == -1)
695 if (decodeName (resource.name, data) == -1)
702 data.read (
reinterpret_cast<char*
> (&resource.mxpref), sizeof (resource.mxpref));
703 resource.mxpref = ntohs (resource.mxpref);
705 if (decodeName (resource.name, data) == -1)
712 if (decodeName (resource.name, data) == -1)
717 decodeMail (resource.mail, data);
719 data.read (
reinterpret_cast<char*
> (&resource.serial), sizeof (resource.serial));
720 resource.serial = ntohl (resource.serial);
722 data.read (
reinterpret_cast<char*
> (&resource.refresh), sizeof (resource.refresh));
723 resource.refresh = ntohl (resource.refresh);
725 data.read (
reinterpret_cast<char*
> (&resource.retry), sizeof (resource.retry));
726 resource.retry = ntohl (resource.retry);
728 data.read (
reinterpret_cast<char*
> (&resource.expire), sizeof (resource.expire));
729 resource.expire = ntohl (resource.expire);
731 data.read (
reinterpret_cast<char*
> (&resource.minimum), sizeof (resource.minimum));
732 resource.minimum = ntohl (resource.minimum);
736 while (data.tellg () != -1 && (data.tellg () - dataBegPos < dataLen))
739 if (!data.read (
reinterpret_cast<char*
> (&size), sizeof (size)))
746 if (!data.read (&txt[0], size))
751 resource.txts.emplace_back (std::move (txt));
756 data.read (
reinterpret_cast<char*
> (&resource.priority), sizeof (resource.priority));
757 resource.priority = ntohs (resource.priority);
759 data.read (
reinterpret_cast<char*
> (&resource.weight), sizeof (resource.weight));
760 resource.weight = ntohs (resource.weight);
762 data.read (
reinterpret_cast<char*
> (&resource.port), sizeof (resource.port));
763 resource.port = ntohs (resource.port);
765 if (decodeName (resource.name, data) == -1)
772 data.seekg (dataBegPos +
static_cast<std::streamoff
> (dataLen));