blob: 3eb2cce11821e1acc1342c12906619b7e0f082ca [file] [log] [blame]
Weiqi Shi28a90fb2014-07-09 10:28:55 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevc0e26582017-08-13 21:16:49 -04002/*
Alexander Afanasyev42290b22017-03-09 12:58:29 -08003 * Copyright (c) 2014-2017, Regents of the University of California.
Weiqi Shi28a90fb2014-07-09 10:28:55 -07004 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "index.hpp"
Weiqi Shi28a90fb2014-07-09 10:28:55 -070021
Alexander Afanasyevc0e26582017-08-13 21:16:49 -040022#include <ndn-cxx/util/sha256.hpp>
23#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
Weiqi Shi28a90fb2014-07-09 10:28:55 -070024
25namespace repo {
26
27/** @brief determines if entry can satisfy interest
28 * @param hash SHA256 hash of PublisherPublicKeyLocator if exists in interest, otherwise ignored
29 */
30static bool
31matchesSimpleSelectors(const Interest& interest, ndn::ConstBufferPtr& hash,
32 const Index::Entry& entry)
33{
34 const Name& fullName = entry.getName();
35
36 if (!interest.getName().isPrefixOf(fullName))
37 return false;
38
39 size_t nSuffixComponents = fullName.size() - interest.getName().size();
40 if (interest.getMinSuffixComponents() >= 0 &&
41 nSuffixComponents < static_cast<size_t>(interest.getMinSuffixComponents()))
42 return false;
43 if (interest.getMaxSuffixComponents() >= 0 &&
44 nSuffixComponents > static_cast<size_t>(interest.getMaxSuffixComponents()))
45 return false;
46
47 if (!interest.getExclude().empty() &&
48 entry.getName().size() > interest.getName().size() &&
49 interest.getExclude().isExcluded(entry.getName()[interest.getName().size()]))
50 return false;
51 if (!interest.getPublisherPublicKeyLocator().empty())
52 {
53 if (*entry.getKeyLocatorHash() != *hash)
54 return false;
55 }
56 return true;
57}
58
Alexander Afanasyevd352cce2015-11-20 14:15:11 -050059Index::Index(size_t nMaxPackets)
Weiqi Shi28a90fb2014-07-09 10:28:55 -070060 : m_maxPackets(nMaxPackets)
61 , m_size(0)
62{
63}
64
65
66bool
Alexander Afanasyevd352cce2015-11-20 14:15:11 -050067Index::insert(const Data& data, int64_t id)
Weiqi Shi28a90fb2014-07-09 10:28:55 -070068{
69 if (isFull())
Alexander Afanasyev42290b22017-03-09 12:58:29 -080070 BOOST_THROW_EXCEPTION(Error("The Index is Full. Cannot Insert Any Data!"));
Weiqi Shi28a90fb2014-07-09 10:28:55 -070071 Entry entry(data, id);
WeiqiShia79c7782014-12-26 09:42:10 +080072 bool isInserted = m_indexContainer.insert(entry).second;
Weiqi Shi28a90fb2014-07-09 10:28:55 -070073 if (isInserted)
74 ++m_size;
75 return isInserted;
76}
77
78bool
Alexander Afanasyevd352cce2015-11-20 14:15:11 -050079Index::insert(const Name& fullName, int64_t id,
Weiqi Shi28a90fb2014-07-09 10:28:55 -070080 const ndn::ConstBufferPtr& keyLocatorHash)
81{
82 if (isFull())
Alexander Afanasyev42290b22017-03-09 12:58:29 -080083 BOOST_THROW_EXCEPTION(Error("The Index is Full. Cannot Insert Any Data!"));
Weiqi Shi28a90fb2014-07-09 10:28:55 -070084 Entry entry(fullName, keyLocatorHash, id);
WeiqiShia79c7782014-12-26 09:42:10 +080085 bool isInserted = m_indexContainer.insert(entry).second;
Weiqi Shi28a90fb2014-07-09 10:28:55 -070086 if (isInserted)
87 ++m_size;
88 return isInserted;
89}
90
91std::pair<int64_t,Name>
92Index::find(const Interest& interest) const
93{
94 Name name = interest.getName();
WeiqiShia79c7782014-12-26 09:42:10 +080095 IndexContainer::const_iterator result = m_indexContainer.lower_bound(name);
96 if (result != m_indexContainer.end())
Weiqi Shi28a90fb2014-07-09 10:28:55 -070097 {
98 return selectChild(interest, result);
99 }
100 else
101 {
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700102 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700103 }
104}
105
106std::pair<int64_t,Name>
107Index::find(const Name& name) const
108{
WeiqiShia79c7782014-12-26 09:42:10 +0800109 IndexContainer::const_iterator result = m_indexContainer.lower_bound(name);
110 if (result != m_indexContainer.end())
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700111 {
112 return findFirstEntry(name, result);
113 }
114 else
115 {
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700116 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700117 }
118}
119
120bool
121Index::hasData(const Data& data) const
122{
123 Index::Entry entry(data, -1); // the id number is useless
WeiqiShia79c7782014-12-26 09:42:10 +0800124 IndexContainer::const_iterator result = m_indexContainer.find(entry);
125 return result != m_indexContainer.end();
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700126
127}
128
129std::pair<int64_t,Name>
130Index::findFirstEntry(const Name& prefix,
WeiqiShia79c7782014-12-26 09:42:10 +0800131 IndexContainer::const_iterator startingPoint) const
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700132{
WeiqiShia79c7782014-12-26 09:42:10 +0800133 BOOST_ASSERT(startingPoint != m_indexContainer.end());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700134 if (prefix.isPrefixOf(startingPoint->getName()))
135 {
136 return std::make_pair(startingPoint->getId(), startingPoint->getName());
137 }
138 else
139 {
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700140 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700141 }
142}
143
144bool
145Index::erase(const Name& fullName)
146{
147 Entry entry(fullName);
WeiqiShia79c7782014-12-26 09:42:10 +0800148 IndexContainer::const_iterator findIterator = m_indexContainer.find(entry);
149 if (findIterator != m_indexContainer.end())
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700150 {
WeiqiShia79c7782014-12-26 09:42:10 +0800151 m_indexContainer.erase(findIterator);
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700152 m_size--;
153 return true;
154 }
155 else
156 return false;
157}
158
159const ndn::ConstBufferPtr
160Index::computeKeyLocatorHash(const KeyLocator& keyLocator)
161{
162 const Block& block = keyLocator.wireEncode();
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400163 ndn::ConstBufferPtr keyLocatorHash = ndn::util::Sha256::computeDigest(block.wire(), block.size());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700164 return keyLocatorHash;
165}
166
167std::pair<int64_t,Name>
168Index::selectChild(const Interest& interest,
WeiqiShia79c7782014-12-26 09:42:10 +0800169 IndexContainer::const_iterator startingPoint) const
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700170{
WeiqiShia79c7782014-12-26 09:42:10 +0800171 BOOST_ASSERT(startingPoint != m_indexContainer.end());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700172 bool isLeftmost = (interest.getChildSelector() <= 0);
173 ndn::ConstBufferPtr hash;
174 if (!interest.getPublisherPublicKeyLocator().empty())
175 {
176 KeyLocator keyLocator = interest.getPublisherPublicKeyLocator();
177 const Block& block = keyLocator.wireEncode();
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400178 hash = ndn::util::Sha256::computeDigest(block.wire(), block.size());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700179 }
180
181 if (isLeftmost)
182 {
WeiqiShia79c7782014-12-26 09:42:10 +0800183 for (IndexContainer::const_iterator it = startingPoint;
184 it != m_indexContainer.end(); ++it)
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700185 {
186 if (!interest.getName().isPrefixOf(it->getName()))
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700187 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700188 if (matchesSimpleSelectors(interest, hash, (*it)))
189 return std::make_pair(it->getId(), it->getName());
190 }
191 }
192 else
193 {
WeiqiShia79c7782014-12-26 09:42:10 +0800194 IndexContainer::const_iterator boundary = m_indexContainer.lower_bound(interest.getName());
195 if (boundary == m_indexContainer.end() || !interest.getName().isPrefixOf(boundary->getName()))
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700196 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700197 Name successor = interest.getName().getSuccessor();
WeiqiShia79c7782014-12-26 09:42:10 +0800198 IndexContainer::const_iterator last = interest.getName().size() == 0 ?
199 m_indexContainer.end() : m_indexContainer.lower_bound(interest.getName().getSuccessor());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700200 while (true)
201 {
WeiqiShia79c7782014-12-26 09:42:10 +0800202 IndexContainer::const_iterator prev = last;
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700203 --prev;
204 if (prev == boundary)
205 {
206 bool isMatch = matchesSimpleSelectors(interest, hash, (*prev));
207 if (isMatch)
208 {
209 return std::make_pair(prev->getId(), prev->getName());
210 }
211 else
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700212 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700213 }
WeiqiShia79c7782014-12-26 09:42:10 +0800214 IndexContainer::const_iterator first =
215 m_indexContainer.lower_bound(prev->getName().getPrefix(interest.getName().size() + 1));
216 IndexContainer::const_iterator match =
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700217 std::find_if(first, last, bind(&matchesSimpleSelectors, interest, hash, _1));
218 if (match != last)
219 {
220 return std::make_pair(match->getId(), match->getName());
221 }
222 last = first;
223 }
224 }
Alexander Afanasyevb7e8a812014-07-23 01:36:47 -0700225 return std::make_pair(0, Name());
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700226}
227
Alexander Afanasyevd352cce2015-11-20 14:15:11 -0500228Index::Entry::Entry(const Data& data, int64_t id)
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700229 : m_name(data.getFullName())
230 , m_id(id)
231{
232 const ndn::Signature& signature = data.getSignature();
233 if (signature.hasKeyLocator())
234 m_keyLocatorHash = computeKeyLocatorHash(signature.getKeyLocator());
235}
236
Alexander Afanasyevd352cce2015-11-20 14:15:11 -0500237Index::Entry::Entry(const Name& fullName, const KeyLocator& keyLocator, int64_t id)
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700238 : m_name(fullName)
239 , m_keyLocatorHash(computeKeyLocatorHash(keyLocator))
240 , m_id(id)
241{
242}
243
244Index::Entry::Entry(const Name& fullName,
Alexander Afanasyevd352cce2015-11-20 14:15:11 -0500245 const ndn::ConstBufferPtr& keyLocatorHash, int64_t id)
Weiqi Shi28a90fb2014-07-09 10:28:55 -0700246 : m_name(fullName)
247 , m_keyLocatorHash(keyLocatorHash)
248 , m_id(id)
249{
250}
251
252Index::Entry::Entry(const Name& name)
253 : m_name(name)
254{
255}
256
257} // namespace repo