blob: 9815aa5a78f72de33e615301c94070a7f209d05b [file] [log] [blame]
Zhiyi Zhangcea58d52015-08-26 10:19:56 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Zhiyi Zhang19a11d22018-04-12 22:58:20 -07003 * Copyright (c) 2014-2018, Regents of the University of California
Zhiyi Zhangcea58d52015-08-26 10:19:56 -07004 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04005 * This file is part of NAC (Name-Based Access Control for NDN).
6 * See AUTHORS.md for complete list of NAC authors and contributors.
Zhiyi Zhangcea58d52015-08-26 10:19:56 -07007 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -04008 * NAC is free software: you can redistribute it and/or modify it under the terms
Zhiyi Zhangcea58d52015-08-26 10:19:56 -07009 * 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 *
Alexander Afanasyev9091d832018-04-18 17:21:08 -040012 * NAC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070013 * 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
Alexander Afanasyev9091d832018-04-18 17:21:08 -040017 * NAC, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070018 *
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070019 * @author Zhiyi Zhang <zhiyi@cs.ucla.edu>
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070020 */
21
22#include "repetitive-interval.hpp"
23#include "tlv.hpp"
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070024#include <ndn-cxx/encoding/block-helpers.hpp>
25#include <ndn-cxx/util/concepts.hpp>
26#include <boost/date_time/posix_time/posix_time.hpp>
27
28namespace ndn {
Alexander Afanasyev9091d832018-04-18 17:21:08 -040029namespace nac {
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070030
31static const TimeStamp DEFAULT_TIME = boost::posix_time::from_iso_string("14000101T000000");
32
33BOOST_CONCEPT_ASSERT((WireEncodable<RepetitiveInterval>));
34BOOST_CONCEPT_ASSERT((WireDecodable<RepetitiveInterval>));
35
36RepetitiveInterval::RepetitiveInterval()
37 : m_startDate(DEFAULT_TIME)
38 , m_endDate(DEFAULT_TIME)
39 , m_intervalStartHour(0)
40 , m_intervalEndHour(24)
41 , m_nRepeats(0)
42 , m_unit(RepeatUnit::NONE)
43{
44}
45
46RepetitiveInterval::RepetitiveInterval(const Block& block)
47{
48 wireDecode(block);
49}
50
51RepetitiveInterval::RepetitiveInterval(const TimeStamp& startDate,
52 const TimeStamp& endDate,
53 size_t intervalStartHour,
54 size_t intervalEndHour,
55 size_t nRepeats,
56 RepeatUnit unit)
57 : m_startDate(startDate)
58 , m_endDate(endDate)
59 , m_intervalStartHour(intervalStartHour)
60 , m_intervalEndHour(intervalEndHour)
61 , m_nRepeats(nRepeats)
62 , m_unit(unit)
63{
64 BOOST_ASSERT(m_intervalStartHour < m_intervalEndHour);
65 BOOST_ASSERT(m_startDate.date() <= m_endDate.date());
66 BOOST_ASSERT(m_intervalEndHour <= 24);
67 if (unit == RepeatUnit::NONE)
68 BOOST_ASSERT(m_startDate.date() == m_endDate.date());
69}
70
71template<encoding::Tag TAG>
72size_t
73RepetitiveInterval::wireEncode(EncodingImpl<TAG>& encoder) const
74{
75 using namespace boost::posix_time;
76
77 size_t totalLength = 0;
78
79 // RepeatUnit
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070080 totalLength +=
81 prependNonNegativeIntegerBlock(encoder, tlv::RepeatUnit, static_cast<size_t>(m_unit));
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070082 // NRepeat
83 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::NRepeats, m_nRepeats);
84 // IntervalEndHour
85 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::IntervalEndHour, m_intervalEndHour);
86 // IntervalStartHour
Zhiyi Zhang19a11d22018-04-12 22:58:20 -070087 totalLength += prependNonNegativeIntegerBlock(encoder, tlv::IntervalStartHour, m_intervalStartHour);
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070088 // EndDate
89 totalLength += prependStringBlock(encoder, tlv::EndDate, to_iso_string(m_endDate));
90 // StartDate
91 totalLength += prependStringBlock(encoder, tlv::StartDate, to_iso_string(m_startDate));
92
93 totalLength += encoder.prependVarNumber(totalLength);
94 totalLength += encoder.prependVarNumber(tlv::RepetitiveInterval);
95
96 return totalLength;
97}
98
99const Block&
100RepetitiveInterval::wireEncode() const
101{
102 if (m_wire.hasWire())
103 return m_wire;
104
105 EncodingEstimator estimator;
106 size_t estimatedSize = wireEncode(estimator);
107
108 EncodingBuffer buffer(estimatedSize, 0);
109 wireEncode(buffer);
110
111 this->m_wire = buffer.block();
112 return m_wire;
113}
114
115void
116RepetitiveInterval::wireDecode(const Block& wire)
117{
118 using namespace boost::posix_time;
119
120 if (wire.type() != tlv::RepetitiveInterval)
121 BOOST_THROW_EXCEPTION(tlv::Error("Unexpected TLV type when decoding RepetitiveInterval"));
122
123 m_wire = wire;
124 m_wire.parse();
125
126 if (m_wire.elements_size() != 6)
127 BOOST_THROW_EXCEPTION(tlv::Error("RepetitiveInterval tlv does not have six sub-TLVs"));
128
129 Block::element_const_iterator it = m_wire.elements_begin();
130 // StartDate
131 if (it->type() == tlv::StartDate) {
132 m_startDate = ptime(from_iso_string(readString(*it)));
133 it++;
134 }
135 else
136 BOOST_THROW_EXCEPTION(tlv::Error("First element must be StartDate"));
137
138 // EndDate
139 if (it->type() == tlv::EndDate) {
140 m_endDate = ptime(from_iso_string(readString(*it)));
141 it++;
142 }
143 else
144 BOOST_THROW_EXCEPTION(tlv::Error("Second element must be EndDate"));
145
146 // IntervalStartHour
147 if (it->type() == tlv::IntervalStartHour) {
148 m_intervalStartHour = readNonNegativeInteger(*it);
149 it++;
150 }
151 else
152 BOOST_THROW_EXCEPTION(tlv::Error("Third element must be IntervalStartHour"));
153
154 // IntervalEndHour
155 if (it->type() == tlv::IntervalEndHour) {
156 m_intervalEndHour = readNonNegativeInteger(*it);
157 it++;
158 }
159 else
160 BOOST_THROW_EXCEPTION(tlv::Error("Fourth element must be IntervalEndHour"));
161
162 // NRepeats
163 if (it->type() == tlv::NRepeats) {
164 m_nRepeats = readNonNegativeInteger(*it);
165 it++;
166 }
167 else
168 BOOST_THROW_EXCEPTION(tlv::Error("Fifth element must be NRepeats"));
169
170 // RepeatUnit
171 if (it->type() == tlv::RepeatUnit) {
172 m_unit = static_cast<RepeatUnit>(readNonNegativeInteger(*it));
173 it++;
174 }
175 else
176 BOOST_THROW_EXCEPTION(tlv::Error("The last element must be RepeatUnit"));
177}
178
179std::tuple<bool, Interval>
180RepetitiveInterval::getInterval(const TimeStamp& tp) const
181{
182 TimeStamp startTime;
183 TimeStamp endTime;
184 bool isPositive;
185
186 if (!this->hasIntervalOnDate(tp)) {
187 // there is no interval on the date of tp
188 startTime = TimeStamp(tp.date(), boost::posix_time::hours(0));
189 endTime = TimeStamp(tp.date(), boost::posix_time::hours(24));
190 isPositive = false;
191 }
192 else {
193 // there is an interval on the date of tp
194 startTime = TimeStamp(tp.date(), boost::posix_time::hours(m_intervalStartHour));
195 endTime = TimeStamp(tp.date(), boost::posix_time::hours(m_intervalEndHour));
196
197 // check if in the time duration
198 if (tp < startTime) {
199 endTime = startTime;
200 startTime = TimeStamp(tp.date(), boost::posix_time::hours(0));
201 isPositive = false;
202 }
203 else if (tp > endTime) {
204 startTime = endTime;
205 endTime = TimeStamp(tp.date(), boost::posix_time::hours(24));
206 isPositive = false;
207 }
208 else {
209 isPositive = true;
210 }
211 }
212 return std::make_tuple(isPositive, Interval(startTime, endTime));
213}
214
215bool
216RepetitiveInterval::hasIntervalOnDate(const TimeStamp& tp) const
217{
218 namespace bg = boost::gregorian;
219
220 // check if in the bound of the interval
221 if (tp.date() < m_startDate.date() || tp.date() > m_endDate.date()) {
222 return false;
223 }
224
225 if (m_unit == RepeatUnit::NONE) {
226 return true;
227 }
228
229 // check if in the matching date
230 bg::date dateA = tp.date();
231 bg::date dateB = m_startDate.date();
232 if (m_unit == RepeatUnit::DAY) {
233 bg::date_duration duration = dateA - dateB;
234 if (static_cast<size_t>(duration.days()) % m_nRepeats == 0)
235 return true;
236 }
237 else if (m_unit == RepeatUnit::MONTH && dateA.day() == dateB.day()) {
238 size_t yearDiff = static_cast<size_t>(dateA.year() - dateB.year());
239 size_t monthDiff = 12 * yearDiff + dateA.month().as_number() - dateB.month().as_number();
240 if (monthDiff % m_nRepeats == 0)
241 return true;
242 }
243 else if (m_unit == RepeatUnit::YEAR &&
244 dateA.day().as_number() == dateB.day().as_number() &&
245 dateA.month().as_number() == dateB.month().as_number()) {
246 size_t diff = static_cast<size_t>(dateA.year() - dateB.year());
247 if (diff % m_nRepeats == 0)
248 return true;
249 }
250
251 return false;
252}
253
254bool
255RepetitiveInterval::operator<(const RepetitiveInterval& interval) const
256{
257 if (m_startDate < interval.getStartDate())
258 return true;
Yingdi Yua717b882016-03-09 17:56:42 -0800259 else if (m_startDate > interval.getStartDate())
260 return false;
261
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700262 if (m_endDate < interval.getEndDate())
263 return true;
Yingdi Yua717b882016-03-09 17:56:42 -0800264 else if (m_endDate > interval.getEndDate())
265 return false;
266
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700267 if (m_intervalStartHour < interval.getIntervalStartHour())
268 return true;
Yingdi Yua717b882016-03-09 17:56:42 -0800269 else if (m_intervalStartHour > interval.getIntervalStartHour())
270 return false;
271
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700272 if (m_intervalEndHour < interval.getIntervalEndHour())
273 return true;
Yingdi Yua717b882016-03-09 17:56:42 -0800274 else if (m_intervalEndHour > interval.getIntervalEndHour())
275 return false;
276
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700277 if (m_nRepeats < interval.getNRepeats())
278 return true;
Yingdi Yua717b882016-03-09 17:56:42 -0800279 else if (m_nRepeats > interval.getNRepeats())
280 return false;
281
282 return (static_cast<size_t>(m_unit) < static_cast<size_t>(interval.getRepeatUnit()));
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700283}
284
Alexander Afanasyev9091d832018-04-18 17:21:08 -0400285} // namespace nac
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700286} // namespace ndn