blob: fdb7fe42310b5592f2b92c8f361996570e9ad864 [file] [log] [blame]
// 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 "chrome/browser/extensions/api/mdns/dns_sd_device_lister.h"
#include <utility>
#include "base/bind.h"
#include "chrome/browser/local_discovery/service_discovery_shared_client.h"
#include "chrome/common/extensions/api/mdns.h"
#include "net/base/net_util.h"
using local_discovery::ServiceDescription;
using local_discovery::ServiceDiscoverySharedClient;
using local_discovery::ServiceResolver;
using local_discovery::ServiceWatcher;
namespace extensions {
namespace {
void FillServiceInfo(const ServiceDescription& service_description,
DnsSdService* service) {
service->service_name = service_description.service_name;
service->service_host_port = service_description.address.ToString();
if (!service_description.ip_address.empty()) {
service->ip_address = net::IPAddressToString(
service_description.ip_address);
}
service->service_data = service_description.metadata;
DVLOG(1) << "Found " << service->service_name << ", "
<< service->service_host_port << ", "
<< service->ip_address;
}
} // namespace
DnsSdDeviceLister::DnsSdDeviceLister(
DnsSdDelegate* delegate,
const std::string& service_type,
ServiceDiscoverySharedClient* service_discovery_client)
: delegate_(delegate),
service_type_(service_type),
service_discovery_client_(service_discovery_client) {
}
DnsSdDeviceLister::~DnsSdDeviceLister() {}
void DnsSdDeviceLister::Discover(bool force_update) {
if (!service_discovery_client_)
return;
if (!service_watcher_.get()) {
service_watcher_ = service_discovery_client_->CreateServiceWatcher(
service_type_,
base::Bind(&DnsSdDeviceLister::OnServiceUpdated,
base::Unretained(this)));
service_watcher_->Start();
}
service_watcher_->DiscoverNewServices(force_update);
}
void DnsSdDeviceLister::OnServiceUpdated(
ServiceWatcher::UpdateType update,
const std::string& service_name) {
// TODO(justinlin): Consolidate with PrivetDeviceListerImpl.
if (update != ServiceWatcher::UPDATE_REMOVED) {
bool added = (update == ServiceWatcher::UPDATE_ADDED);
std::pair<ServiceResolverMap::iterator, bool> insert_result =
resolvers_.insert(make_pair(service_name,
linked_ptr<ServiceResolver>(NULL)));
// If there is already a resolver working on this service, don't add one.
if (insert_result.second) {
scoped_ptr<ServiceResolver> resolver =
service_discovery_client_->CreateServiceResolver(
service_name, base::Bind(
&DnsSdDeviceLister::OnResolveComplete,
base::Unretained(this),
added));
insert_result.first->second.reset(resolver.release());
insert_result.first->second->StartResolving();
}
} else {
delegate_->ServiceRemoved(service_type_, service_name);
}
}
void DnsSdDeviceLister::OnResolveComplete(
bool added,
ServiceResolver::RequestStatus status,
const ServiceDescription& service_description) {
// TODO(justinlin): Consolidate with PrivetDeviceListerImpl.
if (status != ServiceResolver::STATUS_SUCCESS) {
resolvers_.erase(service_description.service_name);
// TODO(noamsml): Add retry logic.
return;
}
DnsSdService service;
FillServiceInfo(service_description, &service);
resolvers_.erase(service_description.service_name);
delegate_->ServiceChanged(service_type_, added, service);
}
} // namespace extensions