privet_device_lister_impl.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 "chrome/browser/local_discovery/privet_device_lister_impl.h" 6 7#include <string> 8#include <utility> 9#include <vector> 10 11#include "base/bind.h" 12#include "base/strings/string_util.h" 13#include "base/strings/stringprintf.h" 14#include "chrome/browser/local_discovery/privet_constants.h" 15 16namespace local_discovery { 17 18PrivetDeviceListerImpl::PrivetDeviceListerImpl( 19 ServiceDiscoveryClient* service_discovery_client, 20 PrivetDeviceLister::Delegate* delegate) 21 : delegate_(delegate), 22 service_discovery_client_(service_discovery_client), 23 service_type_(kPrivetDefaultDeviceType) { 24} 25 26PrivetDeviceListerImpl::PrivetDeviceListerImpl( 27 ServiceDiscoveryClient* service_discovery_client, 28 PrivetDeviceLister::Delegate* delegate, 29 std::string subtype) : delegate_(delegate), 30 service_discovery_client_(service_discovery_client), 31 service_type_( 32 base::StringPrintf(kPrivetSubtypeTemplate, 33 subtype.c_str())) { 34} 35 36PrivetDeviceListerImpl::~PrivetDeviceListerImpl() { 37} 38 39void PrivetDeviceListerImpl::Start() { 40 service_watcher_ = 41 service_discovery_client_->CreateServiceWatcher( 42 service_type_, 43 base::Bind(&PrivetDeviceListerImpl::OnServiceUpdated, 44 base::Unretained(this))); 45 service_watcher_->Start(); 46} 47 48void PrivetDeviceListerImpl::DiscoverNewDevices(bool force_update) { 49 service_watcher_->DiscoverNewServices(force_update); 50} 51 52void PrivetDeviceListerImpl::OnServiceUpdated( 53 ServiceWatcher::UpdateType update, 54 const std::string& service_name) { 55 if (update != ServiceWatcher::UPDATE_REMOVED) { 56 bool added = (update == ServiceWatcher::UPDATE_ADDED); 57 std::pair<ServiceResolverMap::iterator, bool> insert_result = 58 resolvers_.insert(make_pair(service_name, 59 linked_ptr<ServiceResolver>(NULL))); 60 61 // If there is already a resolver working on this service, don't add one. 62 if (insert_result.second) { 63 scoped_ptr<ServiceResolver> resolver = 64 service_discovery_client_->CreateServiceResolver( 65 service_name, base::Bind( 66 &PrivetDeviceListerImpl::OnResolveComplete, 67 base::Unretained(this), 68 added)); 69 70 insert_result.first->second.reset(resolver.release()); 71 insert_result.first->second->StartResolving(); 72 } 73 } else { 74 delegate_->DeviceRemoved(service_name); 75 } 76} 77 78void PrivetDeviceListerImpl::OnResolveComplete( 79 bool added, 80 ServiceResolver::RequestStatus status, 81 const ServiceDescription& service_description) { 82 if (status != ServiceResolver::STATUS_SUCCESS) { 83 resolvers_.erase(service_description.service_name); 84 85 // TODO(noamsml): Add retry logic. 86 return; 87 } 88 89 DeviceDescription device_description; 90 FillDeviceDescription(service_description, &device_description); 91 92 std::string service_name = service_description.service_name; 93 resolvers_.erase(service_name); 94 delegate_->DeviceChanged(added, service_name, device_description); 95} 96 97void PrivetDeviceListerImpl::FillDeviceDescription( 98 const ServiceDescription& service_description, 99 DeviceDescription* device_description) { 100 device_description->address = service_description.address; 101 device_description->ip_address = service_description.ip_address; 102 device_description->last_seen = service_description.last_seen; 103 104 for (std::vector<std::string>::const_iterator i = 105 service_description.metadata.begin(); 106 i < service_description.metadata.end(); 107 i++) { 108 size_t equals_pos = i->find_first_of('='); 109 if (equals_pos == std::string::npos) 110 continue; // We do not parse non key-value TXT records 111 112 std::string key = i->substr(0, equals_pos); 113 std::string value = i->substr(equals_pos + 1); 114 115 if (LowerCaseEqualsASCII(key, kPrivetTxtKeyName)) { 116 device_description->name = value; 117 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyDescription)) { 118 device_description->description = value; 119 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyURL)) { 120 device_description->url = value; 121 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyType)) { 122 device_description->type = value; 123 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyID)) { 124 device_description->id = value; 125 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyConnectionState)) { 126 device_description->connection_state = ConnectionStateFromString(value); 127 } 128 } 129} 130 131DeviceDescription::ConnectionState 132PrivetDeviceListerImpl::ConnectionStateFromString(const std::string& str) { 133 if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOnline)) { 134 return DeviceDescription::ONLINE; 135 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOffline)) { 136 return DeviceDescription::OFFLINE; 137 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusConnecting)) { 138 return DeviceDescription::CONNECTING; 139 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusNotConfigured)) { 140 return DeviceDescription::NOT_CONFIGURED; 141 } 142 143 return DeviceDescription::UNKNOWN; 144} 145 146} // namespace local_discovery 147