Index: cloud_print/gcp20/prototype/dns_sd.cc |
diff --git a/cloud_print/gcp20/prototype/dns_sd.cc b/cloud_print/gcp20/prototype/dns_sd.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e51de03a8bdcc9e2bed57c8c782f7bf5f67f271a |
--- /dev/null |
+++ b/cloud_print/gcp20/prototype/dns_sd.cc |
@@ -0,0 +1,186 @@ |
+// 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/dns_sd.h" |
+ |
+#include <string.h> |
+ |
+#include "base/basictypes.h" |
+#include "net/base/big_endian.h" |
+#include "net/base/net_util.h" |
+#include "net/dns/dns_protocol.h" |
+ |
+namespace { |
+ |
+const char* kDefaultIpAddressMulticast = "224.0.0.251"; |
+const uint16 kDefaultPortMulticast = 5353; |
+ |
+// TODO(maksymb): Add possibility to set constants via command line arguments |
+const uint32 kDefaultTTL = 60*60; // in seconds |
+ |
+} // namespace |
+ |
+DnsSd::DnsSd(): is_online_(false) { |
+ // Do nothing |
+} |
+ |
+DnsSd::~DnsSd() { |
+ Shutdown(); |
+} |
+ |
+bool DnsSd::Start() { |
+ if (is_online_) |
+ return true; |
+ |
+ if (!BindSocket()) |
+ return false; |
+ |
+ LOG(INFO) << "DNS server started"; |
+ |
+ SendAnnouncement(kDefaultTTL); |
+ |
+ is_online_ = true; |
+ return true; |
+} |
+ |
+void DnsSd::Update() { |
+ if (!is_online_) |
+ return; |
+ |
+ SendAnnouncement(kDefaultTTL); |
+} |
+ |
+void DnsSd::Shutdown() { |
+ if (!is_online_) |
+ return; |
+ |
+ SendAnnouncement(0); // ttl is 0 |
+ socket_->Close(); |
+ is_online_ = false; |
+ LOG(INFO) << "DNS server stopped"; |
+} |
+ |
+bool DnsSd::BindSocket() { |
gene
2013/06/06 00:13:51
BindSocket -> CreateSocket ?
maksymb
2013/06/06 01:52:46
Done.
|
+ net::IPAddressNumber local_ip_any; |
+ bool success = net::ParseIPLiteralToNumber("0.0.0.0", &local_ip_any); |
+ DCHECK(success); |
+ |
+ net::IPAddressNumber multicast_dns_ip_address; |
+ success = net::ParseIPLiteralToNumber(kDefaultIpAddressMulticast, |
+ &multicast_dns_ip_address); |
+ DCHECK(success); |
+ |
+ |
+ socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND, |
+ net::RandIntCallback(), |
+ NULL, |
+ net::NetLog::Source())); |
+ |
+ net::IPEndPoint local_address = net::IPEndPoint(local_ip_any, |
+ kDefaultPortMulticast); |
+ multicast_address_ = net::IPEndPoint(multicast_dns_ip_address, |
+ kDefaultPortMulticast); |
+ |
+ socket_->AllowAddressReuse(); |
+ |
+ int status = socket_->Bind(local_address); |
+ if (status < 0) |
+ return false; |
+ |
+ socket_->SetMulticastLoopbackMode(false); |
+ status = socket_->JoinGroup(multicast_dns_ip_address); |
+ |
+ if (status < 0) |
+ return false; |
+ |
+ DCHECK(socket_->is_connected()); |
+ |
+ return true; |
+} |
+ |
+bool DnsSd::CheckPendingQueries() { |
+ // write code |
+ return false; |
+} |
+ |
+void DoNothing(int /*var*/) { |
+ // Do nothing |
+} |
+ |
+void DnsSd::SendAnnouncement(uint32 ttl) { |
+ // Create a message with allocated space for header. |
+ scoped_ptr<std::vector<uint8> > message( |
+ new std::vector<uint8>(sizeof(net::dns_protocol::Header))); |
+ |
+ // These variables will be autimaticaly calculated in |Append*| methods. |
+ question_count_ = 0; |
gene
2013/06/06 00:13:51
I think it is better not to make question_count_ a
maksymb
2013/06/06 01:52:46
Done.
|
+ answers_count_ = 0; |
+ |
+ // AppendSrv(ttl, message.get()); |
+ // AppendPtr(ttl, message.get()); |
+ // AppendTxt(ttl, message.get()); |
+ // AppendA(ttl, message.get()); |
+ UpdateHeader(false/*no question*/, message.get()); |
gene
2013/06/06 00:13:51
It is better to create header here, or pass all pa
maksymb
2013/06/06 01:52:46
Cleared. Created temporary dump.
|
+ |
+ |
gene
2013/06/06 00:13:51
extra empty line
maksymb
2013/06/06 01:52:46
Done.
|
+ // Preparing for sending |
+ scoped_refptr<net::IOBufferWithSize> buffer = |
+ new net::IOBufferWithSize(message.get()->size()); |
+ memcpy(buffer.get()->data(), message.get()->data(), message.get()->size()); |
+ |
+ // Create empty callback (we don't need it at all) and send packet |
+ net::CompletionCallback callback = base::Bind(DoNothing); |
+ socket_->SendTo(buffer.get(), |
+ buffer.get()->size(), |
+ multicast_address_, |
+ callback); |
+ |
+ LOG(INFO) << "Announcement was sent with TTL: " << ttl; |
+} |
+ |
+void DnsSd::UpdateHeader(bool is_question, std::vector<uint8>* message) { |
+ net::dns_protocol::Header header; |
+ header.id = 0; |
+ header.flags = 0; // setting flags is below |
+ header.qdcount = question_count_; |
+ header.ancount = answers_count_; |
+ header.nscount = 0; |
+ header.arcount = 0; |
+ |
+ // Setting flags |
+ header.flags = 0; |
+ if (is_question) |
+ header.flags |= net::dns_protocol::kFlagResponse; |
+ |
+ // Putting into message (place for header already should be allocated) |
+ 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); |
+ DCHECK(success); |
+} |
+ |
+void DnsSd::AppendSrv(uint32 /*ttl*/, std::vector<uint8>* /* message*/) { |
+ ++answers_count_; |
+// write code |
gene
2013/06/06 00:13:51
"// write code" -> "NOTIMPLEMENTED(); // implemen
maksymb
2013/06/06 01:52:46
Done.
|
+} |
+ |
+void DnsSd::AppendPtr(uint32 /*ttl*/, std::vector<uint8>* /* message*/) { |
+ ++answers_count_; |
+// write code |
+} |
+ |
+void DnsSd::AppendTxt(uint32 /*ttl*/, std::vector<uint8>* /* message*/) { |
+ ++answers_count_; |
+// write code |
+} |
+ |
+void DnsSd::AppendA(uint32 /*ttl*/, std::vector<uint8>* /* message*/) { |
+ ++answers_count_; |
+// write code |
+} |
+ |