blob: ac68bdd90fe6795c45780eda4fabe7e576a56eb5 [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
31BOOST_CONCEPT_ASSERT((WireEncodable<Schedule>));
32BOOST_CONCEPT_ASSERT((WireDecodable<Schedule>));
33
34Schedule::Schedule() = default;
35
36Schedule::Schedule(const Block& block)
37{
38 wireDecode(block);
39}
40
41template<encoding::Tag TAG>
42size_t
43Schedule::wireEncode(EncodingImpl<TAG>& encoder) const
44{
45 size_t totalLength = 0;
46 size_t blackLength = 0;
47 size_t whiteLength = 0;
48
49 // encode the blackIntervalList as an embed TLV structure
50 for (const RepetitiveInterval& element : m_blackIntervalList) {
51 blackLength += encoder.prependBlock(element.wireEncode());
52 }
53 blackLength += encoder.prependVarNumber(blackLength);
54 blackLength += encoder.prependVarNumber(tlv::BlackIntervalList);
55
56 // encode the whiteIntervalList as an embed TLV structure
57 for (const RepetitiveInterval& element : m_whiteIntervalList) {
58 whiteLength += encoder.prependBlock(element.wireEncode());
59 }
60 whiteLength += encoder.prependVarNumber(whiteLength);
61 whiteLength += encoder.prependVarNumber(tlv::WhiteIntervalList);
62
63 totalLength = whiteLength + blackLength;
64 totalLength += encoder.prependVarNumber(totalLength);
65 totalLength += encoder.prependVarNumber(tlv::Schedule);
66
67 return totalLength;
68}
69
70const Block&
71Schedule::wireEncode() const
72{
73 if (m_wire.hasWire())
74 return m_wire;
75
76 EncodingEstimator estimator;
77 size_t estimatedSize = wireEncode(estimator);
78
79 EncodingBuffer buffer(estimatedSize, 0);
80 wireEncode(buffer);
81
82 this->m_wire = buffer.block();
83 return m_wire;
84}
85
86void
87Schedule::wireDecode(const Block& wire)
88{
89 if (wire.type() != tlv::Schedule)
90 BOOST_THROW_EXCEPTION(tlv::Error("Unexpected TLV type when decoding RepetitiveInterval"));
91
92 m_wire = wire;
93 m_wire.parse();
94
95 if (m_wire.elements_size() != 2)
96 BOOST_THROW_EXCEPTION(tlv::Error("RepetitiveInterval tlv does not have two sub-TLVs"));
97
98 Block::element_const_iterator it = m_wire.elements_begin();
99
100 if (it != m_wire.elements_end() && it->type() == tlv::WhiteIntervalList) {
101 it->parse();
102 Block::element_const_iterator tempIt = it->elements_begin();
103 while (tempIt != it->elements_end() && tempIt->type() == tlv::RepetitiveInterval) {
104 m_whiteIntervalList.insert(RepetitiveInterval(*tempIt));
105 tempIt++;
106 }
107 it++;
108 }
109 else
110 BOOST_THROW_EXCEPTION(tlv::Error("The first element must be WhiteIntervalList"));
111
112 if (it != m_wire.elements_end() && it->type() == tlv::BlackIntervalList) {
113 it->parse();
114 Block::element_const_iterator tempIt = it->elements_begin();
115 while (tempIt != it->elements_end() && tempIt->type() == tlv::RepetitiveInterval) {
116 m_blackIntervalList.insert(RepetitiveInterval(*tempIt));
117 tempIt++;
118 }
119 it++;
120 }
121 else
122 BOOST_THROW_EXCEPTION(tlv::Error("The second element must be BlackIntervalList"));
123}
124
125Schedule&
126Schedule::addWhiteInterval(const RepetitiveInterval& repetitiveInterval)
127{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700128 m_wire.reset();
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700129 m_whiteIntervalList.insert(repetitiveInterval);
130 return *this;
131}
132
133Schedule&
134Schedule::addBlackInterval(const RepetitiveInterval& repetitiveInterval)
135{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700136 m_wire.reset();
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700137 m_blackIntervalList.insert(repetitiveInterval);
138 return *this;
139}
140
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700141std::tuple<bool, Interval>
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700142Schedule::getCoveringInterval(const TimeStamp& tp) const
143{
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700144 Interval blackPositiveResult(true);
145 Interval whitePositiveResult(true);
146
147 Interval blackNegativeResult;
148 Interval whiteNegativeResult;
149
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700150 Interval tempInterval;
151 bool isPositive;
152
153 // get the blackResult
154 for (const RepetitiveInterval& element : m_blackIntervalList) {
155 std::tie(isPositive, tempInterval) = element.getInterval(tp);
156 if (isPositive == true) {
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700157 // tempInterval is covering the time stamp, || to the black negative result
158 // get the union interval of all the black interval covering the timestamp
159 // return false and the union interval
160 blackPositiveResult || tempInterval;
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700161 }
162 else {
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700163 // tempInterval is not covering the time stamp, && to the black positive result
164 // get the intersection interval of all the black interval not covering the timestamp
165 // return true if white positive result is not empty, false if white positive result is empty
166 if (!blackNegativeResult.isValid())
167 blackNegativeResult = tempInterval;
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700168 else
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700169 blackNegativeResult && tempInterval;
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700170 }
171 }
172
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700173 // if black positive result is not full, the result must be false
174 if (!blackPositiveResult.isEmpty())
175 return std::make_tuple(false, blackPositiveResult);
176
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700177 // get the whiteResult
178 for (const RepetitiveInterval& element : m_whiteIntervalList) {
179 std::tie(isPositive, tempInterval) = element.getInterval(tp);
180 if (isPositive == true) {
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700181 // tempInterval is covering the time stamp, || to the white positive result
182 // get the union interval of all the white interval covering the timestamp
183 // return true
184 whitePositiveResult || tempInterval;
185 }
186 else {
187 // tempInterval is not covering the time, && to the white negative result
188 // get the intersection of all the white interval not covering the timestamp
189 // return false if positive result is empty, return true if positive result is not empty
190 if (!whiteNegativeResult.isValid())
191 whiteNegativeResult = tempInterval;
192 else
193 whiteNegativeResult && tempInterval;
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700194 }
195 }
196
Zhiyi Zhang7cc09fc2015-09-01 13:40:32 -0700197 // return false if positive result is empty, return true if positive result is not empty
198 if (!whitePositiveResult.isEmpty())
199 return std::make_tuple(true, whitePositiveResult && blackNegativeResult);
200 else
201 return std::make_tuple(false, whiteNegativeResult);
Zhiyi Zhangcea58d52015-08-26 10:19:56 -0700202}
203
204} // namespace gep
205} // namespace ndn