ndn-embeds 0.1.0
Lightweight NDN protocol stack for embedded systems
Loading...
Searching...
No Matches
tlv.cpp
1#include "ndn/tlv.hpp"
2#include <cstring>
3
4namespace ndn {
5
6// =============================================================================
7// TlvEncoder
8// =============================================================================
9
10TlvEncoder::TlvEncoder(uint8_t* buf, size_t capacity) : buf_(buf), capacity_(capacity) {}
11
13 if (value <= 252) {
14 if (remaining() < 1) {
15 return Error::BufferTooSmall;
16 }
17 buf_[pos_++] = static_cast<uint8_t>(value);
18 } else if (value <= 0xFFFF) {
19 if (remaining() < 3) {
20 return Error::BufferTooSmall;
21 }
22 buf_[pos_++] = 253;
23 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
24 buf_[pos_++] = static_cast<uint8_t>(value);
25 } else if (value <= 0xFFFFFFFF) {
26 if (remaining() < 5) {
27 return Error::BufferTooSmall;
28 }
29 buf_[pos_++] = 254;
30 buf_[pos_++] = static_cast<uint8_t>(value >> 24);
31 buf_[pos_++] = static_cast<uint8_t>(value >> 16);
32 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
33 buf_[pos_++] = static_cast<uint8_t>(value);
34 } else {
35 if (remaining() < 9) {
36 return Error::BufferTooSmall;
37 }
38 buf_[pos_++] = 255;
39 buf_[pos_++] = static_cast<uint8_t>(value >> 56);
40 buf_[pos_++] = static_cast<uint8_t>(value >> 48);
41 buf_[pos_++] = static_cast<uint8_t>(value >> 40);
42 buf_[pos_++] = static_cast<uint8_t>(value >> 32);
43 buf_[pos_++] = static_cast<uint8_t>(value >> 24);
44 buf_[pos_++] = static_cast<uint8_t>(value >> 16);
45 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
46 buf_[pos_++] = static_cast<uint8_t>(value);
47 }
48 return Error::Success;
49}
50
52 if (value <= 0xFF) {
53 if (remaining() < 1) {
54 return Error::BufferTooSmall;
55 }
56 buf_[pos_++] = static_cast<uint8_t>(value);
57 } else if (value <= 0xFFFF) {
58 if (remaining() < 2) {
59 return Error::BufferTooSmall;
60 }
61 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
62 buf_[pos_++] = static_cast<uint8_t>(value);
63 } else if (value <= 0xFFFFFFFF) {
64 if (remaining() < 4) {
65 return Error::BufferTooSmall;
66 }
67 buf_[pos_++] = static_cast<uint8_t>(value >> 24);
68 buf_[pos_++] = static_cast<uint8_t>(value >> 16);
69 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
70 buf_[pos_++] = static_cast<uint8_t>(value);
71 } else {
72 if (remaining() < 8) {
73 return Error::BufferTooSmall;
74 }
75 buf_[pos_++] = static_cast<uint8_t>(value >> 56);
76 buf_[pos_++] = static_cast<uint8_t>(value >> 48);
77 buf_[pos_++] = static_cast<uint8_t>(value >> 40);
78 buf_[pos_++] = static_cast<uint8_t>(value >> 32);
79 buf_[pos_++] = static_cast<uint8_t>(value >> 24);
80 buf_[pos_++] = static_cast<uint8_t>(value >> 16);
81 buf_[pos_++] = static_cast<uint8_t>(value >> 8);
82 buf_[pos_++] = static_cast<uint8_t>(value);
83 }
84 return Error::Success;
85}
86
88 return writeVarNumber(type);
89}
90
92 return writeVarNumber(length);
93}
94
95Error TlvEncoder::writeBytes(const uint8_t* data, size_t len) {
96 if (remaining() < len) {
97 return Error::BufferTooSmall;
98 }
99 std::memcpy(buf_ + pos_, data, len);
100 pos_ += len;
101 return Error::Success;
102}
103
104Error TlvEncoder::writeTlv(uint32_t type, const uint8_t* value, size_t valueLen) {
105 Error err = writeType(type);
106 if (err != Error::Success) {
107 return err;
108 }
109
110 err = writeLength(valueLen);
111 if (err != Error::Success) {
112 return err;
113 }
114
115 if (valueLen > 0) {
116 err = writeBytes(value, valueLen);
117 if (err != Error::Success) {
118 return err;
119 }
120 }
121
122 return Error::Success;
123}
124
125Error TlvEncoder::writeTlvNonNegativeInteger(uint32_t type, uint64_t value) {
126 const size_t intSize = nonNegativeIntegerSize(value);
127
128 Error err = writeType(type);
129 if (err != Error::Success) {
130 return err;
131 }
132
133 err = writeLength(intSize);
134 if (err != Error::Success) {
135 return err;
136 }
137
138 return writeNonNegativeInteger(value);
139}
140
141// =============================================================================
142// TlvDecoder
143// =============================================================================
144
145TlvDecoder::TlvDecoder(const uint8_t* buf, size_t len) : buf_(buf), len_(len) {}
146
148 if (remaining() < 1) {
149 return {.value = 0, .error = Error::DecodeFailed};
150 }
151
152 const uint8_t firstByte = buf_[pos_++];
153
154 if (firstByte <= 252) {
155 return {.value = firstByte, .error = Error::Success};
156 } else if (firstByte == 253) {
157 if (remaining() < 2) {
158 return {.value = 0, .error = Error::DecodeFailed};
159 }
160 const uint64_t val =
161 (static_cast<uint64_t>(buf_[pos_]) << 8) | static_cast<uint64_t>(buf_[pos_ + 1]);
162 pos_ += 2;
163 return {.value = val, .error = Error::Success};
164 } else if (firstByte == 254) {
165 if (remaining() < 4) {
166 return {.value = 0, .error = Error::DecodeFailed};
167 }
168 const uint64_t val = (static_cast<uint64_t>(buf_[pos_]) << 24) |
169 (static_cast<uint64_t>(buf_[pos_ + 1]) << 16) |
170 (static_cast<uint64_t>(buf_[pos_ + 2]) << 8) |
171 static_cast<uint64_t>(buf_[pos_ + 3]);
172 pos_ += 4;
173 return {.value = val, .error = Error::Success};
174 } else { // firstByte == 255
175 if (remaining() < 8) {
176 return {.value = 0, .error = Error::DecodeFailed};
177 }
178 const uint64_t val = (static_cast<uint64_t>(buf_[pos_]) << 56) |
179 (static_cast<uint64_t>(buf_[pos_ + 1]) << 48) |
180 (static_cast<uint64_t>(buf_[pos_ + 2]) << 40) |
181 (static_cast<uint64_t>(buf_[pos_ + 3]) << 32) |
182 (static_cast<uint64_t>(buf_[pos_ + 4]) << 24) |
183 (static_cast<uint64_t>(buf_[pos_ + 5]) << 16) |
184 (static_cast<uint64_t>(buf_[pos_ + 6]) << 8) |
185 static_cast<uint64_t>(buf_[pos_ + 7]);
186 pos_ += 8;
187 return {.value = val, .error = Error::Success};
188 }
189}
190
192 if (remaining() < numBytes) {
193 return {.value = 0, .error = Error::DecodeFailed};
194 }
195
196 uint64_t val = 0;
197 for (size_t idx = 0; idx < numBytes; ++idx) {
198 val = (val << 8) | buf_[pos_++];
199 }
200
201 return {.value = val, .error = Error::Success};
202}
203
205 auto result = readVarNumber();
206 if (!result.ok()) {
207 return {.value = 0, .error = result.error};
208 }
209 // NDN TLV type must fit in 32 bits
210 if (result.value > 0xFFFFFFFF) {
211 return {.value = 0, .error = Error::DecodeFailed};
212 }
213 return {.value = static_cast<uint32_t>(result.value), .error = Error::Success};
214}
215
217 auto result = readVarNumber();
218 if (!result.ok()) {
219 return {.value = 0, .error = result.error};
220 }
221 return {.value = static_cast<size_t>(result.value), .error = Error::Success};
222}
223
225 auto typeResult = readType();
226 if (!typeResult.ok()) {
227 return {.value = {.type = 0, .length = 0}, .error = typeResult.error};
228 }
229
230 auto lengthResult = readLength();
231 if (!lengthResult.ok()) {
232 return {.value = {.type = 0, .length = 0}, .error = lengthResult.error};
233 }
234
235 return {.value = {.type = typeResult.value, .length = lengthResult.value},
236 .error = Error::Success};
237}
238
239Error TlvDecoder::readBytes(uint8_t* out, size_t len) {
240 if (remaining() < len) {
241 return Error::DecodeFailed;
242 }
243 std::memcpy(out, buf_ + pos_, len);
244 pos_ += len;
245 return Error::Success;
246}
247
249 if (remaining() < len) {
250 return Error::DecodeFailed;
251 }
252 pos_ += len;
253 return Error::Success;
254}
255
256} // namespace ndn
Result< uint32_t > readType()
Read a TLV Type.
Definition tlv.cpp:204
Error readBytes(uint8_t *out, size_t len)
Read a specified number of bytes.
Definition tlv.cpp:239
Result< size_t > readLength()
Read a TLV Length.
Definition tlv.cpp:216
Result< uint64_t > readNonNegativeInteger(size_t numBytes)
Read a non-negative integer of specified byte count.
Definition tlv.cpp:191
Result< TlvHeader > readTlvHeader()
Read a TLV header (Type and Length) at once.
Definition tlv.cpp:224
TlvDecoder(const uint8_t *buf, size_t len)
Constructor.
Definition tlv.cpp:145
Error skip(size_t len)
Skip a specified number of bytes.
Definition tlv.cpp:248
size_t remaining() const
Remaining readable bytes.
Definition tlv.hpp:302
Result< uint64_t > readVarNumber()
Read a value in VAR-NUMBER format.
Definition tlv.cpp:147
Error writeVarNumber(uint64_t value)
Write a value in VAR-NUMBER format.
Definition tlv.cpp:12
Error writeLength(size_t length)
Write a TLV Length.
Definition tlv.cpp:91
TlvEncoder(uint8_t *buf, size_t capacity)
Constructor.
Definition tlv.cpp:10
Error writeNonNegativeInteger(uint64_t value)
Write a non-negative integer (big-endian, minimum bytes)
Definition tlv.cpp:51
Error writeTlv(uint32_t type, const uint8_t *value, size_t valueLen)
Write a complete TLV structure.
Definition tlv.cpp:104
Error writeBytes(const uint8_t *data, size_t len)
Write a byte sequence.
Definition tlv.cpp:95
size_t remaining() const
Remaining writable bytes.
Definition tlv.hpp:195
Error writeTlvNonNegativeInteger(uint32_t type, uint64_t value)
Write a non-negative integer as a TLV.
Definition tlv.cpp:125
Error writeType(uint32_t type)
Write a TLV Type.
Definition tlv.cpp:87
Error
Error codes.
Definition common.hpp:24
Result type template.
Definition common.hpp:147
T value
Result value.
Definition common.hpp:148
NDN TLV (Type-Length-Value) encoding.
constexpr size_t nonNegativeIntegerSize(uint64_t value)
Calculate the encoded size of a non-negative integer (minimum bytes)
Definition tlv.hpp:357