| Index: cloud_print/gcp20/prototype/privet_dns_response_builder.cc
|
| diff --git a/cloud_print/gcp20/prototype/privet_dns_response_builder.cc b/cloud_print/gcp20/prototype/privet_dns_response_builder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fd7457f8f51c5f0e1363ce720225ab3fcc6a26eb
|
| --- /dev/null
|
| +++ b/cloud_print/gcp20/prototype/privet_dns_response_builder.cc
|
| @@ -0,0 +1,195 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "cloud_print/gcp20/prototype/privet_dns_response_builder.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "cloud_print/gcp20/prototype/dns_txt_builder.h"
|
| +#include "net/base/big_endian.h"
|
| +#include "net/base/dns_util.h"
|
| +#include "net/base/ip_endpoint.h"
|
| +
|
| +namespace {
|
| +
|
| +const char* kServiceType = "_privet._tcp.local";
|
| +const uint16 kSrvPriority = 0;
|
| +const uint16 kSrvWeight = 0;
|
| +
|
| +uint16 klass = net::dns_protocol::kClassIN;
|
| +
|
| +} // namespace
|
| +
|
| +PrivetDnsResponseBuilder::PrivetDnsResponseBuilder(
|
| + uint16 id,
|
| + const std::string& service_name_prefix,
|
| + const std::string& service_domain_name,
|
| + const net::IPAddressNumber& http_ip,
|
| + uint16 http_port)
|
| + : service_name_(service_name_prefix + "." + kServiceType),
|
| + service_domain_name_(service_domain_name),
|
| + http_ip_(http_ip),
|
| + http_port_(http_port) {
|
| + header_.id = id;
|
| + // TODO(maksymb): Check do we need AA flag enabled.
|
| + header_.flags = net::dns_protocol::kFlagResponse |
|
| + net::dns_protocol::kFlagAA;
|
| + header_.qdcount = 0;
|
| + header_.ancount = 0;
|
| + header_.nscount = 0;
|
| + header_.arcount = 0;
|
| +}
|
| +
|
| +PrivetDnsResponseBuilder::~PrivetDnsResponseBuilder() {
|
| +}
|
| +
|
| +bool PrivetDnsResponseBuilder::IsSamePtr(const std::string& qname) {
|
| + return qname == kServiceType;
|
| +}
|
| +
|
| +bool PrivetDnsResponseBuilder::IsSameSrv(const std::string& qname) {
|
| + return qname == service_name_;
|
| +}
|
| +
|
| +bool PrivetDnsResponseBuilder::IsSameA(const std::string& qname) {
|
| + return qname == service_domain_name_;
|
| +}
|
| +
|
| +bool PrivetDnsResponseBuilder::IsSameTxt(const std::string& qname) {
|
| + return qname == service_name_;
|
| +}
|
| +
|
| +void PrivetDnsResponseBuilder::AppendPtr(uint32 ttl) {
|
| + std::string rdata;
|
| + bool success = net::DNSDomainFromDot(service_name_, &rdata);
|
| + DCHECK(success);
|
| +
|
| + AddResponse(kServiceType, net::dns_protocol::kTypePTR, ttl, rdata);
|
| +}
|
| +
|
| +void PrivetDnsResponseBuilder::AppendSrv(uint32 ttl) {
|
| + std::string domain_name;
|
| + bool success = net::DNSDomainFromDot(service_domain_name_, &domain_name);
|
| + DCHECK(success);
|
| +
|
| + int rdata_size = 2 + 2 + 2 + domain_name.size();
|
| + scoped_ptr<char[]> rdata(new char[rdata_size]);
|
| + net::BigEndianWriter writer(rdata.get(), rdata_size);
|
| +
|
| + success = writer.WriteU16(kSrvPriority) &&
|
| + writer.WriteU16(kSrvWeight) &&
|
| + writer.WriteU16(http_port_) &&
|
| + writer.WriteBytes(domain_name.data(), domain_name.size());
|
| + DCHECK(success);
|
| +
|
| + base::StringPiece rdata_sp;
|
| + rdata_sp.set(rdata.get(), rdata_size);
|
| + std::string rdata_string;
|
| + rdata_sp.CopyToString(&rdata_string);
|
| +
|
| + AddResponse(service_name_, net::dns_protocol::kTypeSRV, ttl, rdata_string);
|
| +}
|
| +
|
| +void PrivetDnsResponseBuilder::AppendA(uint32 ttl) {
|
| + if (http_ip_.empty()) {
|
| + LOG(ERROR) << "Invalid IP";
|
| + return;
|
| + }
|
| +
|
| + std::string rdata(http_ip_.begin(), http_ip_.end());
|
| +
|
| + AddResponse(service_domain_name_, net::dns_protocol::kTypeA, ttl, rdata);
|
| +}
|
| +
|
| +void PrivetDnsResponseBuilder::AppendTxt(uint32 ttl) {
|
| + DnsTxtBuilder txt_builder;
|
| +
|
| + txt_builder.AddRecord("txtvers=1");
|
| + txt_builder.AddRecord("ty=Google Cloud Ready Printer GCP2.0 Prototype");
|
| + txt_builder.AddRecord("note=Virtual printer");
|
| + txt_builder.AddRecord("url=https://www.google.com/cloudprint");
|
| + txt_builder.AddRecord("type=printer");
|
| + txt_builder.AddRecord("id=");
|
| + txt_builder.AddRecord("cs=offline");
|
| +
|
| + AddResponse(service_name_, net::dns_protocol::kTypeTXT, ttl,
|
| + txt_builder.Build());
|
| +}
|
| +
|
| +scoped_refptr<net::IOBufferWithSize> PrivetDnsResponseBuilder::Build() const {
|
| + scoped_refptr<net::IOBufferWithSize> message(
|
| + new net::IOBufferWithSize(sizeof(header_) +
|
| + responses_.size()));
|
| +
|
| + net::BigEndianWriter writer(message->data(), message->size());
|
| + bool success = writer.WriteU16(header_.id) &&
|
| + writer.WriteU16(header_.flags) &&
|
| + writer.WriteU16(header_.qdcount) &&
|
| + writer.WriteU16(header_.ancount) &&
|
| + writer.WriteU16(header_.nscount) &&
|
| + writer.WriteU16(header_.arcount) &&
|
| + writer.WriteBytes(responses_.data(), responses_.size());
|
| + DCHECK(success);
|
| + DCHECK_EQ(writer.remaining(), 0); // For warranty of correct size allocation.
|
| +
|
| + return message;
|
| +}
|
| +
|
| +scoped_refptr<net::IOBufferWithSize>
|
| + PrivetDnsResponseBuilder::BuildAnnouncement(uint32 ttl) {
|
| + this->AppendPtr(ttl);
|
| + this->AppendSrv(ttl);
|
| + this->AppendA(ttl);
|
| + this->AppendTxt(ttl);
|
| +
|
| + return this->Build();
|
| +}
|
| +
|
| +void PrivetDnsResponseBuilder::AddResponse(const std::string& name, uint16 type,
|
| + uint32 ttl,
|
| + const std::string& rdata) {
|
| + ++header_.ancount;
|
| +
|
| + std::string name_in_dns_format;
|
| + bool success = net::DNSDomainFromDot(name, &name_in_dns_format);
|
| + DCHECK(success);
|
| +
|
| + std::vector<uint8> current_respond(name_in_dns_format.size() + sizeof(type) +
|
| + sizeof(klass) + sizeof(ttl) +
|
| + 2 + // sizeof(RDLENGTH)
|
| + rdata.size());
|
| +
|
| + net::BigEndianWriter writer(current_respond.data(), current_respond.size());
|
| + success = writer.WriteBytes(name_in_dns_format.data(),
|
| + name_in_dns_format.size()) &&
|
| + writer.WriteU16(type) &&
|
| + writer.WriteU16(klass) &&
|
| + writer.WriteU32(ttl) &&
|
| + writer.WriteU16(static_cast<uint16>(rdata.size())) &&
|
| + writer.WriteBytes(rdata.data(), rdata.size());
|
| + DCHECK(success);
|
| + DCHECK_EQ(writer.remaining(), 0); // For warranty of correct size allocation.
|
| +
|
| + // Append current respond to all responds.
|
| + responses_.insert(responses_.end(), current_respond.begin(),
|
| + current_respond.end());
|
| +}
|
| +
|
| +PrivetDnsResponseBuilderFactory::PrivetDnsResponseBuilderFactory(
|
| + const std::string& service_name_prefix,
|
| + const std::string& service_domain_name,
|
| + const net::IPAddressNumber& http_ip,
|
| + uint16 http_port)
|
| + : service_name_prefix_(service_name_prefix),
|
| + service_domain_name_(service_domain_name),
|
| + http_ip_(http_ip),
|
| + http_port_(http_port) {
|
| +}
|
| +
|
| +DnsResponseBuilderInterface* PrivetDnsResponseBuilderFactory::Create(
|
| + uint16 id) {
|
| + return new PrivetDnsResponseBuilder(id, service_name_prefix_,
|
| + service_domain_name_, http_ip_,
|
| + http_port_);
|
| +}
|
| +
|
|
|