blob: 8eef8cce05acdda10356569292b2c746c2d86ef4 [file] [log] [blame]
Junxiao Shibc5030d2014-09-01 11:53:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev5f1820e2017-01-04 18:12:42 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Junxiao Shibc5030d2014-09-01 11:53:12 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "key-locator.hpp"
23#include "encoding/block-helpers.hpp"
Alexander Afanasyev5f1820e2017-01-04 18:12:42 -080024#include "util/string-helper.hpp"
Junxiao Shibc5030d2014-09-01 11:53:12 -070025
26namespace ndn {
27
Junxiao Shic2b8d242014-11-04 08:35:29 -070028BOOST_CONCEPT_ASSERT((boost::EqualityComparable<KeyLocator>));
29BOOST_CONCEPT_ASSERT((WireEncodable<KeyLocator>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070030BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<KeyLocator>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070031BOOST_CONCEPT_ASSERT((WireDecodable<KeyLocator>));
32static_assert(std::is_base_of<tlv::Error, KeyLocator::Error>::value,
33 "KeyLocator::Error must inherit from tlv::Error");
34
Junxiao Shibc5030d2014-09-01 11:53:12 -070035KeyLocator::KeyLocator()
36 : m_type(KeyLocator_None)
37{
38}
39
40KeyLocator::KeyLocator(const Block& wire)
41{
42 wireDecode(wire);
43}
44
45KeyLocator::KeyLocator(const Name& name)
46{
47 setName(name);
48}
49
Alexander Afanasyev74633892015-02-08 18:08:46 -080050template<encoding::Tag TAG>
Junxiao Shibc5030d2014-09-01 11:53:12 -070051size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070052KeyLocator::wireEncode(EncodingImpl<TAG>& encoder) const
Junxiao Shibc5030d2014-09-01 11:53:12 -070053{
54 // KeyLocator ::= KEY-LOCATOR-TYPE TLV-LENGTH (Name | KeyDigest)
55 // KeyDigest ::= KEY-DIGEST-TYPE TLV-LENGTH BYTE+
56
57 size_t totalLength = 0;
58
59 switch (m_type) {
60 case KeyLocator_None:
61 break;
62 case KeyLocator_Name:
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070063 totalLength += m_name.wireEncode(encoder);
Junxiao Shibc5030d2014-09-01 11:53:12 -070064 break;
65 case KeyLocator_KeyDigest:
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070066 totalLength += encoder.prependBlock(m_keyDigest);
Junxiao Shibc5030d2014-09-01 11:53:12 -070067 break;
68 default:
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070069 BOOST_THROW_EXCEPTION(Error("Unsupported KeyLocator type"));
Junxiao Shibc5030d2014-09-01 11:53:12 -070070 }
71
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070072 totalLength += encoder.prependVarNumber(totalLength);
73 totalLength += encoder.prependVarNumber(tlv::KeyLocator);
Junxiao Shibc5030d2014-09-01 11:53:12 -070074 return totalLength;
75}
76
77template size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070078KeyLocator::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
Junxiao Shibc5030d2014-09-01 11:53:12 -070079
80template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080081KeyLocator::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
Junxiao Shibc5030d2014-09-01 11:53:12 -070082
83const Block&
84KeyLocator::wireEncode() const
85{
86 if (m_wire.hasWire())
87 return m_wire;
88
89 EncodingEstimator estimator;
90 size_t estimatedSize = wireEncode(estimator);
91
92 EncodingBuffer buffer(estimatedSize, 0);
93 wireEncode(buffer);
94
95 m_wire = buffer.block();
96 return m_wire;
97}
98
99void
100KeyLocator::wireDecode(const Block& wire)
101{
102 if (wire.type() != tlv::KeyLocator)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700103 BOOST_THROW_EXCEPTION(Error("Unexpected TLV type during KeyLocator decoding"));
Junxiao Shibc5030d2014-09-01 11:53:12 -0700104
105 m_wire = wire;
106 m_wire.parse();
107
108 if (m_wire.elements().empty()) {
109 m_type = KeyLocator_None;
110 return;
111 }
112
113 switch (m_wire.elements_begin()->type()) {
114 case tlv::Name:
115 m_type = KeyLocator_Name;
116 m_name.wireDecode(*m_wire.elements_begin());
117 break;
118 case tlv::KeyDigest:
119 m_type = KeyLocator_KeyDigest;
120 m_keyDigest = *m_wire.elements_begin();
121 break;
122 default:
123 m_type = KeyLocator_Unknown;
124 break;
125 }
126}
127
128KeyLocator&
129KeyLocator::clear()
130{
131 m_wire.reset();
132 m_type = KeyLocator_None;
133 m_name.clear();
134 m_keyDigest.reset();
135 return *this;
136}
137
138const Name&
139KeyLocator::getName() const
140{
141 if (m_type != KeyLocator_Name)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700142 BOOST_THROW_EXCEPTION(Error("KeyLocator type is not Name"));
Junxiao Shibc5030d2014-09-01 11:53:12 -0700143
144 return m_name;
145}
146
147KeyLocator&
148KeyLocator::setName(const Name& name)
149{
150 this->clear();
151 m_type = KeyLocator_Name;
152 m_name = name;
153 return *this;
154}
155
156const Block&
157KeyLocator::getKeyDigest() const
158{
159 if (m_type != KeyLocator_KeyDigest)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700160 BOOST_THROW_EXCEPTION(Error("KeyLocator type is not KeyDigest"));
Junxiao Shibc5030d2014-09-01 11:53:12 -0700161
162 return m_keyDigest;
163}
164
165KeyLocator&
166KeyLocator::setKeyDigest(const Block& keyDigest)
167{
168 if (keyDigest.type() != tlv::KeyDigest)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700169 BOOST_THROW_EXCEPTION(Error("expecting KeyDigest block"));
Junxiao Shibc5030d2014-09-01 11:53:12 -0700170
171 this->clear();
172 m_type = KeyLocator_KeyDigest;
173 m_keyDigest = keyDigest;
174 return *this;
175}
176
177KeyLocator&
178KeyLocator::setKeyDigest(const ConstBufferPtr& keyDigest)
179{
180 // WARNING: ConstBufferPtr is shared_ptr<const Buffer>
181 // This function takes a constant reference of a shared pointer.
182 // It MUST NOT change the reference count of that shared pointer.
183
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700184 return this->setKeyDigest(makeBinaryBlock(tlv::KeyDigest, keyDigest->get(), keyDigest->size()));
Junxiao Shibc5030d2014-09-01 11:53:12 -0700185}
186
187bool
188KeyLocator::operator==(const KeyLocator& other) const
189{
190 return wireEncode() == other.wireEncode();
191}
192
Alexander Afanasyev5f1820e2017-01-04 18:12:42 -0800193std::ostream&
194operator<<(std::ostream& os, const KeyLocator& keyLocator)
195{
196 switch (keyLocator.getType()) {
197 case KeyLocator::KeyLocator_Name: {
198 return os << "Name=" << keyLocator.getName();
199 }
200 case KeyLocator::KeyLocator_KeyDigest: {
201 const size_t MAX_DIGEST_OCTETS_TO_SHOW = 5;
202 const Block& digest = keyLocator.getKeyDigest();
203 os << "KeyDigest=" << toHex(digest.value(), digest.value_size()).substr(0, MAX_DIGEST_OCTETS_TO_SHOW * 2);
204 if (digest.value_size() > MAX_DIGEST_OCTETS_TO_SHOW) {
205 os << "...";
206 }
207 return os;
208 }
209 case KeyLocator::KeyLocator_None: {
210 return os << "None";
211 }
212 case KeyLocator::KeyLocator_Unknown: {
213 return os << "Unknown";
214 }
215 }
216 return os << "Unknown";
217}
218
Junxiao Shibc5030d2014-09-01 11:53:12 -0700219} // namespace ndn