blob: 22fccaec0126dee68ba5828be24ef274fcf9bc32 [file] [log] [blame]
Eric Newberry38982622015-08-06 21:39:55 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2015 Regents of the University of California.
4 *
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 * @author Eric Newberry <enewberry@email.arizona.edu>
22 */
23
24#include "nack-header.hpp"
25
26namespace ndn {
27namespace lp {
28
29std::ostream&
30operator<<(std::ostream& os, NackReason reason)
31{
32 switch (reason) {
33 case NackReason::CONGESTION:
34 os << "Congestion";
35 break;
36 case NackReason::DUPLICATE:
37 os << "Duplicate";
38 break;
39 case NackReason::NO_ROUTE:
40 os << "NoRoute";
41 break;
42 default:
43 os << "None";
44 break;
45 }
46 return os;
47}
48
49NackHeader::NackHeader()
50 : m_reason(NackReason::NONE)
51{
52}
53
54NackHeader::NackHeader(const Block& block)
55{
56 wireDecode(block);
57}
58
59template<encoding::Tag TAG>
60size_t
61NackHeader::wireEncode(EncodingImpl<TAG>& encoder) const
62{
63 size_t length = 0;
64 length += prependNonNegativeIntegerBlock(encoder, tlv::NackReason,
65 static_cast<uint32_t>(m_reason));
66 length += encoder.prependVarNumber(length);
67 length += encoder.prependVarNumber(tlv::Nack);
68 return length;
69}
70
71template size_t
72NackHeader::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
73
74template size_t
75NackHeader::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
76
77const Block&
78NackHeader::wireEncode() const
79{
80 if (m_wire.hasWire()) {
81 return m_wire;
82 }
83
84 EncodingEstimator estimator;
85 size_t estimatedSize = wireEncode(estimator);
86
87 EncodingBuffer buffer(estimatedSize, 0);
88 wireEncode(buffer);
89
90 m_wire = buffer.block();
91
92 return m_wire;
93}
94
95void
96NackHeader::wireDecode(const Block& wire)
97{
98 if (wire.type() != tlv::Nack) {
99 throw ndn::tlv::Error("expecting Nack block");
100 }
101
102 m_wire = wire;
103 m_wire.parse();
104 m_reason = NackReason::NONE;
105
106 if (m_wire.elements_size() > 0) {
107 Block::element_const_iterator it = m_wire.elements_begin();
108
109 if (it->type() == tlv::NackReason) {
110 m_reason = static_cast<NackReason>(readNonNegativeInteger(*it));
111 }
112 else {
113 throw ndn::tlv::Error("expecting NackReason block");
114 }
115 }
116}
117
118NackReason
119NackHeader::getReason() const
120{
121 switch (m_reason) {
122 case NackReason::CONGESTION:
123 case NackReason::DUPLICATE:
124 case NackReason::NO_ROUTE:
125 return m_reason;
126 default:
127 return NackReason::NONE;
128 }
129}
130
131NackHeader&
132NackHeader::setReason(NackReason reason)
133{
134 m_reason = reason;
135 m_wire.reset();
136 return *this;
137}
138
139} // namespace lp
140} // namespace ndn