privet_device_lister_impl.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <string>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <utility>
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <vector>
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/bind.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringprintf.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/local_discovery/privet_constants.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace local_discovery {
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetDeviceListerImpl::PrivetDeviceListerImpl(
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ServiceDiscoveryClient* service_discovery_client,
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PrivetDeviceLister::Delegate* delegate)
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : delegate_(delegate),
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      service_discovery_client_(service_discovery_client),
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      service_type_(kPrivetDefaultDeviceType) {
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetDeviceListerImpl::PrivetDeviceListerImpl(
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ServiceDiscoveryClient* service_discovery_client,
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PrivetDeviceLister::Delegate* delegate,
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string subtype) : delegate_(delegate),
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           service_discovery_client_(service_discovery_client),
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           service_type_(
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                               base::StringPrintf(kPrivetSubtypeTemplate,
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                  subtype.c_str())) {
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetDeviceListerImpl::~PrivetDeviceListerImpl() {
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetDeviceListerImpl::Start() {
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  service_watcher_ =
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      service_discovery_client_->CreateServiceWatcher(
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          service_type_,
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          base::Bind(&PrivetDeviceListerImpl::OnServiceUpdated,
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                     base::Unretained(this)));
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  service_watcher_->Start();
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetDeviceListerImpl::DiscoverNewDevices(bool force_update) {
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  service_watcher_->DiscoverNewServices(force_update);
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetDeviceListerImpl::OnServiceUpdated(
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ServiceWatcher::UpdateType update,
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& service_name) {
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (update != ServiceWatcher::UPDATE_REMOVED) {
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bool added = (update == ServiceWatcher::UPDATE_ADDED);
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::pair<ServiceResolverMap::iterator, bool> insert_result =
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        resolvers_.insert(make_pair(service_name,
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                    linked_ptr<ServiceResolver>(NULL)));
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // If there is already a resolver working on this service, don't add one.
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (insert_result.second) {
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      scoped_ptr<ServiceResolver> resolver =
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          service_discovery_client_->CreateServiceResolver(
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          service_name, base::Bind(
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              &PrivetDeviceListerImpl::OnResolveComplete,
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              base::Unretained(this),
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              added));
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      insert_result.first->second.reset(resolver.release());
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      insert_result.first->second->StartResolving();
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    delegate_->DeviceRemoved(service_name);
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetDeviceListerImpl::OnResolveComplete(
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bool added,
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ServiceResolver::RequestStatus status,
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const ServiceDescription& service_description) {
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (status != ServiceResolver::STATUS_SUCCESS) {
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    resolvers_.erase(service_description.service_name);
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // TODO(noamsml): Add retry logic.
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DeviceDescription device_description;
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FillDeviceDescription(service_description, &device_description);
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string service_name = service_description.service_name;
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  resolvers_.erase(service_name);
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  delegate_->DeviceChanged(added, service_name, device_description);
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrivetDeviceListerImpl::FillDeviceDescription(
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const ServiceDescription& service_description,
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DeviceDescription* device_description) {
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  device_description->address = service_description.address;
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  device_description->ip_address = service_description.ip_address;
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  device_description->last_seen = service_description.last_seen;
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (std::vector<std::string>::const_iterator i =
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           service_description.metadata.begin();
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       i < service_description.metadata.end();
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       i++) {
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t equals_pos = i->find_first_of('=');
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (equals_pos == std::string::npos)
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;  // We do not parse non key-value TXT records
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string key = i->substr(0, equals_pos);
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string value = i->substr(equals_pos + 1);
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (LowerCaseEqualsASCII(key, kPrivetTxtKeyName)) {
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->name = value;
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyDescription)) {
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->description = value;
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyURL)) {
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->url = value;
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyType)) {
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->type = value;
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyID)) {
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->id = value;
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyConnectionState)) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      device_description->connection_state = ConnectionStateFromString(value);
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDeviceDescription::ConnectionState
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochPrivetDeviceListerImpl::ConnectionStateFromString(const std::string& str) {
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOnline)) {
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return DeviceDescription::ONLINE;
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOffline)) {
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return DeviceDescription::OFFLINE;
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusConnecting)) {
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return DeviceDescription::CONNECTING;
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusNotConfigured)) {
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return DeviceDescription::NOT_CONFIGURED;
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return DeviceDescription::UNKNOWN;
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace local_discovery
147