1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "base/at_exit.h" 8 #include "base/bind.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "chrome/tools/service_discovery_sniffer/service_discovery_sniffer.h" 12 #include "chrome/utility/local_discovery/service_discovery_client_impl.h" 13 #include "net/dns/mdns_client.h" 14 15 namespace local_discovery { 16 17 ServicePrinter::ServicePrinter(ServiceDiscoveryClient* client, 18 const std::string& service_name) 19 : changed_(false) { 20 service_resolver_ = 21 client->CreateServiceResolver( 22 service_name, 23 base::Bind(&ServicePrinter::OnServiceResolved, 24 base::Unretained(this))); 25 } 26 27 ServicePrinter::~ServicePrinter() { 28 } 29 30 void ServicePrinter::Added() { 31 changed_ = false; 32 service_resolver_->StartResolving(); 33 } 34 35 void ServicePrinter::Changed() { 36 changed_ = true; 37 service_resolver_->StartResolving(); 38 } 39 40 void ServicePrinter::Removed() { 41 printf("Service Removed: %s\n", service_resolver_->GetName().c_str()); 42 } 43 44 void ServicePrinter::OnServiceResolved(ServiceResolver::RequestStatus status, 45 const ServiceDescription& service) { 46 if (changed_) { 47 printf("Service Updated: %s\n", service.instance_name().c_str()); 48 } else { 49 printf("Service Added: %s\n", service.instance_name().c_str()); 50 } 51 52 printf("\tAddress: %s:%d\n", service.address.host().c_str(), 53 service.address.port()); 54 printf("\tMetadata: \n"); 55 for (std::vector<std::string>::const_iterator i = service.metadata.begin(); 56 i != service.metadata.end(); i++) { 57 printf("\t\t%s\n", i->c_str()); 58 } 59 60 if (service.ip_address != net::IPAddressNumber()) { 61 printf("\tIP Address: %s\n", net::IPAddressToString( 62 service.ip_address).c_str()); 63 } 64 } 65 66 ServiceTypePrinter::ServiceTypePrinter(ServiceDiscoveryClient* client, 67 const std::string& service_type) 68 : client_(client) { 69 watcher_ = client_->CreateServiceWatcher( 70 service_type, base::Bind(&ServiceTypePrinter::OnServiceUpdated, 71 base::Unretained(this))); 72 } 73 74 void ServiceTypePrinter::Start() { 75 watcher_->Start(); 76 watcher_->DiscoverNewServices(false); 77 } 78 79 ServiceTypePrinter::~ServiceTypePrinter() { 80 } 81 82 void ServiceTypePrinter::OnServiceUpdated(ServiceWatcher::UpdateType update, 83 const std::string& service_name) { 84 if (update == ServiceWatcher::UPDATE_ADDED) { 85 services_[service_name].reset(new ServicePrinter(client_, service_name)); 86 services_[service_name]->Added(); 87 } else if (update == ServiceWatcher::UPDATE_CHANGED) { 88 services_[service_name]->Changed(); 89 } else if (update == ServiceWatcher::UPDATE_REMOVED) { 90 services_[service_name]->Removed(); 91 services_.erase(service_name); 92 } 93 } 94 95 } // namespace local_discovery 96 97 int main(int argc, char** argv) { 98 base::AtExitManager at_exit_manager; 99 base::MessageLoopForIO message_loop; 100 101 if (argc != 2) { 102 printf("Please provide exactly 1 argument.\n"); 103 return 1; 104 } 105 106 scoped_ptr<net::MDnsClient> mdns_client = net::MDnsClient::CreateDefault(); 107 scoped_ptr<net::MDnsSocketFactory> socket_factory = 108 net::MDnsSocketFactory::CreateDefault(); 109 mdns_client->StartListening(socket_factory.get()); 110 scoped_ptr<local_discovery::ServiceDiscoveryClient> service_discovery_client; 111 service_discovery_client.reset( 112 new local_discovery::ServiceDiscoveryClientImpl(mdns_client.get())); 113 { 114 // To guarantee/make explicit the ordering constraint. 115 local_discovery::ServiceTypePrinter print_changes( 116 service_discovery_client.get(), 117 std::string(argv[1]) + "._tcp.local"); 118 119 print_changes.Start(); 120 message_loop.Run(); 121 } 122 } 123