blob: ac25c07b43980b6cc626fc00253c472a49a38e56 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi81206d52017-07-23 12:43:22 +00002/*
Eric Newberrya3c8bd12020-05-15 17:27:07 -07003 * Copyright (c) 2013-2020 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Jeff Thompson5cae5e52013-07-10 19:41:20 -070020 */
21
Davide Pesavento905d40f2020-06-09 21:33:25 -040022#ifndef NDN_CXX_DATA_HPP
23#define NDN_CXX_DATA_HPP
Jeff Thompson5cae5e52013-07-10 19:41:20 -070024
Davide Pesavento14c56cd2020-05-21 01:44:03 -040025#include "ndn-cxx/detail/packet-base.hpp"
26#include "ndn-cxx/encoding/block.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "ndn-cxx/meta-info.hpp"
28#include "ndn-cxx/name.hpp"
Davide Pesavento81bd6962020-06-17 16:03:23 -040029#include "ndn-cxx/signature-info.hpp"
Jeff Thompson5cae5e52013-07-10 19:41:20 -070030
31namespace ndn {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070032
Davide Pesavento81bd6962020-06-17 16:03:23 -040033class Signature;
34
Davide Pesavento905d40f2020-06-09 21:33:25 -040035/** @brief Represents a %Data packet.
36 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/data.html
Junxiao Shic2b8d242014-11-04 08:35:29 -070037 */
Davide Pesavento1fd00242018-05-20 00:11:01 -040038class Data : public PacketBase, public std::enable_shared_from_this<Data>
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080039{
Jeff Thompson5cae5e52013-07-10 19:41:20 -070040public:
Junxiao Shic2b8d242014-11-04 08:35:29 -070041 class Error : public tlv::Error
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070042 {
43 public:
Junxiao Shi68b53852018-07-25 13:56:38 -060044 using tlv::Error::Error;
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070045 };
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070046
Junxiao Shi7d9039b2018-04-14 15:56:28 +000047 /** @brief Construct an unsigned Data packet with given @p name and empty Content.
Davide Pesavento905d40f2020-06-09 21:33:25 -040048 * @warning In certain contexts that use `Data::shared_from_this()`, Data must be created using
49 * `std::make_shared`. Otherwise, `shared_from_this()` may trigger undefined behavior.
50 * One example where this is necessary is storing Data into a subclass of InMemoryStorage.
Jeff Thompson20af0732013-09-12 17:01:45 -070051 */
Junxiao Shi9b845352017-07-24 05:04:56 +000052 explicit
Junxiao Shi81206d52017-07-23 12:43:22 +000053 Data(const Name& name = Name());
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070054
Junxiao Shi7d9039b2018-04-14 15:56:28 +000055 /** @brief Construct a Data packet by decoding from @p wire.
Davide Pesavento905d40f2020-06-09 21:33:25 -040056 * @param wire TLV block of type tlv::Data; may be signed or unsigned.
57 * @warning In certain contexts that use `Data::shared_from_this()`, Data must be created using
58 * `std::make_shared`. Otherwise, `shared_from_this()` may trigger undefined behavior.
59 * One example where this is necessary is storing Data into a subclass of InMemoryStorage.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080060 */
61 explicit
Alexander Afanasyev197e5652014-06-13 16:56:31 -070062 Data(const Block& wire);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070063
Davide Pesavento905d40f2020-06-09 21:33:25 -040064 /** @brief Prepend wire encoding to @p encoder
65 * @param encoder EncodingEstimator or EncodingBuffer instance.
66 * @param wantUnsignedPortionOnly If true, prepend only Name, MetaInfo, Content, and
67 * SignatureInfo to @p encoder, but omit SignatureValue and the outermost TLV
68 * Type and Length of the Data element. This is intended to be used with
69 * wireEncode(EncodingBuffer&, const Block&) const.
70 * @throw Error %Signature is not present and @p wantUnsignedPortionOnly is false.
Jeff Thompsonb7aefa002013-09-16 18:22:00 -070071 */
Alexander Afanasyev74633892015-02-08 18:08:46 -080072 template<encoding::Tag TAG>
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -070073 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070074 wireEncode(EncodingImpl<TAG>& encoder, bool wantUnsignedPortionOnly = false) const;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070075
Junxiao Shi81206d52017-07-23 12:43:22 +000076 /** @brief Finalize Data packet encoding with the specified SignatureValue
77 * @param encoder EncodingBuffer containing Name, MetaInfo, Content, and SignatureInfo, but
Davide Pesavento905d40f2020-06-09 21:33:25 -040078 * without SignatureValue and the outermost Type-Length of the Data element.
79 * @param signatureValue SignatureValue element.
Alexander Afanasyev197e5652014-06-13 16:56:31 -070080 *
Davide Pesavento905d40f2020-06-09 21:33:25 -040081 * This method is intended to be used in concert with `wireEncode(encoder, true)`, e.g.:
Junxiao Shi81206d52017-07-23 12:43:22 +000082 * @code
Alexander Afanasyev197e5652014-06-13 16:56:31 -070083 * Data data;
84 * ...
85 * EncodingBuffer encoder;
86 * data.wireEncode(encoder, true);
87 * ...
88 * Block signatureValue = <sign_over_unsigned_portion>(encoder.buf(), encoder.size());
89 * data.wireEncode(encoder, signatureValue)
Junxiao Shi81206d52017-07-23 12:43:22 +000090 * @endcode
Alexander Afanasyev197e5652014-06-13 16:56:31 -070091 */
92 const Block&
93 wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const;
94
Davide Pesavento905d40f2020-06-09 21:33:25 -040095 /** @brief Encode into a Block.
96 * @pre Data must be signed.
Junxiao Shi81206d52017-07-23 12:43:22 +000097 */
98 const Block&
99 wireEncode() const;
100
Davide Pesavento905d40f2020-06-09 21:33:25 -0400101 /** @brief Decode from @p wire.
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800102 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700103 void
104 wireDecode(const Block& wire);
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800105
Junxiao Shi7d9039b2018-04-14 15:56:28 +0000106 /** @brief Check if this instance has cached wire encoding.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800107 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700108 bool
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400109 hasWire() const noexcept
Junxiao Shi81206d52017-07-23 12:43:22 +0000110 {
111 return m_wire.hasWire();
112 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700113
Junxiao Shi81206d52017-07-23 12:43:22 +0000114 /** @brief Get full name including implicit digest
115 * @pre hasWire() == true; i.e. wireEncode() must have been called
116 * @throw Error Data has no wire encoding
Alexander Afanasyev3b703102014-06-13 17:01:14 -0700117 */
118 const Name&
119 getFullName() const;
120
Junxiao Shi81206d52017-07-23 12:43:22 +0000121public: // Data fields
122 /** @brief Get name
123 */
124 const Name&
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400125 getName() const noexcept
Junxiao Shi81206d52017-07-23 12:43:22 +0000126 {
127 return m_name;
128 }
129
130 /** @brief Set name
131 * @return a reference to this Data, to allow chaining
132 */
133 Data&
134 setName(const Name& name);
135
136 /** @brief Get MetaInfo
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700137 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700138 const MetaInfo&
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400139 getMetaInfo() const noexcept
Junxiao Shi81206d52017-07-23 12:43:22 +0000140 {
141 return m_metaInfo;
142 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700143
Junxiao Shi81206d52017-07-23 12:43:22 +0000144 /** @brief Set MetaInfo
145 * @return a reference to this Data, to allow chaining
Jeff Thompson0cd8c4a2013-09-13 17:46:40 -0700146 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700147 Data&
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800148 setMetaInfo(const MetaInfo& metaInfo);
Jeff Thompson46bd45f2013-08-08 16:46:41 -0700149
Davide Pesavento81bd6962020-06-17 16:03:23 -0400150 /**
151 * @brief Return whether this Data has a Content element
152 */
153 bool
154 hasContent() const noexcept
155 {
156 return m_content.isValid();
157 }
158
159 /**
160 * @brief Get the Content element
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800161 *
Davide Pesavento81bd6962020-06-17 16:03:23 -0400162 * If the element is not present (hasContent() == false), an invalid Block will be returned.
163 *
164 * The value of the returned Content Block (if valid) can be accessed through
165 * Block::value() / Block::value_size() or Block::value_begin() / Block::value_end().
166 *
167 * @sa hasContent()
168 * @sa Block::blockFromValue(), Block::parse()
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800169 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700170 const Block&
Davide Pesavento81bd6962020-06-17 16:03:23 -0400171 getContent() const noexcept
172 {
173 return m_content;
174 }
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800175
Davide Pesavento81bd6962020-06-17 16:03:23 -0400176 /**
177 * @brief Set Content from a Block
178 * @param block TLV block to be used as Content; must be valid
179 * @return a reference to this Data, to allow chaining
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700180 *
Davide Pesavento81bd6962020-06-17 16:03:23 -0400181 * If the block's TLV-TYPE is tlv::Content, it will be used directly as this Data's
182 * Content element. Otherwise, the block will be nested into a Content element.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700183 */
184 Data&
185 setContent(const Block& block);
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800186
Davide Pesavento81bd6962020-06-17 16:03:23 -0400187 /**
188 * @brief Set Content by copying from a raw buffer
189 * @param value buffer with the TLV-VALUE of the content; may be nullptr if @p length is zero
190 * @param length size of the buffer
191 * @return a reference to this Data, to allow chaining
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700192 */
193 Data&
Davide Pesavento81bd6962020-06-17 16:03:23 -0400194 setContent(const uint8_t* value, size_t length);
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800195
Davide Pesavento81bd6962020-06-17 16:03:23 -0400196 /**
197 * @brief Set Content from a shared buffer
198 * @param value buffer with the TLV-VALUE of the content; must not be nullptr
199 * @return a reference to this Data, to allow chaining
Junxiao Shi81206d52017-07-23 12:43:22 +0000200 */
201 Data&
Davide Pesavento3b101d02018-07-21 22:44:09 -0400202 setContent(ConstBufferPtr value);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700203
Davide Pesavento81bd6962020-06-17 16:03:23 -0400204 /**
205 * @brief Remove the Content element
206 * @return a reference to this Data, to allow chaining
207 * @post hasContent() == false
208 */
209 Data&
210 unsetContent();
211
Junxiao Shi81206d52017-07-23 12:43:22 +0000212 /** @brief Get Signature
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700213 * @deprecated Use getSignatureInfo and getSignatureValue
Junxiao Shi81206d52017-07-23 12:43:22 +0000214 */
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700215 [[deprecated("use getSignatureInfo and getSignatureValue")]]
216 Signature
217 getSignature() const;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700218
Junxiao Shi81206d52017-07-23 12:43:22 +0000219 /** @brief Set Signature
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700220 * @deprecated Use setSignatureInfo and setSignatureValue
Junxiao Shi81206d52017-07-23 12:43:22 +0000221 * @return a reference to this Data, to allow chaining
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800222 */
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700223 [[deprecated("use setSignatureInfo and setSignatureValue")]]
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700224 Data&
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800225 setSignature(const Signature& signature);
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700226
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700227 /** @brief Get SignatureInfo
228 */
229 const SignatureInfo&
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400230 getSignatureInfo() const noexcept
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700231 {
232 return m_signatureInfo;
233 }
234
235 /** @brief Set SignatureInfo
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400236 *
237 * This is a low-level function that should not normally be called directly by applications.
238 * Instead, provide a SignatureInfo to the SigningInfo object passed to KeyChain::sign().
239 *
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700240 * @return a reference to this Data, to allow chaining
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400241 * @warning SignatureInfo is overwritten when the packet is signed via KeyChain::sign().
242 * @sa SigningInfo
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700243 */
244 Data&
245 setSignatureInfo(const SignatureInfo& info);
246
247 /** @brief Get SignatureValue
248 */
249 const Block&
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400250 getSignatureValue() const noexcept
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700251 {
252 return m_signatureValue;
253 }
254
Junxiao Shi81206d52017-07-23 12:43:22 +0000255 /** @brief Set SignatureValue
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400256 * @param value buffer containing the TLV-VALUE of the SignatureValue; must not be nullptr
257 *
258 * This is a low-level function that should not normally be called directly by applications.
259 * Instead, use KeyChain::sign() to sign the packet.
260 *
Junxiao Shi81206d52017-07-23 12:43:22 +0000261 * @return a reference to this Data, to allow chaining
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400262 * @warning SignatureValue is overwritten when the packet is signed via KeyChain::sign().
Junxiao Shi81206d52017-07-23 12:43:22 +0000263 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700264 Data&
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400265 setSignatureValue(ConstBufferPtr value);
Yingdi Yua4e57672014-02-06 11:16:17 -0800266
Junxiao Shi81206d52017-07-23 12:43:22 +0000267public: // MetaInfo fields
268 uint32_t
269 getContentType() const
270 {
271 return m_metaInfo.getType();
272 }
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700273
Junxiao Shi81206d52017-07-23 12:43:22 +0000274 Data&
275 setContentType(uint32_t type);
276
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000277 time::milliseconds
Junxiao Shi81206d52017-07-23 12:43:22 +0000278 getFreshnessPeriod() const
279 {
280 return m_metaInfo.getFreshnessPeriod();
281 }
282
283 Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000284 setFreshnessPeriod(time::milliseconds freshnessPeriod);
Junxiao Shi81206d52017-07-23 12:43:22 +0000285
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000286 const optional<name::Component>&
287 getFinalBlock() const
Junxiao Shi81206d52017-07-23 12:43:22 +0000288 {
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000289 return m_metaInfo.getFinalBlock();
Junxiao Shi81206d52017-07-23 12:43:22 +0000290 }
291
292 Data&
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000293 setFinalBlock(optional<name::Component> finalBlockId);
294
Davide Pesavento14c56cd2020-05-21 01:44:03 -0400295public: // SignatureInfo fields
296 /** @brief Get SignatureType
297 * @return tlv::SignatureTypeValue, or -1 to indicate the signature is invalid
298 */
299 int32_t
300 getSignatureType() const noexcept
301 {
302 return m_signatureInfo.getSignatureType();
303 }
304
305 /** @brief Get KeyLocator
306 */
307 optional<KeyLocator>
308 getKeyLocator() const noexcept
309 {
310 return m_signatureInfo.hasKeyLocator() ? make_optional(m_signatureInfo.getKeyLocator()) : nullopt;
311 }
312
Spyridon Mastorakis3b54e852015-04-07 08:03:25 -0700313protected:
Junxiao Shi81206d52017-07-23 12:43:22 +0000314 /** @brief Clear wire encoding and cached FullName
315 * @note This does not clear the SignatureValue.
Jeff Thompsonb7aefa002013-09-16 18:22:00 -0700316 */
Alexander Afanasyevff2d08f2014-04-07 18:28:25 -0700317 void
Junxiao Shi81206d52017-07-23 12:43:22 +0000318 resetWire();
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800319
320private:
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800321 Name m_name;
322 MetaInfo m_metaInfo;
Junxiao Shi81206d52017-07-23 12:43:22 +0000323 Block m_content;
Eric Newberrya3c8bd12020-05-15 17:27:07 -0700324 SignatureInfo m_signatureInfo;
325 Block m_signatureValue;
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800326
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800327 mutable Block m_wire;
Junxiao Shi81206d52017-07-23 12:43:22 +0000328 mutable Name m_fullName; ///< cached FullName computed from m_wire
Jeff Thompson5cae5e52013-07-10 19:41:20 -0700329};
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800330
Davide Pesavento88a0d812017-08-19 21:31:42 -0400331#ifndef DOXYGEN
332extern template size_t
333Data::wireEncode<encoding::EncoderTag>(EncodingBuffer&, bool) const;
334
335extern template size_t
336Data::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, bool) const;
337#endif
338
Alexander Afanasyeva0c5f832014-06-19 13:27:56 -0700339std::ostream&
340operator<<(std::ostream& os, const Data& data);
Alexander Afanasyev809805d2014-02-17 17:20:33 -0800341
Junxiao Shi81206d52017-07-23 12:43:22 +0000342bool
343operator==(const Data& lhs, const Data& rhs);
344
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800345inline bool
Junxiao Shi81206d52017-07-23 12:43:22 +0000346operator!=(const Data& lhs, const Data& rhs)
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800347{
Junxiao Shi81206d52017-07-23 12:43:22 +0000348 return !(lhs == rhs);
Alexander Afanasyev2ba8f662014-01-05 22:53:18 -0800349}
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700350
Alexander Afanasyevfadc97d2014-01-03 13:22:10 -0800351} // namespace ndn
352
Davide Pesavento905d40f2020-06-09 21:33:25 -0400353#endif // NDN_CXX_DATA_HPP