| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ |
| /* |
| * Copyright (c) 2011 University of California, Los Angeles |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation; |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| * Author: Ilya Moiseenko <iliamo@cs.ucla.edu> |
| * Alexander Afanasyev <alexander.afanasyev@ucla.edu> |
| */ |
| |
| #include "ccnx-content-object-header.h" |
| |
| #include "ns3/log.h" |
| #include "../helper/ccnx-encoding-helper.h" |
| #include "../helper/ccnx-decoding-helper.h" |
| |
| #include "../helper/ccnb-parser/ccnb-parser-common.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-void-depth-first-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-name-components-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-non-negative-integer-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-timestamp-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-string-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-uint32t-blob-visitor.h" |
| #include "../helper/ccnb-parser/visitors/ccnb-parser-content-type-visitor.h" |
| |
| #include "../helper/ccnb-parser/syntax-tree/ccnb-parser-block.h" |
| #include "../helper/ccnb-parser/syntax-tree/ccnb-parser-dtag.h" |
| |
| #include <boost/foreach.hpp> |
| |
| NS_LOG_COMPONENT_DEFINE ("CcnxContentObjectHeader"); |
| |
| using namespace ns3::CcnbParser; |
| |
| namespace ns3 |
| { |
| |
| const std::string CcnxContentObjectHeader::Signature::DefaultDigestAlgorithm = "2.16.840.1.101.3.4.2.1"; |
| |
| NS_OBJECT_ENSURE_REGISTERED (CcnxContentObjectHeader); |
| NS_OBJECT_ENSURE_REGISTERED (CcnxContentObjectTail); |
| |
| TypeId |
| CcnxContentObjectHeader::GetTypeId (void) |
| { |
| static TypeId tid = TypeId ("ns3::CcnxContentObjectHeader") |
| .SetGroupName ("Ccnx") |
| .SetParent<Header> () |
| .AddConstructor<CcnxContentObjectHeader> () |
| ; |
| return tid; |
| } |
| |
| CcnxContentObjectHeader::CcnxContentObjectHeader () |
| { |
| } |
| |
| void |
| CcnxContentObjectHeader::SetName (const Ptr<CcnxNameComponents> &name) |
| { |
| m_name = name; |
| } |
| |
| const CcnxNameComponents& |
| CcnxContentObjectHeader::GetName () const |
| { |
| if (m_name==0) throw CcnxContentObjectHeaderException(); |
| return *m_name; |
| } |
| |
| #define CCNB CcnxEncodingHelper // just to simplify writing |
| |
| void |
| CcnxContentObjectHeader::Serialize (Buffer::Iterator start) const |
| { |
| size_t written = 0; |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_ContentObject, CcnbParser::CCN_DTAG); // <ContentObject> |
| |
| // fake signature |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_Signature, CcnbParser::CCN_DTAG); // <Signature> |
| // Signature ::= √DigestAlgorithm? |
| // Witness? |
| // √SignatureBits |
| if (GetSignature ().GetDigestAlgorithm () != Signature::DefaultDigestAlgorithm) |
| { |
| written += CCNB::AppendString (start, CCN_DTAG_DigestAlgorithm, GetSignature ().GetDigestAlgorithm ()); |
| } |
| written += CCNB::AppendTaggedBlob (start, CCN_DTAG_SignatureBits, GetSignature ().GetSignatureBits ()); // <SignatureBits /> |
| written += CCNB::AppendCloser (start); // </Signature> |
| |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_Name, CCN_DTAG); // <Name> |
| written += CCNB::AppendNameComponents (start, GetName()); // <Component>...</Component>... |
| written += CCNB::AppendCloser (start); // </Name> |
| |
| // fake signature |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_SignedInfo, CCN_DTAG); // <SignedInfo> |
| // SignedInfo ::= √PublisherPublicKeyDigest |
| // √Timestamp |
| // √Type? |
| // √FreshnessSeconds? |
| // FinalBlockID? |
| // KeyLocator? |
| written += CCNB::AppendTaggedBlob (start, CCN_DTAG_PublisherPublicKeyDigest, // <PublisherPublicKeyDigest>... |
| GetSignedInfo ().GetPublisherPublicKeyDigest ()); |
| |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_Timestamp, CCN_DTAG); // <Timestamp>... |
| written += CCNB::AppendTimestampBlob (start, GetSignedInfo ().GetTimestamp ()); |
| written += CCNB::AppendCloser (start); |
| |
| if (GetSignedInfo ().GetContentType () != DATA) |
| { |
| uint8_t type[3]; |
| type[0] = (GetSignedInfo ().GetContentType () >> 16) & 0xFF; |
| type[1] = (GetSignedInfo ().GetContentType () >> 8 ) & 0xFF; |
| type[2] = (GetSignedInfo ().GetContentType () ) & 0xFF; |
| |
| written += CCNB::AppendTaggedBlob (start, CCN_DTAG_Type, type, 3); |
| } |
| if (GetSignedInfo ().GetFreshness () >= Seconds(0)) |
| { |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_FreshnessSeconds, CCN_DTAG); |
| written += CCNB::AppendNumber (start, GetSignedInfo ().GetFreshness ().ToInteger (Time::S)); |
| written += CCNB::AppendCloser (start); |
| } |
| if (GetSignedInfo ().GetKeyLocator ()->size () > 0) |
| { |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_KeyLocator, CCN_DTAG); // <KeyLocator> |
| { |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_KeyName, CCN_DTAG); // <KeyName> |
| { |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_Name, CCN_DTAG); // <Name> |
| written += CCNB::AppendNameComponents (start, GetName()); // <Component>...</Component>... |
| written += CCNB::AppendCloser (start); // </Name> |
| } |
| written += CCNB::AppendCloser (start); // </KeyName> |
| } |
| written += CCNB::AppendCloser (start); // </KeyLocator> |
| } |
| |
| written += CCNB::AppendCloser (start); // </SignedInfo> |
| |
| written += CCNB::AppendBlockHeader (start, CCN_DTAG_Content, CCN_DTAG); // <Content> |
| |
| // there are no closing tags !!! |
| // The closing tag is handled by CcnxContentObjectTail |
| } |
| |
| uint32_t |
| CcnxContentObjectHeader::GetSerializedSize () const |
| { |
| size_t written = 0; |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_ContentObject); // <ContentObject> |
| |
| // fake signature |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_Signature); // <Signature> |
| // Signature ::= DigestAlgorithm? |
| // Witness? |
| // SignatureBits |
| if (GetSignature ().GetDigestAlgorithm () != Signature::DefaultDigestAlgorithm) |
| { |
| written += CCNB::EstimateString (CCN_DTAG_DigestAlgorithm, GetSignature ().GetDigestAlgorithm ()); |
| } |
| written += CCNB::EstimateTaggedBlob (CCN_DTAG_SignatureBits, |
| sizeof (GetSignature ().GetSignatureBits ())); // <SignatureBits /> |
| written += 1; // </Signature> |
| |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_Name); // <Name> |
| written += CCNB::EstimateNameComponents (GetName()); // <Component>...</Component>... |
| written += 1; // </Name> |
| |
| // fake signature |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_SignedInfo); // <SignedInfo> |
| // SignedInfo ::= √PublisherPublicKeyDigest |
| // √Timestamp |
| // √Type? |
| // √FreshnessSeconds? |
| // FinalBlockID? |
| // KeyLocator? |
| |
| written += CCNB::EstimateTaggedBlob (CCN_DTAG_PublisherPublicKeyDigest, // <PublisherPublicKeyDigest>... |
| sizeof (GetSignedInfo ().GetPublisherPublicKeyDigest ())); |
| |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_Timestamp); // <Timestamp>... |
| written += CCNB::EstimateTimestampBlob (GetSignedInfo ().GetTimestamp ()); |
| written += 1; |
| |
| if (GetSignedInfo ().GetContentType () != DATA) |
| { |
| written += CCNB::EstimateTaggedBlob (CCN_DTAG_Type, 3); |
| } |
| if (GetSignedInfo ().GetFreshness () >= Seconds(0)) |
| { |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_FreshnessSeconds); |
| written += CCNB::EstimateNumber (GetSignedInfo ().GetFreshness ().ToInteger (Time::S)); |
| written += 1; |
| } |
| |
| if (GetSignedInfo ().GetKeyLocator ()->size () > 0) |
| { |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_KeyLocator); // <KeyLocator> |
| { |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_KeyName); // <KeyName> |
| { |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_Name); // <Name> |
| written += CCNB::EstimateNameComponents (GetName()); // <Component>...</Component>... |
| written += 1; // </Name> |
| } |
| written += 1; // </KeyName> |
| } |
| written += 1; // </KeyLocator> |
| } |
| |
| written += 1; // </SignedInfo> |
| |
| written += CCNB::EstimateBlockHeader (CCN_DTAG_Content); // <Content> |
| |
| // there are no closing tags !!! |
| // The closing tag is handled by CcnxContentObjectTail |
| return written; |
| } |
| #undef CCNB |
| |
| class ContentObjectVisitor : public VoidDepthFirstVisitor |
| { |
| public: |
| virtual void visit (Dtag &n, boost::any param/*should be CcnxContentObjectHeader* */) |
| { |
| // uint32_t n.m_dtag; |
| // std::list<Ptr<Block> > n.m_nestedBlocks; |
| static NameComponentsVisitor nameComponentsVisitor; |
| static NonNegativeIntegerVisitor nonNegativeIntegerVisitor; |
| static TimestampVisitor timestampVisitor; |
| static StringVisitor stringVisitor; |
| static Uint32tBlobVisitor uint32tBlobVisitor; |
| static ContentTypeVisitor contentTypeVisitor; |
| |
| CcnxContentObjectHeader &contentObject = *(boost::any_cast<CcnxContentObjectHeader*> (param)); |
| |
| switch (n.m_dtag) |
| { |
| case CCN_DTAG_ContentObject: |
| // process nested blocks |
| BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags) |
| { |
| block->accept (*this, param); |
| } |
| break; |
| case CCN_DTAG_Name: |
| { |
| // process name components |
| Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> (); |
| |
| BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags) |
| { |
| block->accept (nameComponentsVisitor, &(*name)); |
| } |
| contentObject.SetName (name); |
| break; |
| } |
| |
| case CCN_DTAG_Signature: |
| // process nested blocks |
| BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags) |
| { |
| block->accept (*this, param); |
| } |
| break; |
| |
| case CCN_DTAG_DigestAlgorithm: |
| NS_LOG_DEBUG ("DigestAlgorithm"); |
| if (n.m_nestedTags.size ()!=1) // should be exactly one UDATA inside this tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignature ().SetDigestAlgorithm |
| (boost::any_cast<std::string> ((*n.m_nestedTags.begin())->accept |
| (stringVisitor))); |
| break; |
| |
| case CCN_DTAG_SignatureBits: |
| NS_LOG_DEBUG ("SignatureBits"); |
| if (n.m_nestedTags.size ()!=1) // should be only one nested tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignature ().SetSignatureBits |
| (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept |
| (uint32tBlobVisitor))); |
| break; |
| |
| case CCN_DTAG_SignedInfo: |
| // process nested blocks |
| BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags) |
| { |
| block->accept (*this, param); |
| } |
| break; |
| |
| case CCN_DTAG_PublisherPublicKeyDigest: |
| NS_LOG_DEBUG ("PublisherPublicKeyDigest"); |
| if (n.m_nestedTags.size ()!=1) // should be only one nested tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignedInfo ().SetPublisherPublicKeyDigest |
| (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept |
| (uint32tBlobVisitor))); |
| break; |
| |
| case CCN_DTAG_Timestamp: |
| NS_LOG_DEBUG ("Timestamp"); |
| if (n.m_nestedTags.size()!=1) // should be exactly one nested tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignedInfo ().SetTimestamp |
| (boost::any_cast<Time> ((*n.m_nestedTags.begin())->accept |
| (timestampVisitor))); |
| break; |
| |
| case CCN_DTAG_Type: |
| NS_LOG_DEBUG ("Type"); |
| if (n.m_nestedTags.size ()!=1) // should be only one nested tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignedInfo ().SetContentType |
| (static_cast<CcnxContentObjectHeader::ContentType> |
| (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept |
| (contentTypeVisitor)))); |
| break; |
| |
| case CCN_DTAG_FreshnessSeconds: |
| NS_LOG_DEBUG ("FreshnessSeconds"); |
| |
| if (n.m_nestedTags.size()!=1) // should be exactly one nested tag |
| throw CcnbDecodingException (); |
| |
| contentObject.GetSignedInfo ().SetFreshness |
| (Seconds |
| (boost::any_cast<uint32_t> ((*n.m_nestedTags.begin())->accept |
| (nonNegativeIntegerVisitor)))); |
| break; |
| |
| case CCN_DTAG_KeyLocator: |
| // process nested blocks |
| BOOST_FOREACH (Ptr<Block> block, n.m_nestedTags) |
| { |
| block->accept (*this, param); |
| } |
| break; |
| |
| case CCN_DTAG_KeyName: |
| { |
| if (n.m_nestedTags.size ()!=1) // should be exactly one nested tag |
| throw CcnbDecodingException (); |
| |
| Ptr<BaseTag> nameTag = DynamicCast<BaseTag>(n.m_nestedTags.front ()); |
| if (nameTag == 0) |
| throw CcnbDecodingException (); |
| |
| // process name components |
| Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> (); |
| |
| BOOST_FOREACH (Ptr<Block> block, nameTag->m_nestedTags) |
| { |
| block->accept (nameComponentsVisitor, &(*name)); |
| } |
| contentObject.GetSignedInfo ().SetKeyLocator (name); |
| break; |
| } |
| |
| case CCN_DTAG_Content: // !!! HACK |
| // This hack was necessary for memory optimizations (i.e., content is virtual payload) |
| NS_ASSERT_MSG (n.m_nestedTags.size() == 0, "Parser should have stopped just after processing <Content> tag"); |
| break; |
| |
| default: // ignore all other stuff |
| break; |
| } |
| } |
| }; |
| |
| uint32_t |
| CcnxContentObjectHeader::Deserialize (Buffer::Iterator start) |
| { |
| static ContentObjectVisitor contentObjectVisitor; |
| |
| Buffer::Iterator i = start; |
| Ptr<CcnbParser::Block> root = CcnbParser::Block::ParseBlock (i); |
| root->accept (contentObjectVisitor, this); |
| |
| return i.GetDistanceFrom (start); |
| } |
| |
| TypeId |
| CcnxContentObjectHeader::GetInstanceTypeId (void) const |
| { |
| return GetTypeId (); |
| } |
| |
| void |
| CcnxContentObjectHeader::Print (std::ostream &os) const |
| { |
| os << "D: " << GetName (); |
| // os << "<ContentObject><Name>" << GetName () << "</Name><Content>"; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| CcnxContentObjectTail::CcnxContentObjectTail () |
| { |
| } |
| |
| TypeId |
| CcnxContentObjectTail::GetTypeId (void) |
| { |
| static TypeId tid = TypeId ("ns3::CcnxContentObjectTail") |
| .SetParent<Trailer> () |
| .AddConstructor<CcnxContentObjectTail> () |
| ; |
| return tid; |
| } |
| |
| TypeId |
| CcnxContentObjectTail::GetInstanceTypeId (void) const |
| { |
| return GetTypeId (); |
| } |
| |
| void |
| CcnxContentObjectTail::Print (std::ostream &os) const |
| { |
| os << "</Content></ContentObject>"; |
| } |
| |
| uint32_t |
| CcnxContentObjectTail::GetSerializedSize (void) const |
| { |
| return 2; |
| } |
| |
| void |
| CcnxContentObjectTail::Serialize (Buffer::Iterator start) const |
| { |
| Buffer::Iterator i = start; |
| i.Prev (2); // Trailer interface requires us to go backwards |
| |
| i.WriteU8 (0x00); // </Content> |
| i.WriteU8 (0x00); // </ContentObject> |
| } |
| |
| uint32_t |
| CcnxContentObjectTail::Deserialize (Buffer::Iterator start) |
| { |
| Buffer::Iterator i = start; |
| i.Prev (2); // Trailer interface requires us to go backwards |
| |
| uint8_t __attribute__ ((unused)) closing_tag_content = i.ReadU8 (); |
| NS_ASSERT_MSG (closing_tag_content==0, "Should be a closing tag </Content> (0x00)"); |
| |
| uint8_t __attribute__ ((unused)) closing_tag_content_object = i.ReadU8 (); |
| NS_ASSERT_MSG (closing_tag_content_object==0, "Should be a closing tag </ContentObject> (0x00)"); |
| |
| return 2; |
| } |
| |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| /////////////////////////////////////////////////////////////////////// |
| |
| CcnxContentObjectHeader::SignedInfo::SignedInfo () |
| : m_publisherPublicKeyDigest (0) |
| // , m_timestamp |
| , m_type (DATA) |
| // , m_freshness |
| // , FinalBlockID |
| // , KeyLocator |
| { |
| } |
| |
| void |
| CcnxContentObjectHeader::SignedInfo::SetPublisherPublicKeyDigest (uint32_t digest) |
| { |
| m_publisherPublicKeyDigest = digest; |
| } |
| |
| uint32_t |
| CcnxContentObjectHeader::SignedInfo::GetPublisherPublicKeyDigest () const |
| { |
| return m_publisherPublicKeyDigest; |
| } |
| |
| void |
| CcnxContentObjectHeader::SignedInfo::SetTimestamp (const Time ×tamp) |
| { |
| m_timestamp = timestamp; |
| } |
| |
| Time |
| CcnxContentObjectHeader::SignedInfo::GetTimestamp () const |
| { |
| return m_timestamp; |
| } |
| |
| void |
| CcnxContentObjectHeader::SignedInfo::SetContentType (CcnxContentObjectHeader::ContentType type) |
| { |
| m_type = type; |
| } |
| |
| CcnxContentObjectHeader::ContentType |
| CcnxContentObjectHeader::SignedInfo::GetContentType () const |
| { |
| return m_type; |
| } |
| |
| void |
| CcnxContentObjectHeader::SignedInfo::SetFreshness (const Time &freshness) |
| { |
| m_freshness = freshness; |
| } |
| |
| Time |
| CcnxContentObjectHeader::SignedInfo::GetFreshness () const |
| { |
| return m_freshness; |
| } |
| |
| void |
| CcnxContentObjectHeader::SignedInfo::SetKeyLocator (Ptr<const CcnxNameComponents> keyLocator) |
| { |
| m_keyLocator = keyLocator; |
| } |
| |
| Ptr<const CcnxNameComponents> |
| CcnxContentObjectHeader::SignedInfo::GetKeyLocator () const |
| { |
| return m_keyLocator; |
| } |
| |
| } // namespace ns3 |