security: Change the ownership model of Pib and its related entities
Change-Id: I6816a0fd5c7af490f7e98db196e0214219f4b05c
Refs: #3349
diff --git a/src/security/pib/certificate-container.cpp b/src/security/pib/certificate-container.cpp
index fa8d058..e68b0cc 100644
--- a/src/security/pib/certificate-container.cpp
+++ b/src/security/pib/certificate-container.cpp
@@ -21,22 +21,31 @@
#include "certificate-container.hpp"
#include "pib-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
+NDN_CXX_ASSERT_FORWARD_ITERATOR(CertificateContainer::const_iterator);
+
+CertificateContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
CertificateContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
+ const CertificateContainer& container)
: m_it(it)
- , m_impl(impl)
+ , m_container(&container)
{
}
v2::Certificate
CertificateContainer::const_iterator::operator*()
{
- return m_impl->getCertificate(*m_it);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
CertificateContainer::const_iterator&
@@ -49,50 +58,52 @@
CertificateContainer::const_iterator
CertificateContainer::const_iterator::operator++(int)
{
- const_iterator it(m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ const_iterator it(m_it, *m_container);
++m_it;
return it;
}
bool
-CertificateContainer::const_iterator::operator==(const const_iterator& other)
+CertificateContainer::const_iterator::operator==(const const_iterator& other) const
{
- return (m_impl == other.m_impl && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_certNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_certNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_impl == other.m_container->m_impl && m_it == other.m_it);
}
bool
-CertificateContainer::const_iterator::operator!=(const const_iterator& other)
+CertificateContainer::const_iterator::operator!=(const const_iterator& other) const
{
return !(*this == other);
}
-CertificateContainer::CertificateContainer()
-{
-}
-
-CertificateContainer::CertificateContainer(std::set<Name>&& certNames,
- shared_ptr<PibImpl> impl)
- : m_certNames(certNames)
+CertificateContainer::CertificateContainer(const Name& keyName, shared_ptr<PibImpl> impl)
+ : m_keyName(keyName)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
+ m_certNames = impl->getCertificatesOfKey(keyName);
}
CertificateContainer::const_iterator
CertificateContainer::begin() const
{
- return const_iterator(m_certNames.begin(), m_impl);
+ return const_iterator(m_certNames.begin(), *this);
}
CertificateContainer::const_iterator
CertificateContainer::end() const
{
- return const_iterator(m_certNames.end(), m_impl);
+ return const_iterator();
}
CertificateContainer::const_iterator
CertificateContainer::find(const Name& certName) const
{
- return const_iterator(m_certNames.find(certName), m_impl);
+ return const_iterator(m_certNames.find(certName), *this);
}
size_t
@@ -101,6 +112,57 @@
return m_certNames.size();
}
+void
+CertificateContainer::add(const v2::Certificate& certificate)
+{
+ if (m_keyName != certificate.getKeyName())
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certificate.getKeyName().toUri() + "` "
+ "does not match key name"));
+
+ const Name& certName = certificate.getName();
+ m_certNames.insert(certName);
+ m_certs[certName] = certificate;
+ m_impl->addCertificate(certificate);
+}
+
+void
+CertificateContainer::remove(const Name& certName)
+{
+ if (!v2::Certificate::isValidName(certName) ||
+ v2::extractKeyNameFromCertName(certName) != m_keyName) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certName.toUri() + "` "
+ "is invalid or does not match key name"));
+ }
+
+ m_certNames.erase(certName);
+ m_certs.erase(certName);
+ m_impl->removeCertificate(certName);
+}
+
+v2::Certificate
+CertificateContainer::get(const Name& certName) const
+{
+ auto it = m_certs.find(certName);
+
+ if (it != m_certs.end())
+ return it->second;
+
+ if (!v2::Certificate::isValidName(certName) ||
+ v2::extractKeyNameFromCertName(certName) != m_keyName) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate name `" + certName.toUri() + "` "
+ "is invalid or does not match key name"));
+ }
+
+ m_certs[certName] = m_impl->getCertificate(certName);
+ return m_certs[certName];
+}
+
+bool
+CertificateContainer::isConsistent() const
+{
+ return m_certNames == m_impl->getCertificatesOfKey(m_keyName);
+}
+
} // namespace pib
} // namespace security
} // namespace ndn
diff --git a/src/security/pib/certificate-container.hpp b/src/security/pib/certificate-container.hpp
index eba765e..42e9534 100644
--- a/src/security/pib/certificate-container.hpp
+++ b/src/security/pib/certificate-container.hpp
@@ -23,6 +23,7 @@
#define NDN_SECURITY_PIB_CERTIFICATE_CONTAINER_HPP
#include <set>
+#include <unordered_map>
#include "../v2/certificate.hpp"
namespace ndn {
@@ -31,16 +32,24 @@
class PibImpl;
-/// @brief A handler to search or enumerate certificates of a key.
-class CertificateContainer
+namespace detail {
+class KeyImpl;
+} // namespace detail
+
+/**
+ * @brief Container of certificates of a key
+ *
+ * The container is used to search/enumerate certificates of a key.
+ * The container can be created only by detail::KeyImpl.
+ */
+class CertificateContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const v2::Certificate>
{
public:
- friend class CertificateContainer;
+ const_iterator();
- public:
v2::Certificate
operator*();
@@ -51,26 +60,24 @@
operator++(int);
bool
- operator==(const const_iterator& other);
+ operator==(const const_iterator& other) const;
bool
- operator!=(const const_iterator& other);
+ operator!=(const const_iterator& other) const;
private:
- const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const CertificateContainer& container);
private:
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const CertificateContainer* m_container;
+
+ friend class CertificateContainer;
};
typedef const_iterator iterator;
public:
- CertificateContainer();
-
- CertificateContainer(std::set<Name>&& certNames, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -83,9 +90,64 @@
size_t
size() const;
+ /**
+ * @brief Add @p certificate into the container
+ * @throw std::invalid_argument the name of @p certificate does not match the key name
+ */
+ void
+ add(const v2::Certificate& certificate);
+
+ /**
+ * @brief Remove a certificate with @p certName from the container
+ * @throw std::invalid_argument @p certName does not match the key name
+ */
+ void
+ remove(const Name& certName);
+
+ /**
+ * @brief Get a certificate with @p certName from the container
+ * @throw std::invalid_argument @p certName does not match the key name
+ * @throw Pib::Error the certificate does not exist
+ */
+ v2::Certificate
+ get(const Name& certName) const;
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create certificate container for a key with @p keyName
+ * @param impl The PIB backend implementation.
+ */
+ CertificateContainer(const Name& keyName, shared_ptr<PibImpl> impl);
+
+ const std::set<Name>&
+ getCertNames() const
+ {
+ return m_certNames;
+ }
+
+ const std::unordered_map<Name, v2::Certificate>&
+ getCache() const
+ {
+ return m_certs;
+ }
+
private:
+ Name m_keyName;
std::set<Name> m_certNames;
+ /// @brief Cache of loaded certificates
+ mutable std::unordered_map<Name, v2::Certificate> m_certs;
+
shared_ptr<PibImpl> m_impl;
+
+ friend class detail::KeyImpl;
};
} // namespace pib
diff --git a/src/security/pib/detail/identity-impl.cpp b/src/security/pib/detail/identity-impl.cpp
new file mode 100644
index 0000000..af01dc5
--- /dev/null
+++ b/src/security/pib/detail/identity-impl.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "identity-impl.hpp"
+#include "../pib-impl.hpp"
+#include "../pib.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+
+IdentityImpl::IdentityImpl(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
+ : m_name(identityName)
+ , m_isDefaultKeyLoaded(false)
+ , m_keys(identityName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ if (needInit) {
+ m_impl->addIdentity(m_name);
+ }
+ else if (!m_impl->hasIdentity(m_name)) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Identity " + m_name.toUri() + " does not exist"));
+ }
+}
+
+Key
+IdentityImpl::addKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (m_keys.find(keyName) != m_keys.end()) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing key " + keyName.toUri()));
+ }
+
+ return m_keys.add(key, keyLen, keyName);
+}
+
+void
+IdentityImpl::removeKey(const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (m_isDefaultKeyLoaded && m_defaultKey.getName() == keyName)
+ m_isDefaultKeyLoaded = false;
+
+ m_keys.remove(keyName);
+}
+
+Key
+IdentityImpl::getKey(const Name& keyName) const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ return m_keys.get(keyName);
+}
+
+const KeyContainer&
+IdentityImpl::getKeys() const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ return m_keys;
+}
+
+const Key&
+IdentityImpl::setDefaultKey(const Name& keyName)
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ m_defaultKey = m_keys.get(keyName);
+ m_isDefaultKeyLoaded = true;
+ m_impl->setDefaultKeyOfIdentity(m_name, keyName);
+ return m_defaultKey;
+}
+
+const Key&
+IdentityImpl::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ addKey(key, keyLen, keyName);
+ return setDefaultKey(keyName);
+}
+
+const Key&
+IdentityImpl::getDefaultKey() const
+{
+ BOOST_ASSERT(m_keys.isConsistent());
+
+ if (!m_isDefaultKeyLoaded) {
+ m_defaultKey = m_keys.get(m_impl->getDefaultKeyOfIdentity(m_name));
+ m_isDefaultKeyLoaded = true;
+ }
+
+ BOOST_ASSERT(m_impl->getDefaultKeyOfIdentity(m_name) == m_defaultKey.getName());
+
+ return m_defaultKey;
+}
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/detail/identity-impl.hpp b/src/security/pib/detail/identity-impl.hpp
new file mode 100644
index 0000000..b654348
--- /dev/null
+++ b/src/security/pib/detail/identity-impl.hpp
@@ -0,0 +1,138 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
+#define NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
+
+#include "../key-container.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+
+class PibImpl;
+
+namespace detail {
+
+/**
+ * @brief Backend instance of Identity
+ *
+ * An Identity has only one backend instance, but may have multiple frontend handles.
+ * Each frontend handle is associated with the only one backend IdentityImpl.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class IdentityImpl : noncopyable
+{
+public:
+ /**
+ * @brief Create an Identity with @p identityName.
+ *
+ * @param identityName The name of the Identity.
+ * @param impl The PIB backend implementation.
+ * @param needInit If true, create the identity in backend when the identity does not exist.
+ * Otherwise, throw Pib::Error when the identity does not exist.
+ */
+ IdentityImpl(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);
+
+ /// @brief Get the name of the identity.
+ const Name&
+ getName() const
+ {
+ return m_name;
+ }
+
+ /**
+ * @brief Add a @p key of @p keyLen bytes with @p keyName (in PKCS#8 format).
+ *
+ * If no default key is set before, the new key will be set as the default key of the identity.
+ *
+ * @return the added key.
+ * @throw std::invalid_argument key name does not match identity
+ * @throw Pib::Error a key with the same name already exists
+ */
+ Key
+ addKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Remove a key with @p keyName
+ * @throw std::invalid_argument @p keyName does not match identity
+ */
+ void
+ removeKey(const Name& keyName);
+
+ /**
+ * @brief Get a key with id @p keyName.
+ *
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
+ */
+ Key
+ getKey(const Name& keyName) const;
+
+ /**
+ * @brief Get all keys for this Identity.
+ */
+ const KeyContainer&
+ getKeys() const;
+
+ /**
+ * @brief Set the key with id @p keyName.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
+ * @return The default key
+ */
+ const Key&
+ setDefaultKey(const Name& keyName);
+
+ /**
+ * @brief Add @p key of @p keyLen bytes with @p keyName and set it as the default key
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key with the same name already exists
+ * @return the default key
+ */
+ const Key&
+ setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Get the default key for this Identity.
+ * @throw Pib::Error the default key does not exist.
+ */
+ const Key&
+ getDefaultKey() const;
+
+private:
+ Name m_name;
+
+ mutable bool m_isDefaultKeyLoaded;
+ mutable Key m_defaultKey;
+
+ mutable KeyContainer m_keys;
+
+ shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_DETAIL_IDENTITY_IMPL_HPP
diff --git a/src/security/pib/detail/key-impl.cpp b/src/security/pib/detail/key-impl.cpp
new file mode 100644
index 0000000..35a0de6
--- /dev/null
+++ b/src/security/pib/detail/key-impl.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "key-impl.hpp"
+#include "../pib-impl.hpp"
+#include "../pib.hpp"
+#include "../../transform/public-key.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+namespace detail {
+
+KeyImpl::KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl)
+ : m_identity(v2::extractIdentityFromKeyName(keyName))
+ , m_keyName(keyName)
+ , m_key(key, keyLen)
+ , m_isDefaultCertificateLoaded(false)
+ , m_certificates(keyName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ if (m_impl->hasKey(m_keyName)) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing key " + m_keyName.toUri()));
+ }
+
+ transform::PublicKey publicKey;
+ try {
+ publicKey.loadPkcs8(key, keyLen);
+ }
+ catch (transform::PublicKey::Error&) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid key bits"));
+ }
+ m_keyType = publicKey.getKeyType();
+
+ m_impl->addKey(m_identity, m_keyName, key, keyLen);
+}
+
+KeyImpl::KeyImpl(const Name& keyName, shared_ptr<PibImpl> impl)
+ : m_identity(v2::extractIdentityFromKeyName(keyName))
+ , m_keyName(keyName)
+ , m_isDefaultCertificateLoaded(false)
+ , m_certificates(keyName, impl)
+ , m_impl(impl)
+{
+ BOOST_ASSERT(impl != nullptr);
+
+ m_key = m_impl->getKeyBits(m_keyName);
+
+ transform::PublicKey key;
+ key.loadPkcs8(m_key.buf(), m_key.size());
+ m_keyType = key.getKeyType();
+}
+
+void
+KeyImpl::addCertificate(const v2::Certificate& certificate)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (m_certificates.find(certificate.getName()) != m_certificates.end()) {
+ BOOST_THROW_EXCEPTION(Pib::Error("Cannot overwrite existing certificate " + certificate.getName().toUri()));
+ }
+
+ m_certificates.add(certificate);
+}
+
+void
+KeyImpl::removeCertificate(const Name& certName)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (m_isDefaultCertificateLoaded && m_defaultCertificate.getName() == certName)
+ m_isDefaultCertificateLoaded = false;
+
+ m_certificates.remove(certName);
+}
+
+v2::Certificate
+KeyImpl::getCertificate(const Name& certName) const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ return m_certificates.get(certName);
+}
+
+const CertificateContainer&
+KeyImpl::getCertificates() const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ return m_certificates;
+}
+
+const v2::Certificate&
+KeyImpl::setDefaultCertificate(const Name& certName)
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ m_defaultCertificate = m_certificates.get(certName);
+ m_impl->setDefaultCertificateOfKey(m_keyName, certName);
+ m_isDefaultCertificateLoaded = true;
+ return m_defaultCertificate;
+}
+
+const v2::Certificate&
+KeyImpl::setDefaultCertificate(const v2::Certificate& certificate)
+{
+ addCertificate(certificate);
+ return setDefaultCertificate(certificate.getName());
+}
+
+const v2::Certificate&
+KeyImpl::getDefaultCertificate() const
+{
+ BOOST_ASSERT(m_certificates.isConsistent());
+
+ if (!m_isDefaultCertificateLoaded) {
+ m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_keyName);
+ m_isDefaultCertificateLoaded = true;
+ }
+
+ BOOST_ASSERT(m_impl->getDefaultCertificateOfKey(m_keyName).wireEncode() == m_defaultCertificate.wireEncode());
+
+ return m_defaultCertificate;
+}
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
diff --git a/src/security/pib/detail/key-impl.hpp b/src/security/pib/detail/key-impl.hpp
new file mode 100644
index 0000000..c05e77e
--- /dev/null
+++ b/src/security/pib/detail/key-impl.hpp
@@ -0,0 +1,179 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
+#define NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
+
+#include "../../../data.hpp"
+#include "../certificate-container.hpp"
+#include "../../security-common.hpp"
+
+namespace ndn {
+namespace security {
+namespace pib {
+
+class PibImpl;
+
+namespace detail {
+
+/**
+ * @brief Backend instance of Key
+ *
+ * An Key has only one backend instance, but may have multiple frontend handles.
+ * Each frontend handle is associated with the only one backend KeyImpl.
+ *
+ * @throw PibImpl::Error when underlying implementation has non-semantic error.
+ */
+class KeyImpl : noncopyable
+{
+public:
+ /**
+ * @brief Create a KeyImpl with @p keyName.
+ *
+ * If the key does not exist in the backend, create it in backend.
+ *
+ * @param keyName The name of the key.
+ * @param key The public key to add.
+ * @param keyLen The length of the key.
+ * @param impl The Pib backend implementation.
+ * @throw Pib::Error a key with the same @p keyName already exists.
+ */
+ KeyImpl(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl);
+
+ /**
+ * @brief Create a KeyImpl with @p keyName.
+ *
+ * @param keyName The name of the key.
+ * @param impl The Pib backend implementation.
+ * @throw Pib::Error the key does not exist.
+ */
+ KeyImpl(const Name& keyName, shared_ptr<PibImpl> impl);
+
+ /// @brief Get the name of the key.
+ const Name&
+ getName() const
+ {
+ return m_keyName;
+ }
+
+ /**
+ * @brief Get the name of the belonging identity.
+ */
+ const Name&
+ getIdentity() const
+ {
+ return m_identity;
+ }
+
+ /**
+ * @brief Get key type
+ */
+ KeyType
+ getKeyType() const
+ {
+ return m_keyType;
+ }
+
+ /**
+ * @brief Get public key bits
+ */
+ const Buffer&
+ getPublicKey() const
+ {
+ return m_key;
+ }
+
+ /**
+ * @brief Add @p certificate.
+ *
+ * If no default certificate is set before, the new certificate will be set as the default
+ * certificate of the key.
+ *
+ * @throw std::invalid_argument certificate name does not match key name
+ * @throw Pib::Error a certificate with the same name already exists
+ */
+ void
+ addCertificate(const v2::Certificate& certificate);
+
+ /**
+ * @brief Remove a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ */
+ void
+ removeCertificate(const Name& certName);
+
+ /**
+ * @brief Get a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
+ */
+ v2::Certificate
+ getCertificate(const Name& certName) const;
+
+ /// @brief Get all the certificates for this key.
+ const CertificateContainer&
+ getCertificates() const;
+
+ /**
+ * @brief Set an existing one with @p certName as the default certificate
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
+ * @return the default certificate
+ */
+ const v2::Certificate&
+ setDefaultCertificate(const Name& certName);
+
+ /**
+ * @brief Add @p certificate and set it as the default certificate of the key
+ * @throw std::invalid_argument @p certificate does not match key name
+ * @throw Pib::Error the certificate with the same name already exists.
+ * @return the default certificate
+ */
+ const v2::Certificate&
+ setDefaultCertificate(const v2::Certificate& certificate);
+
+ /**
+ * @brief Get the default certificate for this Key.
+ * @throw Pib::Error the default certificate does not exist.
+ */
+ const v2::Certificate&
+ getDefaultCertificate() const;
+
+private:
+ Name m_identity;
+ Name m_keyName;
+ Buffer m_key;
+ KeyType m_keyType;
+
+ mutable bool m_isDefaultCertificateLoaded;
+ mutable v2::Certificate m_defaultCertificate;
+
+ CertificateContainer m_certificates;
+
+ shared_ptr<PibImpl> m_impl;
+};
+
+} // namespace detail
+} // namespace pib
+} // namespace security
+} // namespace ndn
+
+#endif // NDN_SECURITY_PIB_DETAIL_KEY_IMPL_HPP
diff --git a/src/security/pib/identity-container.cpp b/src/security/pib/identity-container.cpp
index 77076af..7c018ce 100644
--- a/src/security/pib/identity-container.cpp
+++ b/src/security/pib/identity-container.cpp
@@ -21,22 +21,32 @@
#include "identity-container.hpp"
#include "pib-impl.hpp"
+#include "detail/identity-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
+NDN_CXX_ASSERT_FORWARD_ITERATOR(IdentityContainer::const_iterator);
+
+IdentityContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
IdentityContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
+ const IdentityContainer& container)
: m_it(it)
- , m_impl(impl)
+ , m_container(&container)
{
}
Identity
IdentityContainer::const_iterator::operator*()
{
- return Identity(*m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
IdentityContainer::const_iterator&
@@ -57,7 +67,11 @@
bool
IdentityContainer::const_iterator::operator==(const const_iterator& other)
{
- return (m_impl == other.m_impl && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_identityNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_identityNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_pibImpl == other.m_container->m_pibImpl && m_it == other.m_it);
}
bool
@@ -66,39 +80,83 @@
return !(*this == other);
}
-IdentityContainer::IdentityContainer()
+IdentityContainer::IdentityContainer(shared_ptr<PibImpl> pibImpl)
+ : m_pibImpl(pibImpl)
{
-}
-
-IdentityContainer::IdentityContainer(std::set<Name>&& identities,
- shared_ptr<PibImpl> impl)
- : m_identities(identities)
- , m_impl(impl)
-{
+ BOOST_ASSERT(pibImpl != nullptr);
+ m_identityNames = pibImpl->getIdentities();
}
IdentityContainer::const_iterator
IdentityContainer::begin() const
{
- return const_iterator(m_identities.begin(), m_impl);
+ return const_iterator(m_identityNames.begin(), *this);
}
IdentityContainer::const_iterator
IdentityContainer::end() const
{
- return const_iterator(m_identities.end(), m_impl);
+ return const_iterator();
}
IdentityContainer::const_iterator
IdentityContainer::find(const Name& identity) const
{
- return const_iterator(m_identities.find(identity), m_impl);
+ return const_iterator(m_identityNames.find(identity), *this);
}
size_t
IdentityContainer::size() const
{
- return m_identities.size();
+ return m_identityNames.size();
+}
+
+Identity
+IdentityContainer::add(const Name& identityName)
+{
+ if (m_identityNames.count(identityName) == 0) {
+ m_identityNames.insert(identityName);
+ m_identities[identityName] =
+ shared_ptr<detail::IdentityImpl>(new detail::IdentityImpl(identityName, m_pibImpl, true));
+ }
+ return get(identityName);
+}
+
+void
+IdentityContainer::remove(const Name& identityName)
+{
+ m_identityNames.erase(identityName);
+ m_identities.erase(identityName);
+ m_pibImpl->removeIdentity(identityName);
+}
+
+Identity
+IdentityContainer::get(const Name& identityName) const
+{
+ shared_ptr<detail::IdentityImpl> id;
+ auto it = m_identities.find(identityName);
+
+ if (it != m_identities.end()) {
+ id = it->second;
+ }
+ else {
+ id = shared_ptr<detail::IdentityImpl>(new detail::IdentityImpl(identityName, m_pibImpl, false));
+ m_identities[identityName] = id;
+ }
+ return Identity(id);
+}
+
+void
+IdentityContainer::reset()
+{
+ m_identities.clear();
+ m_identityNames = m_pibImpl->getIdentities();
+}
+
+bool
+IdentityContainer::isConsistent() const
+{
+ return m_identityNames == m_pibImpl->getIdentities();
}
} // namespace pib
diff --git a/src/security/pib/identity-container.hpp b/src/security/pib/identity-container.hpp
index 1ac30e1..94cd370 100644
--- a/src/security/pib/identity-container.hpp
+++ b/src/security/pib/identity-container.hpp
@@ -22,25 +22,35 @@
#ifndef NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
#define NDN_SECURITY_PIB_IDENTITY_CONTAINER_HPP
-#include <set>
#include "identity.hpp"
+#include <set>
+#include <unordered_map>
+
namespace ndn {
namespace security {
namespace pib {
class PibImpl;
-/// @brief A handler to search or enumerate identities in PIB.
-class IdentityContainer
+namespace detail {
+class IdentityImpl;
+} // namespace detail
+
+/**
+ * @brief Container of identities of a Pib
+ *
+ * The container is used to search/enumerate identities of a Pib.
+ * The container can be created only by Pib.
+ */
+class IdentityContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const Identity>
{
public:
- friend class IdentityContainer;
+ const_iterator();
- public:
Identity
operator*();
@@ -57,21 +67,18 @@
operator!=(const const_iterator& other);
private:
- const_iterator(std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const IdentityContainer& container);
private:
- Name m_identity;
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const IdentityContainer* m_container;
+
+ friend class IdentityContainer;
};
typedef const_iterator iterator;
public:
- IdentityContainer();
-
- IdentityContainer(std::set<Name>&& identities, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -84,9 +91,69 @@
size_t
size() const;
+ /**
+ * @brief Add @p identity into the container
+ */
+ Identity
+ add(const Name& identityName);
+
+ /**
+ * @brief Remove @p identity from the container
+ */
+ void
+ remove(const Name& identity);
+
+ /**
+ * @brief Get @p identity from the container
+ * @throw Pib::Error @p identity does not exist
+ */
+ Identity
+ get(const Name& identity) const;
+
+ /**
+ * @brief Reset state of the container
+ *
+ * This method removes all loaded identities and retrieves identity names from the PIB
+ * implementation.
+ */
+ void
+ reset();
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create identity container
+ * @param impl The PIB backend implementation.
+ */
+ explicit
+ IdentityContainer(shared_ptr<PibImpl> pibImpl);
+
+ const std::set<Name>&
+ getIdentityNames() const
+ {
+ return m_identityNames;
+ }
+
+ const std::unordered_map<Name, shared_ptr<detail::IdentityImpl>>&
+ getLoadedIdentities() const
+ {
+ return m_identities;
+ }
+
private:
- std::set<Name> m_identities;
- shared_ptr<PibImpl> m_impl;
+ std::set<Name> m_identityNames;
+ /// @brief Cache of loaded detail::IdentityImpl.
+ mutable std::unordered_map<Name, shared_ptr<detail::IdentityImpl>> m_identities;
+
+ shared_ptr<PibImpl> m_pibImpl;
+ friend class Pib;
};
} // namespace pib
diff --git a/src/security/pib/identity.cpp b/src/security/pib/identity.cpp
index 11cad88..4797cb6 100644
--- a/src/security/pib/identity.cpp
+++ b/src/security/pib/identity.cpp
@@ -20,123 +20,65 @@
*/
#include "identity.hpp"
-#include "pib-impl.hpp"
-#include "pib.hpp"
+#include "detail/identity-impl.hpp"
namespace ndn {
namespace security {
namespace pib {
-Identity::Identity()
- : m_hasDefaultKey(false)
- , m_needRefreshKeys(false)
- , m_impl(nullptr)
-{
-}
+Identity::Identity() = default;
-Identity::Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit)
- : m_name(identityName)
- , m_hasDefaultKey(false)
- , m_needRefreshKeys(true)
- , m_impl(impl)
+Identity::Identity(weak_ptr<detail::IdentityImpl> impl)
+ : m_impl(impl)
{
- validityCheck();
-
- if (needInit)
- m_impl->addIdentity(m_name);
- else if (!m_impl->hasIdentity(m_name))
- BOOST_THROW_EXCEPTION(Pib::Error("Identity: " + m_name.toUri() + " does not exist"));
}
const Name&
Identity::getName() const
{
- return m_name;
+ return lock()->getName();
}
Key
Identity::addKey(const uint8_t* key, size_t keyLen, const Name& keyName)
{
- if (m_name != v2::extractIdentityFromKeyName(keyName)) {
- BOOST_THROW_EXCEPTION(Pib::Error("Key name `" + keyName.toUri() + "` does not match identity "
- "`" + m_name.toUri() + "`"));
- }
-
- // if we have already loaded all the keys, but the new key is not one of them the
- // KeyContainer should be refreshed
- m_needRefreshKeys = m_needRefreshKeys || m_keys.find(keyName) == m_keys.end();
-
- return Key(keyName, key, keyLen, m_impl);
+ return lock()->addKey(key, keyLen, keyName);
}
void
Identity::removeKey(const Name& keyName)
{
- if (m_name != v2::extractIdentityFromKeyName(keyName)) {
- BOOST_THROW_EXCEPTION(Pib::Error("Key name `" + keyName.toUri() + "` does not match identity "
- "`" + m_name.toUri() + "`"));
- }
-
- validityCheck();
-
- if (m_hasDefaultKey && m_defaultKey.getName() == keyName)
- m_hasDefaultKey = false;
-
- m_impl->removeKey(keyName);
- m_needRefreshKeys = true;
+ return lock()->removeKey(keyName);
}
Key
Identity::getKey(const Name& keyName) const
{
- return Key(keyName, m_impl);
+ return lock()->getKey(keyName);
}
const KeyContainer&
Identity::getKeys() const
{
- validityCheck();
-
- if (m_needRefreshKeys) {
- m_keys = KeyContainer(m_name, m_impl->getKeysOfIdentity(m_name), m_impl);
- m_needRefreshKeys = false;
- }
-
- return m_keys;
+ return lock()->getKeys();
}
-Key&
+const Key&
Identity::setDefaultKey(const Name& keyName)
{
- validityCheck();
-
- m_defaultKey = Key(keyName, m_impl);
- m_hasDefaultKey = true;
-
- m_impl->setDefaultKeyOfIdentity(m_name, keyName);
- return m_defaultKey;
+ return lock()->setDefaultKey(keyName);
}
-Key&
+const Key&
Identity::setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName)
{
- validityCheck();
-
- addKey(key, keyLen, keyName);
- return setDefaultKey(keyName);
+ return lock()->setDefaultKey(key, keyLen, keyName);
}
-Key&
+const Key&
Identity::getDefaultKey() const
{
- validityCheck();
-
- if (!m_hasDefaultKey) {
- m_defaultKey = Key(m_impl->getDefaultKeyOfIdentity(m_name), m_impl);
- m_hasDefaultKey = true;
- }
-
- return m_defaultKey;
+ return lock()->getDefaultKey();
}
Identity::operator bool() const
@@ -147,15 +89,18 @@
bool
Identity::operator!() const
{
- return (m_impl == nullptr);
+ return m_impl.expired();
}
-void
-Identity::validityCheck() const
+shared_ptr<detail::IdentityImpl>
+Identity::lock() const
{
- if (m_impl == nullptr) {
- BOOST_THROW_EXCEPTION(std::domain_error("Invalid identity instance"));
- }
+ auto impl = m_impl.lock();
+
+ if (impl == nullptr)
+ BOOST_THROW_EXCEPTION(std::domain_error("Invalid Identity instance"));
+
+ return impl;
}
} // namespace pib
diff --git a/src/security/pib/identity.hpp b/src/security/pib/identity.hpp
index 0a6ca60..3d0117d 100644
--- a/src/security/pib/identity.hpp
+++ b/src/security/pib/identity.hpp
@@ -28,14 +28,16 @@
namespace security {
namespace pib {
+namespace detail {
+class IdentityImpl;
+} // namespace detail
+
/**
- * @brief represents an identity
+ * @brief A frontend handle of an Identity
*
* Identity is at the top level in PIB's Identity-Key-Certificate hierarchy. An identity has a
* Name, and contains zero or more keys, at most one of which is set as the default key of this
* identity. Properties of a key can be accessed after obtaining a Key object.
- *
- * @throw Pib::Error when underlying implementation has non-semantic error.
*/
class Identity
{
@@ -44,7 +46,7 @@
* @brief Default Constructor
*
* Identity created using this default constructor is just a place holder.
- * It must obtain an actual instance from Pib::getIdentity(...). A typical
+ * It can obtain an actual instance from Pib::getIdentity(...). A typical
* usage would be for exception handling:
*
* Identity id;
@@ -61,105 +63,97 @@
Identity();
/**
- * @brief Create an Identity with @p identityName.
+ * @brief Create an Identity with a backend implementation @p impl.
*
- * @param identityName The name of the Identity.
- * @param impl The backend implementation.
- * @param needInit If true, create the identity in backend when the identity does not exist.
- * Otherwise, throw Pib::Error when the identity does not exist.
+ * This method should only be used by IdentityContainer.
*/
- Identity(const Name& identityName, shared_ptr<PibImpl> impl, bool needInit = false);
+ explicit
+ Identity(weak_ptr<detail::IdentityImpl> impl);
- /// @brief Get the name of the identity.
+ /**
+ * @brief Get the name of the identity.
+ */
const Name&
getName() const;
/**
- * @brief Get a key with @p keyName.
- * @throw Pib::Error if the key does not exist.
+ * @brief Get a key with id @p keyName.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
*/
Key
getKey(const Name& keyName) const;
- /// @brief Get all the keys for this Identity.
+ /**
+ * @brief Get all keys for this identity.
+ */
const KeyContainer&
getKeys() const;
/**
* @brief Get the default key for this Identity.
- *
- * @throws Pib::Error if the default key does not exist.
+ * @throw Pib::Error the default key does not exist.
*/
- Key&
+ const Key&
getDefaultKey() const;
- /// @brief Check if the Identity instance is valid
+ /*
+ * @return True if the identity instance is valid
+ */
operator bool() const;
- /// @brief Check if the Identity instance is invalid
+ /**
+ * @return True if the identity instance is invalid
+ */
bool
operator!() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/**
- * @brief Add a @p key (in PKCS#8 format) with @p keyName.
- *
- * If the key already exists, do nothing.
- *
- * If no default key is set before, the new key will be set as the default key of the identity.
- *
- * @return the added key or existing key with the same key id.
+ * @brief Add a @p key of @p keyLen bytes (in PKCS#8 format) with @p keyName.
+ * @return the handle of added key
+ * @throw std::invalid_argument key name does not match identity
+ * @throw Pib::Error a key with the same name already exists
*/
Key
addKey(const uint8_t* key, size_t keyLen, const Name& keyName);
/**
* @brief Remove a key with @p keyName
+ * @throw std::invalid_argument @p keyName does not match identity
*/
void
removeKey(const Name& keyName);
/**
- * @brief Set the key with id @p keyName.
- *
+ * @brief Set an existing key with @p keyName as the default key.
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key does not exist.
* @return The default key
- * @throws Pib::Error if the key does not exist.
*/
- Key&
+ const Key&
setDefaultKey(const Name& keyName);
/**
- * @brief Set the default key with @p keyName (in PKCS#8 format).
- *
- * If the key does not exist, add the key and set it as the default of the Identity.
- * If the key exists, simply set it as the default key of the Identity.
- *
- * @param key The public key to add.
- * @param keyLen The length of the key.
+ * @brief Add a @p key of @p keyLen bytes with @p keyName and set it as the default key
+ * @throw std::invalid_argument @p keyName does not match identity
+ * @throw Pib::Error the key with the same name already exists.
* @return the default key
*/
- Key&
+ const Key&
setDefaultKey(const uint8_t* key, size_t keyLen, const Name& keyName);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+private:
/**
- * @brief Check the validity of this instance
- *
- * @throws std::domain_error if the instance is invalid
+ * @brief Check the validity of the instance
+ * @return a shared_ptr when the instance is valid
+ * @throw std::domain_error the instance is invalid
*/
- void
- validityCheck() const;
+ shared_ptr<detail::IdentityImpl>
+ lock() const;
private:
- Name m_name;
-
- mutable bool m_hasDefaultKey;
- mutable Key m_defaultKey;
-
- mutable bool m_needRefreshKeys;
- mutable KeyContainer m_keys;
-
- shared_ptr<PibImpl> m_impl;
+ weak_ptr<detail::IdentityImpl> m_impl;
};
} // namespace pib
diff --git a/src/security/pib/key-container.cpp b/src/security/pib/key-container.cpp
index 7653955..34f96d0 100644
--- a/src/security/pib/key-container.cpp
+++ b/src/security/pib/key-container.cpp
@@ -21,24 +21,32 @@
#include "key-container.hpp"
#include "pib-impl.hpp"
+#include "detail/key-impl.hpp"
+#include "util/concepts.hpp"
namespace ndn {
namespace security {
namespace pib {
-KeyContainer::const_iterator::const_iterator(const Name& identity,
- std::set<Name>::const_iterator it,
- shared_ptr<PibImpl> impl)
- : m_identity(identity)
- , m_it(it)
- , m_impl(impl)
+NDN_CXX_ASSERT_FORWARD_ITERATOR(KeyContainer::const_iterator);
+
+KeyContainer::const_iterator::const_iterator()
+ : m_container(nullptr)
+{
+}
+
+KeyContainer::const_iterator::const_iterator(std::set<Name>::const_iterator it,
+ const KeyContainer& container)
+ : m_it(it)
+ , m_container(&container)
{
}
Key
KeyContainer::const_iterator::operator*()
{
- return Key(*m_it, m_impl);
+ BOOST_ASSERT(m_container != nullptr);
+ return m_container->get(*m_it);
}
KeyContainer::const_iterator&
@@ -59,7 +67,11 @@
bool
KeyContainer::const_iterator::operator==(const const_iterator& other)
{
- return (m_impl == other.m_impl && m_identity == other.m_identity && m_it == other.m_it);
+ bool isThisEnd = m_container == nullptr || m_it == m_container->m_keyNames.end();
+ bool isOtherEnd = other.m_container == nullptr || other.m_it == other.m_container->m_keyNames.end();
+ return ((isThisEnd || isOtherEnd) ?
+ (isThisEnd == isOtherEnd) :
+ m_container->m_impl == other.m_container->m_impl && m_it == other.m_it);
}
bool
@@ -68,33 +80,30 @@
return !(*this == other);
}
-KeyContainer::KeyContainer()
-{
-}
-
-KeyContainer::KeyContainer(const Name& identity, std::set<Name>&& keyNames, shared_ptr<PibImpl> impl)
+KeyContainer::KeyContainer(const Name& identity, shared_ptr<PibImpl> impl)
: m_identity(identity)
- , m_keyNames(keyNames)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
+ m_keyNames = impl->getKeysOfIdentity(identity);
}
KeyContainer::const_iterator
KeyContainer::begin() const
{
- return const_iterator(m_identity, m_keyNames.begin(), m_impl);
+ return const_iterator(m_keyNames.begin(), *this);
}
KeyContainer::const_iterator
KeyContainer::end() const
{
- return const_iterator(m_identity, m_keyNames.end(), m_impl);
+ return const_iterator();
}
KeyContainer::const_iterator
KeyContainer::find(const Name& keyName) const
{
- return const_iterator(m_identity, m_keyNames.find(keyName), m_impl);
+ return const_iterator(m_keyNames.find(keyName), *this);
}
size_t
@@ -103,6 +112,63 @@
return m_keyNames.size();
}
+Key
+KeyContainer::add(const uint8_t* key, size_t keyLen, const Name& keyName)
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ if (m_keyNames.count(keyName) == 0) {
+ m_keyNames.insert(keyName);
+ m_keys[keyName] = shared_ptr<detail::KeyImpl>(new detail::KeyImpl(keyName, key, keyLen, m_impl));
+ }
+
+ return get(keyName);
+}
+
+void
+KeyContainer::remove(const Name& keyName)
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ m_keyNames.erase(keyName);
+ m_keys.erase(keyName);
+ m_impl->removeKey(keyName);
+}
+
+Key
+KeyContainer::get(const Name& keyName) const
+{
+ if (m_identity != v2::extractIdentityFromKeyName(keyName)) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Key name `" + keyName.toUri() + "` does not match identity "
+ "`" + m_identity.toUri() + "`"));
+ }
+
+ shared_ptr<detail::KeyImpl> key;
+ auto it = m_keys.find(keyName);
+
+ if (it != m_keys.end()) {
+ key = it->second;
+ }
+ else {
+ key = shared_ptr<detail::KeyImpl>(new detail::KeyImpl(keyName, m_impl));
+ m_keys[keyName] = key;
+ }
+
+ return Key(key);
+}
+
+bool
+KeyContainer::isConsistent() const
+{
+ return m_keyNames == m_impl->getKeysOfIdentity(m_identity);
+}
+
} // namespace pib
} // namespace security
} // namespace ndn
diff --git a/src/security/pib/key-container.hpp b/src/security/pib/key-container.hpp
index a593132..45d9127 100644
--- a/src/security/pib/key-container.hpp
+++ b/src/security/pib/key-container.hpp
@@ -23,6 +23,7 @@
#define NDN_SECURITY_PIB_KEY_CONTAINER_HPP
#include <set>
+#include <unordered_map>
#include "key.hpp"
namespace ndn {
@@ -31,13 +32,25 @@
class PibImpl;
-/// @brief A handler to search or enumerate keys of an identity.
-class KeyContainer
+namespace detail {
+class KeyImpl;
+class IdentityImpl;
+} // namespace detail
+
+/**
+ * @brief Container of keys of an identity
+ *
+ * The container is used to search/enumerate keys of an identity.
+ * The container can be created only by detail::IdentityImpl.
+ */
+class KeyContainer : noncopyable
{
public:
- class const_iterator
+ class const_iterator : public std::iterator<std::forward_iterator_tag, const Key>
{
public:
+ const_iterator();
+
Key
operator*();
@@ -54,12 +67,11 @@
operator!=(const const_iterator& other);
private:
- const_iterator(const Name& identity, std::set<Name>::const_iterator it, shared_ptr<PibImpl> impl);
+ const_iterator(std::set<Name>::const_iterator it, const KeyContainer& container);
private:
- Name m_identity;
std::set<Name>::const_iterator m_it;
- shared_ptr<PibImpl> m_impl;
+ const KeyContainer* m_container;
friend class KeyContainer;
};
@@ -67,10 +79,6 @@
typedef const_iterator iterator;
public:
- KeyContainer();
-
- KeyContainer(const Name& identity, std::set<Name>&& keyNames, shared_ptr<PibImpl> impl);
-
const_iterator
begin() const;
@@ -83,10 +91,63 @@
size_t
size() const;
+ /**
+ * @brief Add @p key of @p keyLen bytes with @p keyName into the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ */
+ Key
+ add(const uint8_t* key, size_t keyLen, const Name& keyName);
+
+ /**
+ * @brief Remove a key with @p keyName from the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ */
+ void
+ remove(const Name& keyName);
+
+ /**
+ * @brief Get a key with @p keyName from the container
+ * @throw std::invalid_argument @p keyName does not match the identity
+ * @throw Pib::Error the key does not exist
+ */
+ Key
+ get(const Name& keyName) const;
+
+ /**
+ * @brief Check if the container is consistent with the backend storage
+ *
+ * @note this method is heavyweight and should be used in debugging mode only.
+ */
+ bool
+ isConsistent() const;
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Create key container for @p identity
+ * @param impl The PIB backend implementation.
+ */
+ KeyContainer(const Name& identity, shared_ptr<PibImpl> impl);
+
+ const std::set<Name>&
+ getKeyNames() const
+ {
+ return m_keyNames;
+ }
+
+ const std::unordered_map<Name, shared_ptr<detail::KeyImpl>>&
+ getLoadedKeys() const
+ {
+ return m_keys;
+ }
+
private:
Name m_identity;
std::set<Name> m_keyNames;
+ /// @brief Cache of loaded detail::KeyImpl.
+ mutable std::unordered_map<Name, shared_ptr<detail::KeyImpl>> m_keys;
+
shared_ptr<PibImpl> m_impl;
+ friend class detail::IdentityImpl;
};
} // namespace pib
diff --git a/src/security/pib/key.cpp b/src/security/pib/key.cpp
index 5890a9c..b4e6daf 100644
--- a/src/security/pib/key.cpp
+++ b/src/security/pib/key.cpp
@@ -20,161 +20,84 @@
*/
#include "key.hpp"
-#include "pib-impl.hpp"
-#include "pib.hpp"
+#include "detail/key-impl.hpp"
#include "../v2/certificate.hpp"
-#include "../transform/public-key.hpp"
namespace ndn {
namespace security {
namespace pib {
-Key::Key()
- : m_keyType(KeyType::NONE)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(false)
- , m_impl(nullptr)
+Key::Key() = default;
+
+Key::Key(weak_ptr<detail::KeyImpl> impl)
+ : m_impl(impl)
{
}
-Key::Key(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl)
- : m_keyName(keyName)
- , m_key(key, keyLen)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(true)
- , m_impl(impl)
-{
- validityCheck();
-
- m_identity = v2::extractIdentityFromKeyName(keyName);
- m_impl->addIdentity(m_identity);
- m_impl->addKey(m_identity, m_keyName, key, keyLen);
-
- transform::PublicKey publicKey;
- publicKey.loadPkcs8(key, keyLen);
- m_keyType = publicKey.getKeyType();
-}
-
-Key::Key(const Name& keyName, shared_ptr<PibImpl> impl)
- : m_keyName(keyName)
- , m_hasDefaultCertificate(false)
- , m_needRefreshCerts(true)
- , m_impl(impl)
-{
- validityCheck();
-
- m_identity = v2::extractIdentityFromKeyName(keyName);
- m_key = m_impl->getKeyBits(m_keyName);
-
- transform::PublicKey key;
- key.loadPkcs8(m_key.buf(), m_key.size());
- m_keyType = key.getKeyType();
-}
-
const Name&
Key::getName() const
{
- validityCheck();
-
- return m_keyName;
+ return lock()->getName();
}
const Name&
Key::getIdentity() const
{
- validityCheck();
+ return lock()->getIdentity();
+}
- return m_identity;
+KeyType
+Key::getKeyType() const
+{
+ return lock()->getKeyType();
}
const Buffer&
Key::getPublicKey() const
{
- validityCheck();
-
- return m_key;
+ return lock()->getPublicKey();
}
void
Key::addCertificate(const v2::Certificate& certificate)
{
- validityCheck();
-
- if (certificate.getKeyName() != m_keyName)
- BOOST_THROW_EXCEPTION(Pib::Error("Certificate name does not match key name"));
-
- if (!m_needRefreshCerts &&
- m_certificates.find(certificate.getName()) == m_certificates.end()) {
- // if we have already loaded all the certificate, but the new certificate is not one of them
- // the CertificateContainer should be refreshed
- m_needRefreshCerts = true;
- }
-
- m_impl->addCertificate(certificate);
+ return lock()->addCertificate(certificate);
}
void
Key::removeCertificate(const Name& certName)
{
- validityCheck();
-
- if (m_hasDefaultCertificate && m_defaultCertificate.getName() == certName)
- m_hasDefaultCertificate = false;
-
- m_impl->removeCertificate(certName);
- m_needRefreshCerts = true;
+ return lock()->removeCertificate(certName);
}
v2::Certificate
Key::getCertificate(const Name& certName) const
{
- validityCheck();
-
- return m_impl->getCertificate(certName);
+ return lock()->getCertificate(certName);
}
const CertificateContainer&
Key::getCertificates() const
{
- validityCheck();
-
- if (m_needRefreshCerts) {
- m_certificates = CertificateContainer(m_impl->getCertificatesOfKey(m_keyName), m_impl);
- m_needRefreshCerts = false;
- }
-
- return m_certificates;
+ return lock()->getCertificates();
}
const v2::Certificate&
Key::setDefaultCertificate(const Name& certName)
{
- validityCheck();
-
- m_impl->setDefaultCertificateOfKey(m_keyName, certName);
- m_defaultCertificate = m_impl->getCertificate(certName);
- m_hasDefaultCertificate = true;
- return m_defaultCertificate;
+ return lock()->setDefaultCertificate(certName);
}
const v2::Certificate&
Key::setDefaultCertificate(const v2::Certificate& certificate)
{
- addCertificate(certificate);
- return setDefaultCertificate(certificate.getName());
+ return lock()->setDefaultCertificate(certificate);
}
const v2::Certificate&
Key::getDefaultCertificate() const
{
- validityCheck();
-
- if (!m_hasDefaultCertificate) {
- m_defaultCertificate = m_impl->getDefaultCertificateOfKey(m_keyName);
- m_hasDefaultCertificate = true;
- }
-
- return m_defaultCertificate;
+ return lock()->getDefaultCertificate();
}
Key::operator bool() const
@@ -185,14 +108,19 @@
bool
Key::operator!() const
{
- return (m_impl == nullptr);
+ return m_impl.expired();
}
-void
-Key::validityCheck() const
+shared_ptr<detail::KeyImpl>
+Key::lock() const
{
- if (m_impl == nullptr)
- BOOST_THROW_EXCEPTION(std::domain_error("Invalid Key instance"));
+ auto impl = m_impl.lock();
+
+ if (impl == nullptr) {
+ BOOST_THROW_EXCEPTION(std::domain_error("Invalid key instance"));
+ }
+
+ return impl;
}
} // namespace pib
diff --git a/src/security/pib/key.hpp b/src/security/pib/key.hpp
index d99e427..69ceec8 100644
--- a/src/security/pib/key.hpp
+++ b/src/security/pib/key.hpp
@@ -22,7 +22,6 @@
#ifndef NDN_SECURITY_PIB_KEY_HPP
#define NDN_SECURITY_PIB_KEY_HPP
-#include "../../data.hpp"
#include "certificate-container.hpp"
#include "../security-common.hpp"
@@ -33,10 +32,12 @@
namespace pib {
-class PibImpl;
+namespace detail {
+class KeyImpl;
+} // namespace detail
/**
- * @brief represents a key
+ * @brief A frontend handle of a key instance
*
* Key is at the second level in PIB's Identity-Key-Certificate hierarchy. A Key has a Name
* (identity + "KEY" + keyId), and contains one or more certificates, one of which is set as
@@ -50,7 +51,7 @@
* @brief Default Constructor
*
* Key created using this default constructor is just a place holder.
- * It must obtain an actual instance from Identity::getKey(...). A typical
+ * It can obtain an actual instance from Identity::getKey(...). A typical
* usage would be for exception handling:
*
* Key key;
@@ -67,134 +68,114 @@
Key();
/**
- * @brief Create a Key with @p keyName
+ * @brief Create a Key with a backend implementation @p impl.
*
- * If the key/identity does not exist in the backend, create it in backend.
- *
- * @param keyName Key name
- * @param key The public key to add.
- * @param keyLen The length of the key.
- * @param impl The actual backend implementation.
+ * This method should only be used by KeyContainer.
*/
- Key(const Name& keyName, const uint8_t* key, size_t keyLen, shared_ptr<PibImpl> impl);
+ explicit
+ Key(weak_ptr<detail::KeyImpl> impl);
- /**
- * @brief Create a Key with @p keyName
- *
- * @param keyName Key name
- * @param impl The actual backend implementation.
- * @throws Pib::Error if the key does not exist.
+ /*
+ * @brief Get key name.
*/
- Key(const Name& keyName, shared_ptr<PibImpl> impl);
-
- /// @brief Get the key name.
const Name&
getName() const;
- /// @brief Get the name of the belonging identity.
+ /**
+ * @brief Get the name of the belonging identity.
+ */
const Name&
getIdentity() const;
- /// @brief Get key type.
+ /**
+ * @brief Get key type.
+ */
KeyType
- getKeyType() const
- {
- return m_keyType;
- }
+ getKeyType() const;
- /// @brief Get public key.
+ /**
+ * @brief Get public key bits.
+ */
const Buffer&
getPublicKey() const;
/**
- * @brief Get a certificate.
- *
- * @return the certificate
- * @throws Pib::Error if the certificate does not exist.
+ * @brief Get a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
*/
v2::Certificate
getCertificate(const Name& certName) const;
- /// @brief Get all certificates for this key.
+ /**
+ * @brief Get all certificates for this key.
+ */
const CertificateContainer&
getCertificates() const;
/**
* @brief Get the default certificate for this Key.
- *
- * @throws Pib::Error if the default certificate does not exist.
+ * @throw Pib::Error the default certificate does not exist.
*/
const v2::Certificate&
getDefaultCertificate() const;
- /// @brief Check if the Key instance is valid
+ /**
+ * @brief Check if the Key instance is valid.
+ */
operator bool() const;
- /// @brief Check if the Key instance is invalid
+ /**
+ * @brief Check if the Key instance is invalid.
+ */
bool
operator!() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/**
- * @brief Add a certificate.
- *
- * @param certificate The certificate to add.
+ * @brief Add @p certificate.
+ * @throw std::invalid_argument certificate name does not match key name
+ * @throw Pib::Error a certificate with the same name already exists
*/
void
addCertificate(const v2::Certificate& certificate);
/**
- * @brief Remove a certificate.
- *
- * @param certName The name of the certificate to delete.
+ * @brief Remove a certificate with @p certName
+ * @throw std::invalid_argument @p certName does not match key name
*/
void
removeCertificate(const Name& certName);
/**
- * @brief Set the default certificate.
- *
- * @param certName The name of the default certificate of the key.
+ * @brief Set an existing certificate with @p certName as the default certificate
+ * @throw std::invalid_argument @p certName does not match key name
+ * @throw Pib::Error the certificate does not exist.
* @return the default certificate
- * @throws Pib::Error if the certificate does not exist.
*/
const v2::Certificate&
setDefaultCertificate(const Name& certName);
/**
- * @brief Set the default certificate.
- *
- * If the certificate does not exist, add it and set it as the default certificate of the key.
- * If the certificate exists, simply set it as the default certificate of the key.
- *
- * @param certificate The certificate to add.
+ * @brief Add @p certificate and set it as the default certificate of the key
+ * @throw std::invalid_argument @p certificate does not match key name
+ * @throw Pib::Error the certificate with the same name already exists.
* @return the default certificate
*/
const v2::Certificate&
setDefaultCertificate(const v2::Certificate& certificate);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+private:
/**
- * @brief Check the validity of this instance
- *
- * @throws std::domain_error if the instance is invalid
+ * @brief Check the validity of the instance
+ * @return a shared_ptr when the instance is valid
+ * @throw std::domain_error the instance is invalid
*/
- void
- validityCheck() const;
+ shared_ptr<detail::KeyImpl>
+ lock() const;
private:
- Name m_identity;
- Name m_keyName;
- Buffer m_key;
- KeyType m_keyType;
-
- mutable bool m_hasDefaultCertificate;
- mutable v2::Certificate m_defaultCertificate;
-
- mutable bool m_needRefreshCerts;
- mutable CertificateContainer m_certificates;
-
- shared_ptr<PibImpl> m_impl;
+ weak_ptr<detail::KeyImpl> m_impl;
};
} // namespace pib
diff --git a/src/security/pib/pib-impl.hpp b/src/security/pib/pib-impl.hpp
index ef859a6..dc384a8 100644
--- a/src/security/pib/pib-impl.hpp
+++ b/src/security/pib/pib-impl.hpp
@@ -22,6 +22,7 @@
#ifndef NDN_SECURITY_PIB_PIB_IMPL_HPP
#define NDN_SECURITY_PIB_PIB_IMPL_HPP
+#include "pib.hpp"
#include <set>
#include "../v2/certificate.hpp"
@@ -131,7 +132,7 @@
* @brief Get the default identity.
*
* @return The name for the default identity.
- * @throws Pib::Error if no default identity.
+ * @throw Pib::Error no default identity.
*/
virtual Name
getDefaultIdentity() const = 0;
@@ -173,7 +174,7 @@
* @brief Get the key bits of a key with name @p keyName.
*
* @return key bits
- * @throws Pib::Error if the key does not exist.
+ * @throw Pib::Error the key does not exist.
*/
virtual Buffer
getKeyBits(const Name& keyName) const = 0;
@@ -192,7 +193,7 @@
/**
* @brief Set an key with @p keyName as the default key of an identity with name @p identity.
*
- * @throws Pib::Error if the key does not exist.
+ * @throw Pib::Error the key does not exist.
*/
virtual void
setDefaultKeyOfIdentity(const Name& identity, const Name& keyName) = 0;
@@ -200,7 +201,7 @@
/**
* @return The name of the default key of an identity with name @p identity.
*
- * @throws Pib::Error if no default key or the identity does not exist.
+ * @throw Pib::Error no default key or the identity does not exist.
*/
virtual Name
getDefaultKeyOfIdentity(const Name& identity) const = 0;
@@ -245,7 +246,7 @@
*
* @param certName The name of the certificate.
* @return the certificate.
- * @throws Pib::Error if the certificate does not exist.
+ * @throw Pib::Error the certificate does not exist.
*/
virtual v2::Certificate
getCertificate(const Name& certName) const = 0;
@@ -264,7 +265,7 @@
/**
* @brief Set a cert with name @p certName as the default of a key with @p keyName.
*
- * @throws Pib::Error if the certificate with name @p certName does not exist.
+ * @throw Pib::Error the certificate with name @p certName does not exist.
*/
virtual void
setDefaultCertificateOfKey(const Name& keyName, const Name& certName) = 0;
@@ -272,7 +273,7 @@
/**
* @return Get the default certificate of a key with @p keyName.
*
- * @throws Pib::Error if the default certificate does not exist.
+ * @throw Pib::Error the default certificate does not exist.
*/
virtual v2::Certificate
getDefaultCertificateOfKey(const Name& keyName) const = 0;
diff --git a/src/security/pib/pib-sqlite3.hpp b/src/security/pib/pib-sqlite3.hpp
index 8c47176..5571657 100644
--- a/src/security/pib/pib-sqlite3.hpp
+++ b/src/security/pib/pib-sqlite3.hpp
@@ -49,7 +49,7 @@
*
* @param dir The directory where the database file is located. By default, it points to the
* $HOME/.ndn directory.
- * @throws PibImpl::Error when initialization fails.
+ * @throw PibImpl::Error when initialization fails.
*/
explicit
PibSqlite3(const std::string& dir = "");
diff --git a/src/security/pib/pib.cpp b/src/security/pib/pib.cpp
index a29018e..6c5f316 100644
--- a/src/security/pib/pib.cpp
+++ b/src/security/pib/pib.cpp
@@ -29,10 +29,11 @@
Pib::Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl)
: m_scheme(scheme)
, m_location(location)
- , m_hasDefaultIdentity(false)
- , m_needRefreshIdentities(true)
+ , m_isDefaultIdentityLoaded(false)
+ , m_identities(impl)
, m_impl(impl)
{
+ BOOST_ASSERT(impl != nullptr);
}
Pib::~Pib() = default;
@@ -68,67 +69,69 @@
{
m_impl->clearIdentities();
m_impl->setTpmLocator("");
-
- m_hasDefaultIdentity = false;
- m_needRefreshIdentities = true;
+ m_isDefaultIdentityLoaded = false;
+ m_identities.reset();
}
Identity
Pib::addIdentity(const Name& identity)
{
- if (!m_needRefreshIdentities && m_identities.find(identity) == m_identities.end()) {
- // if we have already loaded all the identities, but the new identity is not one of them
- // the IdentityContainer should be refreshed
- m_needRefreshIdentities = true;
- }
- return Identity(identity, m_impl, true);
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ return m_identities.add(identity);
}
void
Pib::removeIdentity(const Name& identity)
{
- if (m_hasDefaultIdentity && m_defaultIdentity.getName() == identity)
- m_hasDefaultIdentity = false;
+ BOOST_ASSERT(m_identities.isConsistent());
- m_impl->removeIdentity(identity);
- m_needRefreshIdentities = true;
+ if (m_isDefaultIdentityLoaded && m_defaultIdentity.getName() == identity)
+ m_isDefaultIdentityLoaded = false;
+
+ m_identities.remove(identity);
}
Identity
Pib::getIdentity(const Name& identity) const
{
- return Identity(identity, m_impl, false);
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ return m_identities.get(identity);
}
const IdentityContainer&
Pib::getIdentities() const
{
- if (m_needRefreshIdentities) {
- m_identities = IdentityContainer(m_impl->getIdentities(), m_impl);
- m_needRefreshIdentities = false;
- }
+ BOOST_ASSERT(m_identities.isConsistent());
return m_identities;
}
-Identity&
+const Identity&
Pib::setDefaultIdentity(const Name& identityName)
{
- m_defaultIdentity = addIdentity(identityName);
- m_hasDefaultIdentity = true;
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ m_defaultIdentity = m_identities.add(identityName);
+ m_isDefaultIdentityLoaded = true;
m_impl->setDefaultIdentity(identityName);
return m_defaultIdentity;
}
-Identity&
+const Identity&
Pib::getDefaultIdentity() const
{
- if (!m_hasDefaultIdentity) {
- m_defaultIdentity = Identity(m_impl->getDefaultIdentity(), m_impl, false);
- m_hasDefaultIdentity = true;
+ BOOST_ASSERT(m_identities.isConsistent());
+
+ if (!m_isDefaultIdentityLoaded) {
+ m_defaultIdentity = m_identities.get(m_impl->getDefaultIdentity());
+ m_isDefaultIdentityLoaded = true;
}
+ BOOST_ASSERT(m_impl->getDefaultIdentity() == m_defaultIdentity.getName());
+
return m_defaultIdentity;
}
diff --git a/src/security/pib/pib.hpp b/src/security/pib/pib.hpp
index 06f100d..47dbd5c 100644
--- a/src/security/pib/pib.hpp
+++ b/src/security/pib/pib.hpp
@@ -51,9 +51,6 @@
class Pib : noncopyable
{
public:
- friend class KeyChain;
-
-public:
/// @brief represents a semantic error
class Error : public std::runtime_error
{
@@ -107,8 +104,6 @@
/**
* @brief Get an identity with name @p identityName.
- *
- * @param identityName The name for the identity to get.
* @throw Pib::Error if the identity does not exist.
*/
Identity
@@ -120,15 +115,22 @@
/**
* @brief Get the default identity.
- *
- * @return the default identity.
- * @throws Pib::Error if no default identity.
+ * @throw Pib::Error if no default identity.
*/
- Identity&
+ const Identity&
getDefaultIdentity() const;
NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: // write operations should be private
/*
+ * @brief Create a Pib instance
+ *
+ * @param scheme The scheme for the Pib
+ * @param location The location for the Pib
+ * @param impl The backend implementation
+ */
+ Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl);
+
+ /*
* @brief Create an identity with name @p identityName and return a reference to it.
*
* If there already exists an identity for the name @p identityName, then it is returned.
@@ -136,39 +138,34 @@
*
* @param identityName The name for the identity to be added
*/
- Identity
- addIdentity(const Name& identityName);
-
- /*
- * @brief Remove an identity with name @p identityName.
- *
- * If the default identity is being removed, no default identity will be selected.
- *
- * @param identityName The name for the identity to be deleted
- */
- void
- removeIdentity(const Name& identityName);
/**
- * @brief Set an identity with name @p identityName as the default identity.
+ * @brief Add an @p identity.
*
- * Also create the identity if it does not exist.
+ * If no default identity is set before, the new identity will be set as the default identity
*
- * @param identityName The name for the default identity.
- * @return the default identity
+ * @return handle of the added identity.
*/
- Identity&
- setDefaultIdentity(const Name& identityName);
+ Identity
+ addIdentity(const Name& identity);
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
/*
- * @brief Create a new Pib with the specified @p location
+ * @brief Remove an @p identity.
*
- * @param scheme The scheme for the Pib
- * @param location The location for the Pib
- * @param impl The backend implementation
+ * If the default identity is being removed, no default identity will be selected.
*/
- Pib(const std::string& scheme, const std::string& location, shared_ptr<PibImpl> impl);
+ void
+ removeIdentity(const Name& identity);
+
+ /**
+ * @brief Set an @p identity as the default identity.
+ *
+ * Create the identity if it does not exist.
+ *
+ * @return handle of the default identity
+ */
+ const Identity&
+ setDefaultIdentity(const Name& identity);
shared_ptr<PibImpl>
getImpl()
@@ -180,13 +177,14 @@
std::string m_scheme;
std::string m_location;
- mutable bool m_hasDefaultIdentity;
+ mutable bool m_isDefaultIdentityLoaded;
mutable Identity m_defaultIdentity;
- mutable bool m_needRefreshIdentities;
- mutable IdentityContainer m_identities;
+ IdentityContainer m_identities;
shared_ptr<PibImpl> m_impl;
+
+ friend class KeyChain;
};
} // namespace pib
diff --git a/src/util/concepts.hpp b/src/util/concepts.hpp
index 8d4567e..a8c7fdd 100644
--- a/src/util/concepts.hpp
+++ b/src/util/concepts.hpp
@@ -1,6 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2014-2017, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -96,6 +102,41 @@
}
};
+// NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE and NDN_CXX_ASSERT_FORWARD_ITERATOR
+// originally written as part of NFD codebase
+
+namespace detail {
+
+// As of Boost 1.54.0, the internal implementation of BOOST_CONCEPT_ASSERT does not allow
+// multiple assertions on the same line, so we have to combine multiple concepts together.
+
+template<typename T>
+class StlForwardIteratorConcept : public boost::ForwardIterator<T>
+ , public boost::DefaultConstructible<T>
+{
+};
+
+} // namespace detail
+
+/** \brief assert T is default constructible
+ * \sa http://en.cppreference.com/w/cpp/concept/DefaultConstructible
+ */
+#define NDN_CXX_ASSERT_DEFAULT_CONSTRUCTIBLE(T) \
+ static_assert(std::is_default_constructible<T>::value, \
+ #T " must be default-constructible"); \
+ BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<T>))
+
+/** \brief assert T is a forward iterator
+ * \sa http://en.cppreference.com/w/cpp/concept/ForwardIterator
+ * \note A forward iterator should be default constructible, but boost::ForwardIterator follows
+ * SGI standard which doesn't require DefaultConstructible, so a separate check is needed.
+ */
+#define NDN_CXX_ASSERT_FORWARD_ITERATOR(T) \
+ BOOST_CONCEPT_ASSERT((::ndn::detail::StlForwardIteratorConcept<T>)); \
+ static_assert(std::is_default_constructible<T>::value, \
+ #T " must be default-constructible")
+
+
} // namespace ndn
#endif // NDN_UTIL_CONCEPTS_HPP