blob: dfe92d71ac9c71d344b4fc824f091653a31e47ea [file] [log] [blame]
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2018, The University of Memphis,
4 * Regents of the University of California,
5 * Arizona Board of Regents.
6 *
7 * This file is part of NLSR (Named-data Link State Routing).
8 * See AUTHORS.md for complete list of NLSR authors and contributors.
9 *
10 * NLSR is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 **/
21
22#include "lsa-segment-storage.hpp"
23#include "logger.hpp"
24#include "lsa.hpp"
25#include "utility/name-helper.hpp"
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -060026#include "conf-parameter.hpp"
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +000027
28namespace nlsr {
29
30INIT_LOGGER(LsaSegmentStorage);
31
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -060032LsaSegmentStorage::LsaSegmentStorage(ndn::Scheduler& scheduler)
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +000033 : m_scheduler(scheduler)
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +000034{
35}
36
37void
38LsaSegmentStorage::connectToFetcher(ndn::util::SegmentFetcher& fetcher)
39{
40 fetcher.afterSegmentValidated.connect(std::bind(&LsaSegmentStorage::afterFetcherSignalEmitted,
41 this, _1));
42}
43
44const ndn::Data*
45LsaSegmentStorage::getLsaSegment(const ndn::Interest& interest)
46{
47 ndn::Name lsaSegmentsKey = interest.getName();
48
Ashlesh Gawande304bebf2018-02-07 17:10:35 -060049 // If this is the first interest then it does not contain the segment number,
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +000050 // so need to append zero segment component at the end to match with the data
51 if (lsaSegmentsKey.size() > 0) {
52 if (!lsaSegmentsKey.get(-1).isSegment()) {
53 lsaSegmentsKey.appendSegment(0);
54 }
55
56 auto it = m_lsaSegments.find(lsaSegmentsKey);
57 if (it == m_lsaSegments.end()) {
58 NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " cannot be found in the lsa storage");
59
60 return nullptr;
61 }
62 else {
63 NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " is in the storage.");
64 return &(it->second);
65 }
66 }
67 else {
68 NLSR_LOG_ERROR("Received interest has empty name.");
69 return nullptr;
70 }
71}
72
73void
74LsaSegmentStorage::afterFetcherSignalEmitted(const ndn::Data& lsaSegment)
75{
76 NLSR_LOG_TRACE("Received a LSA segment: " << lsaSegment.getName());
77
78 // lsaSegmentName is /<router-prefix>/<LS type>/<sequence no.>/<version no.>/<segment no.>
79 auto lsaSegmentName = lsaSegment.getName();
80
81 if (lsaSegmentName.size() > 0) {
82 // lsaSegmentsKey is /<router-prefix>/<LS type>/<sequence no.>/<segment no.>
83 ndn::Name lsaSegmentsKey(lsaSegmentName.getPrefix(lsaSegmentName.size() - 2));
84 lsaSegmentsKey.append(lsaSegmentName.get(-1));
85
86 // No need to store same LSA multiple time
87 if (m_lsaSegments.find(lsaSegmentsKey) == m_lsaSegments.end()) {
Ashlesh Gawandee8d8bd52018-08-09 17:18:51 -050088 NLSR_LOG_TRACE("Received LSA segment is new. Storing it in the storage.");
89 NLSR_LOG_TRACE("LSA data segment's name: " << lsaSegmentName);
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +000090
91 // Delete the same LSA with lower sequence number
92 deleteOldLsas(lsaSegmentName);
93
94 m_lsaSegments[lsaSegmentsKey] = lsaSegment;
95 }
96 else {
97 NLSR_LOG_TRACE("The received segment is already in the storage.");
98 }
99
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600100 std::string content(reinterpret_cast<const char*>(lsaSegment.getContent().value()),
101 lsaSegment.getContent().value_size());
102
103 ndn::time::seconds expirationTime(LSA_REFRESH_TIME_DEFAULT);
104
105 std::vector<std::string> options;
106 boost::split(options, content, boost::is_any_of("|"));
107
108 try {
109 expirationTime = ndn::time::duration_cast<ndn::time::seconds>
Ashlesh Gawanded65786a2018-03-30 01:17:58 -0500110 (ndn::time::fromIsoString(options.at(3)) - ndn::time::system_clock::now());
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600111 } catch (const std::exception& e) {
112 NLSR_LOG_ERROR("Cannot extract expiration time from LSA content: " << e.what());
113 }
114
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000115 // schedule the segment deletion
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600116 scheduleLsaSegmentDeletion(lsaSegmentsKey, expirationTime);
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000117 }
118 else {
119 NLSR_LOG_ERROR("The received LSA segment has empty name.");
120 }
121}
122
123void
124LsaSegmentStorage::deleteOldLsas(const ndn::Name& newLsaName)
125{
126 auto newLsaKey = newLsaName.getPrefix(newLsaName.size() - 3);
127 auto newSeqNo = newLsaName.get(-3).toNumber();
128
129 std::vector<decltype(m_lsaSegments)::key_type> lsaToDelete;
130
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600131 for (const auto& segment : m_lsaSegments) {
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000132 ndn::Name segmentKey = segment.first;
133 auto oldSeqNo = segmentKey.get(-2).toNumber();
134 auto existingLsaKey = segmentKey.getPrefix(segmentKey.size() - 2);
135
136 if (newLsaKey == existingLsaKey) {
137 if (newSeqNo > oldSeqNo) { // in the key the second last component is the sequence number
138 NLSR_LOG_TRACE("Outdated LSA: " << segmentKey << " with seq no: " <<
139 oldSeqNo << " is deleted.");
140 lsaToDelete.push_back(segmentKey);
141 }
142 }
143 }
144
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600145 for (const auto& segmentKey : lsaToDelete) {
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000146 m_lsaSegments.erase(segmentKey);
147 }
148}
149
150void
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600151LsaSegmentStorage::scheduleLsaSegmentDeletion(const ndn::Name& lsaSegmentsKey,
152 ndn::time::seconds expirationTime)
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000153{
Ashlesh Gawande8c6d8c82018-02-28 21:41:31 -0600154 NLSR_LOG_TRACE("Scheduling LSA segment deletion for "
155 << lsaSegmentsKey << " in: " << expirationTime);
156 m_scheduler.scheduleEvent(expirationTime,
157 [lsaSegmentsKey, this] {
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000158 m_lsaSegments.erase(lsaSegmentsKey);
159 });
160}
161
Ashlesh Gawande304bebf2018-02-07 17:10:35 -0600162} // namespace nlsr