blob: 40f0284c79eee30512907da7293683ea8a6a6b06 [file] [log] [blame]
// Copyright 2018 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 <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/macros.h>
#include <base/stl_util.h>
#include "portier/group.h"
#include "portier/status.h"
namespace portier {
// Manages proxy interfaces and proxy groups.
// Proxy groups are logical groupings of interfaces which collectively
// act as a Neighbor Discover proxy node. Interfaces can only be part
// of one group. Destroying a group will remove all member interfaces.
template <class MemberType>
class GroupManager {
using GroupType = Group<MemberType>;
GroupManager() = default;
~GroupManager() = default;
// Proxy groups.
// Creates a new proxy group. Verifies that the name is valid and
// that no group exists with the current name. Store the group
// internally, but can be accessed using a call to `GetGroup()`.
Status CreateGroup(const std::string& pg_name);
// Stops managing a proxy group, removing all members from the group.
Status ReleaseGroup(const std::string& pg_name);
// Releases all proxy groups, removing all members.
void ReleaseAllGroups();
// Checks if a given proxy group exists already.
bool HasGroup(const std::string& pg_name) const;
// Get a pointer to the group.
GroupType* GetGroup(const std::string& pg_name) const;
// Get a list of the existing proxy groups.
std::vector<std::string> GetGroupNames() const;
// Gets the list of proxy groups.
std::vector<GroupType*> GetGroups() const;
using NameGroupPair =
std::pair<const std::string, std::unique_ptr<GroupType>>;
using Code = Status::Code;
// A mapping of group names to a list of their members.
std::map<std::string, std::unique_ptr<GroupType>> proxy_groups_;
// Template implementation.
template <class MemberType>
Status GroupManager<MemberType>::CreateGroup(const std::string& pg_name) {
if (HasGroup(pg_name)) {
return Status(Code::ALREADY_EXISTS)
<< "A proxy group named " << pg_name << " already exists";
auto pg_ptr = GroupType::Create(pg_name);
// Only cause of failure is having an invalid name.
if (!pg_ptr) {
return Status(Code::INVALID_ARGUMENT)
<< "Invalid proxy group name " << pg_name;
proxy_groups_.insert(NameGroupPair(pg_name, std::move(pg_ptr)));
return Status();
template <class MemberType>
Status GroupManager<MemberType>::ReleaseGroup(const std::string& pg_name) {
auto it = proxy_groups_.find(pg_name);
if (it == proxy_groups_.end()) {
return Status(Code::DOES_NOT_EXIST)
<< "The proxy group " << pg_name << " does not exist";
return Status();
template <class MemberType>
void GroupManager<MemberType>::ReleaseAllGroups() {
auto pg_names = GetGroupNames();
for (const auto& pg_name : pg_names) {
template <class MemberType>
bool GroupManager<MemberType>::HasGroup(const std::string& pg_name) const {
return base::ContainsKey(proxy_groups_, pg_name);
template <class MemberType>
Group<MemberType>* GroupManager<MemberType>::GetGroup(
const std::string& pg_name) const {
const auto it = proxy_groups_.find(pg_name);
if (it == proxy_groups_.end()) {
return nullptr;
return it->second.get();
template <class MemberType>
std::vector<std::string> GroupManager<MemberType>::GetGroupNames() const {
std::vector<std::string> pg_names;
for (const NameGroupPair& pair : proxy_groups_) {
return pg_names;
template <class MemberType>
std::vector<Group<MemberType>*> GroupManager<MemberType>::GetGroups() const {
std::vector<GroupType*> groups;
for (const NameGroupPair& pair : proxy_groups_) {
return groups;
} // namespace portier