blob: e625e06741f0049801f8dc8bb8012a55dac451de [file] [log] [blame]
Alexander Afanasyev1043c702013-07-15 16:21:09 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2011 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
22#include "../ccnb.h"
23
24#include "wire-ccnb.h"
25
26#include "ns3/log.h"
27
28#include "ccnb-parser/common.h"
29#include "ccnb-parser/visitors/void-depth-first-visitor.h"
30#include "ccnb-parser/visitors/name-visitor.h"
31#include "ccnb-parser/visitors/non-negative-integer-visitor.h"
32#include "ccnb-parser/visitors/timestamp-visitor.h"
33#include "ccnb-parser/visitors/string-visitor.h"
34#include "ccnb-parser/visitors/uint32t-blob-visitor.h"
35#include "ccnb-parser/visitors/content-type-visitor.h"
36
37#include "ccnb-parser/syntax-tree/block.h"
38#include "ccnb-parser/syntax-tree/dtag.h"
39
40#include <boost/foreach.hpp>
41
42NS_LOG_COMPONENT_DEFINE ("ndn.wire.Ccnb.Data");
43
44NDN_NAMESPACE_BEGIN
45
46namespace wire {
47namespace ccnb {
48
49// const std::string DefaultDigestAlgorithm = "2.16.840.1.101.3.4.2.1";
50
51class DataTrailer : public Trailer
52{
53public:
54 DataTrailer ()
55 {
56 }
57
58 static TypeId GetTypeId ()
59 {
60 static TypeId tid = TypeId ("ns3::ndn::Data::Ccnb::Closer")
61 .SetGroupName ("Ndn")
62 .SetParent<Trailer> ()
63 .AddConstructor<DataTrailer> ()
64 ;
65 return tid;
66 }
67
68 virtual TypeId GetInstanceTypeId (void) const
69 {
70 return GetTypeId ();
71 }
72
73 virtual void Print (std::ostream &os) const
74 {
75 }
76
77 virtual uint32_t GetSerializedSize (void) const
78 {
79 return 2;
80 }
81
82 virtual void Serialize (Buffer::Iterator end) const
83 {
84 Buffer::Iterator i = end;
85 i.Prev (2); // Trailer interface requires us to go backwards
86
87 i.WriteU8 (0x00); // </Content>
88 i.WriteU8 (0x00); // </ContentObject>
89 }
90
91 virtual uint32_t Deserialize (Buffer::Iterator end)
92 {
93 Buffer::Iterator i = end;
94 i.Prev (2); // Trailer interface requires us to go backwards
95
96 uint8_t closing_tag_content = i.ReadU8 ();
97 NS_ASSERT_MSG (closing_tag_content==0, "Should be a closing tag </Content> (0x00)");
98
99 uint8_t closing_tag_content_object = i.ReadU8 ();
100 NS_ASSERT_MSG (closing_tag_content_object==0, "Should be a closing tag </ContentObject> (0x00)");
101
102 return 2;
103 }
104};
105
106NS_OBJECT_ENSURE_REGISTERED (Data);
107NS_OBJECT_ENSURE_REGISTERED (DataTrailer);
108
109TypeId
110Data::GetTypeId (void)
111{
112 static TypeId tid = TypeId ("ns3::ndn::Data::Ccnb")
113 .SetGroupName ("Ndn")
114 .SetParent<Header> ()
115 .AddConstructor<Data> ()
116 ;
117 return tid;
118}
119
120TypeId
121Data::GetInstanceTypeId (void) const
122{
123 return GetTypeId ();
124}
125
126Data::Data ()
127 : m_data (Create<ndn::ContentObject> ())
128{
129}
130
131Data::Data (Ptr<ndn::ContentObject> data)
132 : m_data (data)
133{
134}
135
136Ptr<ndn::ContentObject>
137Data::GetData ()
138{
139 return m_data;
140}
141
142Ptr<Packet>
143Data::ToWire (Ptr<const ndn::ContentObject> data)
144{
145 static DataTrailer trailer;
146
147 Ptr<const Packet> p = data->GetWire ();
148 if (!p)
149 {
150 Ptr<Packet> packet = Create<Packet> (*data->GetPayload ());
151 Data wireEncoding (ConstCast<ndn::ContentObject> (data));
152 packet->AddHeader (wireEncoding);
153 packet->AddTrailer (trailer);
154 data->SetWire (packet);
155
156 p = packet;
157 }
158
159 return p->Copy ();
160}
161
162Ptr<ndn::ContentObject>
163Data::FromWire (Ptr<Packet> packet)
164{
165 static DataTrailer trailer;
166
167 Ptr<ndn::ContentObject> data = Create<ndn::ContentObject> ();
168 data->SetWire (packet->Copy ());
169
170 Data wireEncoding (data);
171 packet->RemoveHeader (wireEncoding);
172 packet->RemoveTrailer (trailer);
173
174 data->SetPayload (packet);
175
176 return data;
177}
178
179void
180Data::Serialize (Buffer::Iterator start) const
181{
182 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_ContentObject, CcnbParser::CCN_DTAG); // <ContentObject>
183
184 // fake signature
185 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_Signature, CcnbParser::CCN_DTAG); // <Signature>
186 // Signature ::= √DigestAlgorithm?
187 // Witness?
188 // √SignatureBits
189 // if (GetSignature ().GetDigestAlgorithm () != Signature::DefaultDigestAlgorithm)
190 // {
191 // Ccnb::AppendString (start, CcnbParser::CCN_DTAG_DigestAlgorithm, GetSignature ().GetDigestAlgorithm ());
192 // }
193 Ccnb::AppendTaggedBlob (start, CcnbParser::CCN_DTAG_SignatureBits, m_data->GetSignature ()); // <SignatureBits />
194 Ccnb::AppendCloser (start); // </Signature>
195
196 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_Name, CcnbParser::CCN_DTAG); // <Name>
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700197 Ccnb::SerializeName (start, m_data->GetName()); // <Component>...</Component>...
198 Ccnb::AppendCloser (start); // </Name>
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700199
200 // fake signature
201 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_SignedInfo, CcnbParser::CCN_DTAG); // <SignedInfo>
202 // SignedInfo ::= √PublisherPublicKeyDigest
203 // √Timestamp
204 // √Type?
205 // √FreshnessSeconds?
206 // FinalBlockID?
207 // KeyLocator?
208 // Ccnb::AppendTaggedBlob (start, CcnbParser::CCN_DTAG_PublisherPublicKeyDigest, // <PublisherPublicKeyDigest>...
209 // GetSignedInfo ().GetPublisherPublicKeyDigest ());
210
211 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_Timestamp, CcnbParser::CCN_DTAG); // <Timestamp>...
212 Ccnb::AppendTimestampBlob (start, m_data->GetTimestamp ());
213 Ccnb::AppendCloser (start);
214
215 // if (GetSignedInfo ().GetContentType () != DATA)
216 // {
217 // uint8_t type[3];
218 // type[0] = (GetSignedInfo ().GetContentType () >> 16) & 0xFF;
219 // type[1] = (GetSignedInfo ().GetContentType () >> 8 ) & 0xFF;
220 // type[2] = (GetSignedInfo ().GetContentType () ) & 0xFF;
221
222 // Ccnb::AppendTaggedBlob (start, CCN_DTAG_Type, type, 3);
223 // }
224 if (m_data->GetFreshness () > Seconds(0))
225 {
226 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_FreshnessSeconds, CcnbParser::CCN_DTAG);
227 Ccnb::AppendNumber (start, m_data->GetFreshness ().ToInteger (Time::S));
228 Ccnb::AppendCloser (start);
229 }
230 if (m_data->GetKeyLocator () != 0)
231 {
232 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_KeyLocator, CcnbParser::CCN_DTAG); // <KeyLocator>
233 {
234 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_KeyName, CcnbParser::CCN_DTAG); // <KeyName>
235 {
236 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_Name, CcnbParser::CCN_DTAG); // <Name>
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700237 Ccnb::SerializeName (start, *m_data->GetKeyLocator ()); // <Component>...</Component>...
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700238 Ccnb::AppendCloser (start); // </Name>
239 }
240 Ccnb::AppendCloser (start); // </KeyName>
241 }
242 Ccnb::AppendCloser (start); // </KeyLocator>
243 }
244
245 Ccnb::AppendCloser (start); // </SignedInfo>
246
247 Ccnb::AppendBlockHeader (start, CcnbParser::CCN_DTAG_Content, CcnbParser::CCN_DTAG); // <Content>
248
Alexander Afanasyevb4bf3ef2013-07-30 10:40:55 -0700249 uint32_t payloadSize = m_data->GetPayload ()->GetSize ();
250 if (payloadSize > 0)
251 Ccnb::AppendBlockHeader (start, payloadSize, CcnbParser::CCN_BLOB);
252
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700253 // there are no closing tags !!!
254 // The closing tag is handled by ContentObjectTail
255}
256
257uint32_t
258Data::GetSerializedSize () const
259{
260 size_t written = 0;
261 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_ContentObject); // <ContentObject>
262
263 // fake signature
264 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_Signature); // <Signature>
265 // Signature ::= DigestAlgorithm?
266 // Witness?
267 // SignatureBits
268 // if (GetSignature ().GetDigestAlgorithm () != Signature::DefaultDigestAlgorithm)
269 // {
270 // written += Ccnb::EstimateString (CcnbParser::CCN_DTAG_DigestAlgorithm, GetSignature ().GetDigestAlgorithm ());
271 // }
272 written += Ccnb::EstimateTaggedBlob (CcnbParser::CCN_DTAG_SignatureBits,
273 sizeof (m_data->GetSignature ())); // <SignatureBits />
274 written += 1; // </Signature>
275
276 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_Name); // <Name>
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700277 written += Ccnb::SerializedSizeName (m_data->GetName ()); // <Component>...</Component>...
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700278 written += 1; // </Name>
279
280 // fake signature
281 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_SignedInfo); // <SignedInfo>
282 // SignedInfo ::= √PublisherPublicKeyDigest
283 // √Timestamp
284 // √Type?
285 // √FreshnessSeconds?
286 // FinalBlockID?
287 // KeyLocator?
288
289 // written += Ccnb::EstimateTaggedBlob (CCN_DTAG_PublisherPublicKeyDigest, // <PublisherPublicKeyDigest>...
290 // sizeof (GetSignedInfo ().GetPublisherPublicKeyDigest ()));
291
292 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_Timestamp); // <Timestamp>...
293 written += Ccnb::EstimateTimestampBlob (m_data->GetTimestamp ());
294 written += 1;
295
296 // if (GetSignedInfo ().GetContentType () != DATA)
297 // {
298 // written += Ccnb::EstimateTaggedBlob (CcnbParser::CCN_DTAG_Type, 3);
299 // }
300 if (m_data->GetFreshness () > Seconds(0))
301 {
302 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_FreshnessSeconds);
303 written += Ccnb::EstimateNumber (m_data->GetFreshness ().ToInteger (Time::S));
304 written += 1;
305 }
306
307 if (m_data->GetKeyLocator () != 0)
308 {
309 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_KeyLocator); // <KeyLocator>
310 {
311 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_KeyName); // <KeyName>
312 {
313 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_Name); // <Name>
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700314 written += Ccnb::SerializedSizeName (*m_data->GetKeyLocator ()); // <Component>...</Component>...
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700315 written += 1; // </Name>
316 }
317 written += 1; // </KeyName>
318 }
319 written += 1; // </KeyLocator>
320 }
321
322 written += 1; // </SignedInfo>
323
324 written += Ccnb::EstimateBlockHeader (CcnbParser::CCN_DTAG_Content); // <Content>
325
Alexander Afanasyevb4bf3ef2013-07-30 10:40:55 -0700326 uint32_t payloadSize = m_data->GetPayload ()->GetSize ();
327 if (payloadSize > 0)
328 written += Ccnb::EstimateBlockHeader (payloadSize);
329
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700330 // there are no closing tags !!!
331 // The closing tag is handled by ContentObjectTail
332 return written;
333}
334
335class ContentObjectVisitor : public CcnbParser::VoidDepthFirstVisitor
336{
337public:
338 virtual void visit (CcnbParser::Dtag &n, boost::any param/*should be ContentObject* */)
339 {
340 // uint32_t n.m_dtag;
341 // std::list< Ptr<CcnbParser::Block> > n.m_nestedBlocks;
342 static CcnbParser::NameVisitor nameVisitor;
343 static CcnbParser::NonNegativeIntegerVisitor nonNegativeIntegerVisitor;
344 static CcnbParser::TimestampVisitor timestampVisitor;
345 static CcnbParser::StringVisitor stringVisitor;
346 static CcnbParser::Uint32tBlobVisitor uint32tBlobVisitor;
347 static CcnbParser::ContentTypeVisitor contentTypeVisitor;
348
349 ndn::ContentObject &contentObject = *(boost::any_cast<ndn::ContentObject*> (param));
350
351 switch (n.m_dtag)
352 {
353 case CcnbParser::CCN_DTAG_ContentObject:
354 // process nested blocks
355 BOOST_FOREACH (Ptr<CcnbParser::Block> block, n.m_nestedTags)
356 {
357 block->accept (*this, param);
358 }
359 break;
360 case CcnbParser::CCN_DTAG_Name:
361 {
362 // process name components
363 Ptr<Name> name = Create<Name> ();
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700364 n.accept (nameVisitor, GetPointer (name));
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700365 contentObject.SetName (name);
366 break;
367 }
368
369 case CcnbParser::CCN_DTAG_Signature:
370 // process nested blocks
371 BOOST_FOREACH (Ptr<CcnbParser::Block> block, n.m_nestedTags)
372 {
373 block->accept (*this, param);
374 }
375 break;
376
377 // case CCN_DTAG_DigestAlgorithm:
378 // NS_LOG_DEBUG ("DigestAlgorithm");
379 // if (n.m_nestedTags.size ()!=1) // should be exactly one UDATA inside this tag
380 // throw CcnbParser::CcnbDecodingException ();
381
382 // contentObject.GetSignature ().SetDigestAlgorithm
383 // (boost::any_cast<std::string> ((*n.m_nestedTags.begin())->accept
384 // (stringVisitor)));
385 // break;
386
387 case CcnbParser::CCN_DTAG_SignatureBits:
388 NS_LOG_DEBUG ("SignatureBits");
389 if (n.m_nestedTags.size ()!=1) // should be only one nested tag
390 throw CcnbParser::CcnbDecodingException ();
391
392 contentObject.SetSignature
393 (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept
394 (uint32tBlobVisitor)));
395 break;
396
397 case CcnbParser::CCN_DTAG_SignedInfo:
398 // process nested blocks
399 BOOST_FOREACH (Ptr<CcnbParser::Block> block, n.m_nestedTags)
400 {
401 block->accept (*this, param);
402 }
403 break;
404
405 // case CCN_DTAG_PublisherPublicKeyDigest:
406 // NS_LOG_DEBUG ("PublisherPublicKeyDigest");
407 // if (n.m_nestedTags.size ()!=1) // should be only one nested tag
408 // throw CcnbParser::CcnbDecodingException ();
409
410 // contentObject.GetSignedInfo ().SetPublisherPublicKeyDigest
411 // (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept
412 // (uint32tBlobVisitor)));
413 // break;
414
415 case CcnbParser::CCN_DTAG_Timestamp:
416 NS_LOG_DEBUG ("Timestamp");
417 if (n.m_nestedTags.size()!=1) // should be exactly one nested tag
418 throw CcnbParser::CcnbDecodingException ();
419
420 contentObject.SetTimestamp
421 (boost::any_cast<Time> ((*n.m_nestedTags.begin())->accept
422 (timestampVisitor)));
423 break;
424
425 // case CCN_DTAG_Type:
426 // NS_LOG_DEBUG ("Type");
427 // if (n.m_nestedTags.size ()!=1) // should be only one nested tag
428 // throw CcnbParser::CcnbDecodingException ();
429
430 // contentObject.GetSignedInfo ().SetContentType
431 // (static_cast<Data::ContentType>
432 // (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept
433 // (contentTypeVisitor))));
434 // break;
435
436 case CcnbParser::CCN_DTAG_FreshnessSeconds:
437 NS_LOG_DEBUG ("FreshnessSeconds");
438
439 if (n.m_nestedTags.size()!=1) // should be exactly one nested tag
440 throw CcnbParser::CcnbDecodingException ();
441
442 contentObject.SetFreshness
443 (Seconds
444 (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept
445 (nonNegativeIntegerVisitor))));
446 break;
447
448 case CcnbParser::CCN_DTAG_KeyLocator:
449 // process nested blocks
450 BOOST_FOREACH (Ptr<CcnbParser::Block> block, n.m_nestedTags)
451 {
452 block->accept (*this, param);
453 }
454 break;
455
456 case CcnbParser::CCN_DTAG_KeyName:
457 {
458 if (n.m_nestedTags.size ()!=1) // should be exactly one nested tag
459 throw CcnbParser::CcnbDecodingException ();
460
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700461 // process name components
462 Ptr<Name> name = Create<Name> ();
Alexander Afanasyeva89bc102013-07-16 10:17:31 -0700463 n.accept (nameVisitor, GetPointer (name));
Alexander Afanasyev1043c702013-07-15 16:21:09 -0700464 contentObject.SetKeyLocator (name);
465 break;
466 }
467
468 case CcnbParser::CCN_DTAG_Content: // !!! HACK
469 // This hack was necessary for memory optimizations (i.e., content is virtual payload)
470 NS_ASSERT_MSG (n.m_nestedTags.size() == 0, "Parser should have stopped just after processing <Content> tag");
471 break;
472
473 default: // ignore all other stuff
474 break;
475 }
476 }
477};
478
479uint32_t
480Data::Deserialize (Buffer::Iterator start)
481{
482 static ContentObjectVisitor contentObjectVisitor;
483
484 Buffer::Iterator i = start;
485 Ptr<CcnbParser::Block> root = CcnbParser::Block::ParseBlock (i);
486 root->accept (contentObjectVisitor, GetPointer (m_data));
487
488 return i.GetDistanceFrom (start);
489}
490
491void
492Data::Print (std::ostream &os) const
493{
494 os << "D: " << m_data->GetName ();
495 // os << "<ContentObject><Name>" << GetName () << "</Name><Content>";
496}
497
498} // ccnb
499} // wire
500
501NDN_NAMESPACE_END