// Copyright 2014 The Chromium OS 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 "peerd/discovered_peer.h" #include #include #include using chromeos::dbus_utils::ExportedObjectManager; using peerd::technologies::TechnologySet; using peerd::technologies::Technology; using std::bitset; using std::string; namespace peerd { DiscoveredPeer::DiscoveredPeer(const scoped_refptr& bus, ExportedObjectManager* object_manager, const dbus::ObjectPath& path, Technology which_technology) : Peer(bus, object_manager, path) { discovered_on_technologies_.set(which_technology); } void DiscoveredPeer::UpdateFromAdvertisement(const base::Time& last_seen, Technology technology) { if (!IsValidUpdateTime(nullptr, last_seen)) { return; } SetLastSeen(nullptr, last_seen); discovered_on_technologies_.set(technology); } void DiscoveredPeer::UpdateService(const std::string& service_id, const Service::IpAddresses& addresses, const Service::ServiceInfo& info, const base::Time& last_seen, Technology technology) { if (!discovered_on_technologies_.test(technology)) { // We're updating a service for a technology, even though we haven't found // this peer on that technology. We could allow this, but lets not until // we know this is valid use case. LOG(WARNING) << "Found service=" << service_id << " on technology=" << technology << " but had not previously found a peer on that service."; return; } // Regardless of what we do with the service update, we have new information // about this peer, so this counts as "seeing it." SetLastSeen(nullptr, last_seen); // Ignore errors. auto service_it = services_.find(service_id); if (service_it != services_.end()) { auto metadata_it = service_metadata_.find(service_id); CHECK(metadata_it != service_metadata_.end()); if (last_seen < metadata_it->second.last_seen) { LOG(WARNING) << "Discarding stale service update."; return; } if (!service_it->second->Update(nullptr, addresses, info, {})) { LOG(WARNING) << "Discarding invalid service update."; return; } metadata_it->second.technology.set(technology); metadata_it->second.last_seen = last_seen; return; } // A new service is discovered! Exposed it over DBus and update our metadata. if (!Peer::AddService(nullptr, service_id, addresses, info, {})) { LOG(WARNING) << "Failed to publish discovered service over DBus."; return; } TechnologySet service_tech; service_tech.set(technology); service_metadata_[service_id] = {std::move(service_tech), last_seen}; } void DiscoveredPeer::RemoveTechnology(Technology technology) { discovered_on_technologies_.reset(technology); auto it = service_metadata_.begin(); while (it != service_metadata_.end()) { it->second.technology.reset(technology); if (it->second.technology.none()) { RemoveService(nullptr, it->first); it = service_metadata_.erase(it); } else { ++it; } } } void DiscoveredPeer::RemoveTechnologyFromService(const std::string& service_id, Technology technology) { auto it = service_metadata_.find(service_id); if (it == service_metadata_.end()) { LOG(WARNING) << "Failed to find service previously discovered over " << "technology=" << technology; return; } it->second.technology.reset(technology); // Remove this service if there are no technologies claiming to see it. if (it->second.technology.none()) { service_metadata_.erase(it); RemoveService(nullptr, service_id); } } size_t DiscoveredPeer::GetTechnologyCount() const { return discovered_on_technologies_.count(); } } // namespace peerd