privet_device_lister_impl.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 CreateServiceWatcher(); 41} 42 43void PrivetDeviceListerImpl::DiscoverNewDevices(bool force_update) { 44 service_watcher_->DiscoverNewServices(force_update); 45} 46 47void PrivetDeviceListerImpl::OnServiceUpdated( 48 ServiceWatcher::UpdateType update, 49 const std::string& service_name) { 50 if (update == ServiceWatcher::UPDATE_INVALIDATED) { 51 resolvers_.clear(); 52 CreateServiceWatcher(); 53 54 delegate_->DeviceCacheFlushed(); 55 return; 56 } 57 58 if (update != ServiceWatcher::UPDATE_REMOVED) { 59 bool added = (update == ServiceWatcher::UPDATE_ADDED); 60 std::pair<ServiceResolverMap::iterator, bool> insert_result = 61 resolvers_.insert(make_pair(service_name, 62 linked_ptr<ServiceResolver>(NULL))); 63 64 // If there is already a resolver working on this service, don't add one. 65 if (insert_result.second) { 66 scoped_ptr<ServiceResolver> resolver = 67 service_discovery_client_->CreateServiceResolver( 68 service_name, base::Bind( 69 &PrivetDeviceListerImpl::OnResolveComplete, 70 base::Unretained(this), 71 added)); 72 73 insert_result.first->second.reset(resolver.release()); 74 insert_result.first->second->StartResolving(); 75 } 76 } else { 77 delegate_->DeviceRemoved(service_name); 78 } 79} 80 81void PrivetDeviceListerImpl::OnResolveComplete( 82 bool added, 83 ServiceResolver::RequestStatus status, 84 const ServiceDescription& service_description) { 85 if (status != ServiceResolver::STATUS_SUCCESS) { 86 resolvers_.erase(service_description.service_name); 87 88 // TODO(noamsml): Add retry logic. 89 return; 90 } 91 92 DeviceDescription device_description; 93 FillDeviceDescription(service_description, &device_description); 94 95 std::string service_name = service_description.service_name; 96 resolvers_.erase(service_name); 97 delegate_->DeviceChanged(added, service_name, device_description); 98} 99 100void PrivetDeviceListerImpl::FillDeviceDescription( 101 const ServiceDescription& service_description, 102 DeviceDescription* device_description) { 103 device_description->address = service_description.address; 104 device_description->ip_address = service_description.ip_address; 105 device_description->last_seen = service_description.last_seen; 106 107 for (std::vector<std::string>::const_iterator i = 108 service_description.metadata.begin(); 109 i < service_description.metadata.end(); 110 i++) { 111 size_t equals_pos = i->find_first_of('='); 112 if (equals_pos == std::string::npos) 113 continue; // We do not parse non key-value TXT records 114 115 std::string key = i->substr(0, equals_pos); 116 std::string value = i->substr(equals_pos + 1); 117 118 if (LowerCaseEqualsASCII(key, kPrivetTxtKeyName)) { 119 device_description->name = value; 120 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyDescription)) { 121 device_description->description = value; 122 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyURL)) { 123 device_description->url = value; 124 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyType)) { 125 device_description->type = value; 126 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyID)) { 127 device_description->id = value; 128 } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyConnectionState)) { 129 device_description->connection_state = ConnectionStateFromString(value); 130 } 131 } 132} 133 134DeviceDescription::ConnectionState 135PrivetDeviceListerImpl::ConnectionStateFromString(const std::string& str) { 136 if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOnline)) { 137 return DeviceDescription::ONLINE; 138 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOffline)) { 139 return DeviceDescription::OFFLINE; 140 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusConnecting)) { 141 return DeviceDescription::CONNECTING; 142 } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusNotConfigured)) { 143 return DeviceDescription::NOT_CONFIGURED; 144 } 145 146 return DeviceDescription::UNKNOWN; 147} 148 149void PrivetDeviceListerImpl::CreateServiceWatcher() { 150 service_watcher_ = 151 service_discovery_client_->CreateServiceWatcher( 152 service_type_, 153 base::Bind(&PrivetDeviceListerImpl::OnServiceUpdated, 154 base::Unretained(this))); 155 service_watcher_->Start(); 156 157} 158 159} // namespace local_discovery 160