blob: 14635b432c3f52d6634d9853a363a86dd523b209 [file] [log] [blame]
Zhiyi Zhangcea58d52015-08-26 10:19:56 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California
4 *
5 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
6 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
7 *
8 * ndn-group-encrypt 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 * ndn-group-encrypt 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 * ndn-group-encrypt, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
20 */
21
22#include "schedule.hpp"
23#include "tlv.hpp"
24
25#include <ndn-cxx/encoding/block-helpers.hpp>
26#include <ndn-cxx/util/concepts.hpp>
27
28namespace ndn {
29namespace gep {
30
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +080031/**
32 * @brief Helper functon to calculate black interval results or white interval results
33 * @p list The RepetitiveInterval list, which can be white list or the black list
34 * @p tp The timestamp
35 * @p positiveR The positive result
36 * @p negativeR The negative result
37 */
38static void
39calIntervalResult(const std::set<RepetitiveInterval>& list, const TimeStamp& ts,
40 Interval& positiveR, Interval& negativeR)
41{
42 Interval tempInterval;
43 bool isPositive;
44
45 for (const RepetitiveInterval& element : list) {
46 std::tie(isPositive, tempInterval) = element.getInterval(ts);
47 if (isPositive == true) {
48 positiveR || tempInterval;
49 }
50 else {
51 if (!negativeR.isValid())
52 negativeR = tempInterval;
53 else
54 negativeR && tempInterval;
55 }
56 }
57}
58
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070059BOOST_CONCEPT_ASSERT((WireEncodable<Schedule>));
60BOOST_CONCEPT_ASSERT((WireDecodable<Schedule>));
61
62Schedule::Schedule() = default;
63
64Schedule::Schedule(const Block& block)
65{
66 wireDecode(block);
67}
68
69template<encoding::Tag TAG>
70size_t
71Schedule::wireEncode(EncodingImpl<TAG>& encoder) const
72{
73 size_t totalLength = 0;
74 size_t blackLength = 0;
75 size_t whiteLength = 0;
76
77 // encode the blackIntervalList as an embed TLV structure
Yingdi Yud263c8a2016-03-09 16:53:19 -080078 for (auto it = m_blackIntervalList.rbegin(); it != m_blackIntervalList.rend(); it++) {
79 blackLength += encoder.prependBlock(it->wireEncode());
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070080 }
81 blackLength += encoder.prependVarNumber(blackLength);
82 blackLength += encoder.prependVarNumber(tlv::BlackIntervalList);
83
84 // encode the whiteIntervalList as an embed TLV structure
Yingdi Yud263c8a2016-03-09 16:53:19 -080085 for (auto it = m_whiteIntervalList.rbegin(); it != m_whiteIntervalList.rend(); it++) {
86 whiteLength += encoder.prependBlock(it->wireEncode());
Zhiyi Zhangcea58d52015-08-26 10:19:56 -070087 }
88 whiteLength += encoder.prependVarNumber(whiteLength);
89 whiteLength += encoder.prependVarNumber(tlv::WhiteIntervalList);
90
91 totalLength = whiteLength + blackLength;
92 totalLength += encoder.prependVarNumber(totalLength);
93 totalLength += encoder.prependVarNumber(tlv::Schedule);
94
95 return totalLength;
96}
97
98const Block&
99Schedule::wireEncode() const
100{
101 if (m_wire.hasWire())
102 return m_wire;
103
104 EncodingEstimator estimator;
105 size_t estimatedSize = wireEncode(estimator);
106
107 EncodingBuffer buffer(estimatedSize, 0);
108 wireEncode(buffer);
109
110 this->m_wire = buffer.block();
111 return m_wire;
112}
113
114void
115Schedule::wireDecode(const Block& wire)
116{
117 if (wire.type() != tlv::Schedule)
118 BOOST_THROW_EXCEPTION(tlv::Error("Unexpected TLV type when decoding RepetitiveInterval"));
119
120 m_wire = wire;
121 m_wire.parse();
122
123 if (m_wire.elements_size() != 2)
124 BOOST_THROW_EXCEPTION(tlv::Error("RepetitiveInterval tlv does not have two sub-TLVs"));
125
126 Block::element_const_iterator it = m_wire.elements_begin();
127
128 if (it != m_wire.elements_end() && it->type() == tlv::WhiteIntervalList) {
129 it->parse();
130 Block::element_const_iterator tempIt = it->elements_begin();
131 while (tempIt != it->elements_end() && tempIt->type() == tlv::RepetitiveInterval) {
132 m_whiteIntervalList.insert(RepetitiveInterval(*tempIt));
133 tempIt++;
134 }
135 it++;
136 }
137 else
138 BOOST_THROW_EXCEPTION(tlv::Error("The first element must be WhiteIntervalList"));
139
140 if (it != m_wire.elements_end() && it->type() == tlv::BlackIntervalList) {
141 it->parse();
142 Block::element_const_iterator tempIt = it->elements_begin();
143 while (tempIt != it->elements_end() && tempIt->type() == tlv::RepetitiveInterval) {
144 m_blackIntervalList.insert(RepetitiveInterval(*tempIt));
145 tempIt++;
146 }
147 it++;
148 }
149 else
150 BOOST_THROW_EXCEPTION(tlv::Error("The second element must be BlackIntervalList"));
151}
152
153Schedule&
154Schedule::addWhiteInterval(const RepetitiveInterval& repetitiveInterval)
155{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700156 m_wire.reset();
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700157 m_whiteIntervalList.insert(repetitiveInterval);
158 return *this;
159}
160
161Schedule&
162Schedule::addBlackInterval(const RepetitiveInterval& repetitiveInterval)
163{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700164 m_wire.reset();
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700165 m_blackIntervalList.insert(repetitiveInterval);
166 return *this;
167}
168
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700169std::tuple<bool, Interval>
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800170Schedule::getCoveringInterval(const TimeStamp& ts) const
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700171{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700172 Interval blackPositiveResult(true);
173 Interval whitePositiveResult(true);
174
175 Interval blackNegativeResult;
176 Interval whiteNegativeResult;
177
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700178 // get the blackResult
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800179 calIntervalResult(m_blackIntervalList, ts,
180 blackPositiveResult, blackNegativeResult);
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700181
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800182 // if black positive result is not empty, the result must be false
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700183 if (!blackPositiveResult.isEmpty())
184 return std::make_tuple(false, blackPositiveResult);
185
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700186 // get the whiteResult
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800187 calIntervalResult(m_whiteIntervalList, ts,
188 whitePositiveResult, whiteNegativeResult);
189
190 if (whitePositiveResult.isEmpty() && !whiteNegativeResult.isValid()) {
191 // there is no white interval covering the timestamp
192 // return false and a 24-hour interval
193 return std::make_tuple(false, Interval(TimeStamp(ts.date(), boost::posix_time::hours(0)),
194 TimeStamp(ts.date(), boost::posix_time::hours(24))));
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700195 }
196
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800197 if (!whitePositiveResult.isEmpty()) {
198 // there is white interval covering the timestamp
199 // return ture and calculate the intersection
200 if (blackNegativeResult.isValid())
201 return std::make_tuple(true, whitePositiveResult && blackNegativeResult);
202 else
203 return std::make_tuple(true, whitePositiveResult);
204 }
205 else {
206 // there is no white interval covering the timestamp
207 // return false
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700208 return std::make_tuple(false, whiteNegativeResult);
Zhiyi Zhang2f9efa62015-11-23 19:02:28 +0800209 }
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700210}
211
212} // namespace gep
213} // namespace ndn