1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file includes definitions for generating and processing MLE TLVs.
32 */
33
34 #ifndef TLVS_HPP_
35 #define TLVS_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include <openthread/thread.h>
40 #include <openthread/platform/toolchain.h>
41
42 #include "common/encoding.hpp"
43 #include "common/error.hpp"
44 #include "common/type_traits.hpp"
45
46 namespace ot {
47
48 using ot::Encoding::BigEndian::HostSwap16;
49
50 class Message;
51
52 /**
53 * Implements TLV generation and parsing.
54 *
55 */
56 OT_TOOL_PACKED_BEGIN
57 class Tlv
58 {
59 public:
60 /**
61 * The maximum length of the Base TLV format.
62 *
63 */
64 static constexpr uint8_t kBaseTlvMaxLength = OT_NETWORK_BASE_TLV_MAX_LENGTH;
65
66 /**
67 * Returns the Type value.
68 *
69 * @returns The Type value.
70 *
71 */
GetType(void) const72 uint8_t GetType(void) const { return mType; }
73
74 /**
75 * Sets the Type value.
76 *
77 * @param[in] aType The Type value.
78 *
79 */
SetType(uint8_t aType)80 void SetType(uint8_t aType) { mType = aType; }
81
82 /**
83 * Indicates whether the TLV is an Extended TLV.
84 *
85 * @retval TRUE If the TLV is an Extended TLV.
86 * @retval FALSE If the TLV is not an Extended TLV.
87 *
88 */
IsExtended(void) const89 bool IsExtended(void) const { return (mLength == kExtendedLength); }
90
91 /**
92 * Returns the Length value.
93 *
94 * @note This method should be used when TLV is not an Extended TLV, otherwise the returned length from this method
95 * would not be correct. When TLV is an Extended TLV, the TLV should be down-casted to the `ExtendedTlv` type and
96 * the `ExtendedTlv::GetLength()` should be used instead.
97 *
98 * @returns The Length value.
99 *
100 */
GetLength(void) const101 uint8_t GetLength(void) const { return mLength; }
102
103 /**
104 * Sets the Length value.
105 *
106 * @param[in] aLength The Length value.
107 *
108 */
SetLength(uint8_t aLength)109 void SetLength(uint8_t aLength) { mLength = aLength; }
110
111 /**
112 * Returns the TLV's total size (number of bytes) including Type, Length, and Value fields.
113 *
114 * Correctly returns the TLV size independent of whether the TLV is an Extended TLV or not.
115 *
116 * @returns The total size include Type, Length, and Value fields.
117 *
118 */
119 uint32_t GetSize(void) const;
120
121 /**
122 * Returns a pointer to the Value.
123 *
124 * Can be used independent of whether the TLV is an Extended TLV or not.
125 *
126 * @returns A pointer to the value.
127 *
128 */
129 uint8_t *GetValue(void);
130
131 /**
132 * Returns a pointer to the Value.
133 *
134 * Can be used independent of whether the TLV is an Extended TLV or not.
135 *
136 * @returns A pointer to the value.
137 *
138 */
139 const uint8_t *GetValue(void) const;
140
141 /**
142 * Returns a pointer to the next TLV.
143 *
144 * Correctly returns the next TLV independent of whether the current TLV is an Extended TLV or not.
145 *
146 * @returns A pointer to the next TLV.
147 *
148 */
GetNext(void)149 Tlv *GetNext(void) { return reinterpret_cast<Tlv *>(reinterpret_cast<uint8_t *>(this) + GetSize()); }
150
151 /**
152 * Returns a pointer to the next TLV.
153 *
154 * Correctly returns the next TLV independent of whether the current TLV is an Extended TLV or not.
155 *
156 * @returns A pointer to the next TLV.
157 *
158 */
GetNext(void) const159 const Tlv *GetNext(void) const
160 {
161 return reinterpret_cast<const Tlv *>(reinterpret_cast<const uint8_t *>(this) + GetSize());
162 }
163
164 /**
165 * Appends a TLV to the end of the message.
166 *
167 * On success, this method grows the message by the size of the TLV.
168 *
169 * @param[in] aMessage A reference to the message to append to.
170 *
171 * @retval kErrorNone Successfully appended the TLV to the message.
172 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
173 *
174 */
175 Error AppendTo(Message &aMessage) const;
176
177 /**
178 * Reads a TLV's value in a message at a given offset expecting a minimum length for the value.
179 *
180 * Can be used independent of whether the read TLV (from the message) is an Extended TLV or not.
181 *
182 * @param[in] aMessage The message to read from.
183 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
184 * @param[out] aValue A buffer to output the TLV's value, must contain (at least) @p aMinLength bytes.
185 * @param[in] aMinLength The minimum expected length of TLV and number of bytes to copy into @p aValue buffer.
186 *
187 * @retval kErrorNone Successfully read the TLV and copied @p aMinLength into @p aValue.
188 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
189 *
190 */
191 static Error ReadTlvValue(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength);
192
193 /**
194 * Reads a simple TLV with a single non-integral value in a message at a given offset.
195 *
196 * @tparam SimpleTlvType The simple TLV type to read (must be a sub-class of `SimpleTlvInfo`).
197 *
198 * @param[in] aMessage The message to read from.
199 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
200 * @param[out] aValue A reference to the value object to output the read value.
201 *
202 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
203 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
204 *
205 */
206 template <typename SimpleTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename SimpleTlvType::ValueType & aValue)207 static Error Read(const Message &aMessage, uint16_t aOffset, typename SimpleTlvType::ValueType &aValue)
208 {
209 return ReadTlvValue(aMessage, aOffset, &aValue, sizeof(aValue));
210 }
211
212 /**
213 * Reads a simple TLV with a single integral value in a message at a given offset.
214 *
215 * @tparam UintTlvType The simple TLV type to read (must be a sub-class of `UintTlvInfo`).
216 *
217 * @param[in] aMessage The message to read from.
218 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
219 * @param[out] aValue A reference to an unsigned int to output the read value.
220 *
221 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
222 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
223 *
224 */
225 template <typename UintTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename UintTlvType::UintValueType & aValue)226 static Error Read(const Message &aMessage, uint16_t aOffset, typename UintTlvType::UintValueType &aValue)
227 {
228 return ReadUintTlv(aMessage, aOffset, aValue);
229 }
230
231 /**
232 * Reads a simple TLV with a UTF-8 string value in a message at a given offset.
233 *
234 * @tparam StringTlvType The simple TLV type to read (must be a sub-class of `StringTlvInfo`).
235 *
236 * @param[in] aMessage The message to read from.
237 * @param[in] aOffset The offset into the message pointing to the start of the TLV.
238 * @param[out] aValue A reference to the string buffer to output the read value.
239 *
240 * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
241 * @retval kErrorParse The TLV was not well-formed and could not be parsed.
242 *
243 */
244 template <typename StringTlvType>
Read(const Message & aMessage,uint16_t aOffset,typename StringTlvType::StringType & aValue)245 static Error Read(const Message &aMessage, uint16_t aOffset, typename StringTlvType::StringType &aValue)
246 {
247 return ReadStringTlv(aMessage, aOffset, StringTlvType::kMaxStringLength, aValue);
248 }
249
250 /**
251 * Searches for and reads a requested TLV out of a given message.
252 *
253 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
254 *
255 * @param[in] aMessage A reference to the message.
256 * @param[in] aType The Type value to search for.
257 * @param[in] aMaxSize Maximum number of bytes to read.
258 * @param[out] aTlv A reference to the TLV that will be copied to.
259 *
260 * @retval kErrorNone Successfully copied the TLV.
261 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
262 *
263 */
264 static Error FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv);
265
266 /**
267 * Searches for and reads a requested TLV out of a given message.
268 *
269 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
270 *
271 * @param[in] aMessage A reference to the message.
272 * @param[in] aType The Type value to search for.
273 * @param[in] aMaxSize Maximum number of bytes to read.
274 * @param[out] aTlv A reference to the TLV that will be copied to.
275 * @param[out] aOffset A reference to return the offset to start of the TLV in @p aMessage.
276 *
277 * @retval kErrorNone Successfully copied the TLV.
278 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
279 *
280 */
281 static Error FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv, uint16_t &aOffset);
282
283 /**
284 * Searches for and reads a requested TLV out of a given message.
285 *
286 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
287 *
288 * @tparam TlvType The TlvType to search for (must be a sub-class of `Tlv`).
289 *
290 * @param[in] aMessage A reference to the message.
291 * @param[out] aTlv A reference to the TLV that will be copied to.
292 *
293 * @retval kErrorNone Successfully copied the TLV.
294 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
295 *
296 */
FindTlv(const Message & aMessage,TlvType & aTlv)297 template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
298 {
299 return FindTlv(aMessage, TlvType::kType, sizeof(TlvType), aTlv);
300 }
301
302 /**
303 * Searches for and reads a requested TLV out of a given message.
304 *
305 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
306 *
307 * @tparam TlvType The TlvType to search for (must be a sub-class of `Tlv`).
308 *
309 * @param[in] aMessage A reference to the message.
310 * @param[out] aTlv A reference to the TLV that will be copied to.
311 * @param[out] aOffset A reference to return the offset to start of the TLV in @p aMessage.
312 *
313 * @retval kErrorNone Successfully copied the TLV.
314 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
315 *
316 */
FindTlv(const Message & aMessage,TlvType & aTlv,uint16_t & aOffset)317 template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv, uint16_t &aOffset)
318 {
319 return FindTlv(aMessage, TlvType::kType, sizeof(TlvType), aTlv, aOffset);
320 }
321
322 /**
323 * Finds the offset and length of TLV value for a given TLV type within @p aMessage.
324 *
325 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
326 *
327 * @param[in] aMessage A reference to the message.
328 * @param[in] aType The Type value to search for.
329 * @param[out] aValueOffset The offset where the value starts.
330 * @param[out] aLength The length of the value.
331 *
332 * @retval kErrorNone Successfully found the TLV.
333 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
334 *
335 */
336 static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
337
338 /**
339 * Finds the start and end offset of TLV value for a given TLV type with @p aMessage.
340 *
341 * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
342 *
343 * @param[in] aMessage A reference to the message.
344 * @param[in] aType The Type value to search for.
345 * @param[out] aValueStartOffset The offset where the value starts.
346 * @param[out] aValueEndOffset The offset immediately after the last byte of value.
347 *
348 * @retval kErrorNone Successfully found the TLV.
349 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
350 *
351 */
352 static Error FindTlvValueStartEndOffsets(const Message &aMessage,
353 uint8_t aType,
354 uint16_t &aValueStartOffset,
355 uint16_t &aValueEndOffset);
356
357 /**
358 * Searches for a TLV with a given type in a message, ensures its length is same or larger than
359 * an expected minimum value, and then reads its value into a given buffer.
360 *
361 * If the TLV length is smaller than the minimum length @p aLength, the TLV is considered invalid. In this case,
362 * this method returns `kErrorParse` and the @p aValue buffer is not updated.
363 *
364 * If the TLV length is larger than @p aLength, the TLV is considered valid, but only the first @p aLength bytes
365 * of the value are read and copied into the @p aValue buffer.
366 *
367 * @tparam TlvType The TLV type to find.
368 *
369 * @param[in] aMessage A reference to the message.
370 * @param[out] aValue A buffer to output the value (must contain at least @p aLength bytes).
371 * @param[in] aLength The expected (minimum) length of the TLV value.
372 *
373 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
374 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
375 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
376 *
377 */
Find(const Message & aMessage,void * aValue,uint8_t aLength)378 template <typename TlvType> static Error Find(const Message &aMessage, void *aValue, uint8_t aLength)
379 {
380 return FindTlv(aMessage, TlvType::kType, aValue, aLength);
381 }
382
383 /**
384 * Searches for a simple TLV with a single non-integral value in a message, ensures its length is
385 * same or larger than the expected `ValueType` object size, and then reads its value into a value object reference.
386 *
387 * If the TLV length is smaller than the size of @p aValue, the TLV is considered invalid. In this case, this
388 * method returns `kErrorParse` and the @p aValue is not updated.
389 *
390 * If the TLV length is larger than the size of @p aValue, the TLV is considered valid, but the size of
391 * `ValueType` bytes are read and copied into the @p aValue.
392 *
393 * @tparam SimpleTlvType The simple TLV type to find (must be a sub-class of `SimpleTlvInfo`)
394 *
395 * @param[in] aMessage A reference to the message.
396 * @param[out] aValue A reference to the value object to output the read value.
397 *
398 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
399 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
400 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
401 *
402 */
403 template <typename SimpleTlvType>
Find(const Message & aMessage,typename SimpleTlvType::ValueType & aValue)404 static Error Find(const Message &aMessage, typename SimpleTlvType::ValueType &aValue)
405 {
406 return FindTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
407 }
408
409 /**
410 * Searches for a simple TLV with a single integral value in a message, and then reads its value
411 * into a given `uint` reference variable.
412 *
413 * If the TLV length is smaller than size of integral value, the TLV is considered invalid. In this case, this
414 * method returns `kErrorParse` and the @p aValue is not updated.
415 *
416 * @tparam UintTlvType The simple TLV type to find (must be a sub-class of `UintTlvInfo`)
417 *
418 * @param[in] aMessage A reference to the message.
419 * @param[out] aValue A reference to an unsigned int value to output the TLV's value.
420 *
421 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
422 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
423 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
424 *
425 */
426 template <typename UintTlvType>
Find(const Message & aMessage,typename UintTlvType::UintValueType & aValue)427 static Error Find(const Message &aMessage, typename UintTlvType::UintValueType &aValue)
428 {
429 return FindUintTlv(aMessage, UintTlvType::kType, aValue);
430 }
431
432 /**
433 * Searches for a simple TLV with a UTF-8 string value in a message, and then reads its value
434 * into a given string buffer.
435 *
436 * If the TLV length is longer than maximum string length specified by `StringTlvType::kMaxStringLength` then
437 * only up to maximum length is read and returned. In this case `kErrorNone` is returned.
438 *
439 * The returned string in @p aValue is always null terminated.`StringTlvType::StringType` MUST have at least
440 * `kMaxStringLength + 1` chars.
441 *
442 * @tparam StringTlvType The simple TLV type to find (must be a sub-class of `StringTlvInfo`)
443 *
444 * @param[in] aMessage A reference to the message.
445 * @param[out] aValue A reference to a string buffer to output the TLV's value.
446 *
447 * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
448 * @retval kErrorNotFound Could not find the TLV with Type @p aType.
449 * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
450 *
451 */
452 template <typename StringTlvType>
Find(const Message & aMessage,typename StringTlvType::StringType & aValue)453 static Error Find(const Message &aMessage, typename StringTlvType::StringType &aValue)
454 {
455 return FindStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue);
456 }
457
458 /**
459 * Appends a TLV with a given type and value to a message.
460 *
461 * On success this method grows the message by the size of the TLV.
462 *
463 * @tparam TlvType The TLV type to append.
464 *
465 * @param[in] aMessage A reference to the message to append to.
466 * @param[in] aValue A buffer containing the TLV value.
467 * @param[in] aLength The value length (in bytes).
468 *
469 * @retval kErrorNone Successfully appended the TLV to the message.
470 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
471 *
472 */
Append(Message & aMessage,const void * aValue,uint8_t aLength)473 template <typename TlvType> static Error Append(Message &aMessage, const void *aValue, uint8_t aLength)
474 {
475 return AppendTlv(aMessage, TlvType::kType, aValue, aLength);
476 }
477
478 /**
479 * Appends a simple TLV with a single (non-integral) value to a message.
480 *
481 * On success this method grows the message by the size of the TLV.
482 *
483 * @tparam SimpleTlvType The simple TLV type to append (must be a sub-class of `SimpleTlvInfo`)
484 *
485 * @param[in] aMessage A reference to the message to append to.
486 * @param[in] aValue A reference to the object containing TLV's value.
487 *
488 * @retval kErrorNone Successfully appended the TLV to the message.
489 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
490 *
491 */
492 template <typename SimpleTlvType>
Append(Message & aMessage,const typename SimpleTlvType::ValueType & aValue)493 static Error Append(Message &aMessage, const typename SimpleTlvType::ValueType &aValue)
494 {
495 return AppendTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
496 }
497
498 /**
499 * Appends a simple TLV with a single integral value to a message.
500 *
501 * On success this method grows the message by the size of the TLV.
502 *
503 * @tparam UintTlvType The simple TLV type to append (must be a sub-class of `UintTlvInfo`)
504 *
505 * @param[in] aMessage A reference to the message to append to.
506 * @param[in] aValue An unsigned int value to use as TLV's value.
507 *
508 * @retval kErrorNone Successfully appended the TLV to the message.
509 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
510 *
511 */
Append(Message & aMessage,typename UintTlvType::UintValueType aValue)512 template <typename UintTlvType> static Error Append(Message &aMessage, typename UintTlvType::UintValueType aValue)
513 {
514 return AppendUintTlv(aMessage, UintTlvType::kType, aValue);
515 }
516
517 /**
518 * Appends a simple TLV with a single UTF-8 string value to a message.
519 *
520 * On success this method grows the message by the size of the TLV.
521 *
522 * If the passed in @p aValue string length is longer than the maximum allowed length for the TLV as specified by
523 * `StringTlvType::kMaxStringLength`, the first maximum length chars are appended.
524 *
525 * The @p aValue can be `nullptr` in which case it is treated as an empty string.
526 *
527 * @tparam StringTlvType The simple TLV type to append (must be a sub-class of `StringTlvInfo`)
528 *
529 * @param[in] aMessage A reference to the message to append to.
530 * @param[in] aValue A pointer to a C string to append as TLV's value.
531 *
532 * @retval kErrorNone Successfully appended the TLV to the message.
533 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
534 *
535 */
Append(Message & aMessage,const char * aValue)536 template <typename StringTlvType> static Error Append(Message &aMessage, const char *aValue)
537 {
538 return AppendStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue);
539 }
540
541 protected:
542 static const uint8_t kExtendedLength = 255; // Extended Length value.
543
544 private:
545 struct ParsedInfo
546 {
547 Error ParseFrom(const Message &aMessage, uint16_t aOffset);
548 Error FindIn(const Message &aMessage, uint8_t aType);
549
550 uint8_t mType;
551 uint16_t mLength;
552 uint16_t mOffset;
553 uint16_t mValueOffset;
554 uint16_t mSize;
555 };
556
557 static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
558 static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
559 static Error ReadStringTlv(const Message &aMessage, uint16_t aOffset, uint8_t aMaxStringLength, char *aValue);
560 static Error FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue);
561 static Error AppendStringTlv(Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, const char *aValue);
562 template <typename UintType> static Error ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue);
563 template <typename UintType> static Error FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue);
564 template <typename UintType> static Error AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue);
565
566 uint8_t mType;
567 uint8_t mLength;
568 } OT_TOOL_PACKED_END;
569
570 OT_TOOL_PACKED_BEGIN
571 class ExtendedTlv : public Tlv
572 {
573 public:
574 /**
575 * Returns the Length value.
576 *
577 */
GetLength(void) const578 uint16_t GetLength(void) const { return HostSwap16(mLength); }
579
580 /**
581 * Sets the Length value.
582 *
583 * @param[in] aLength The Length value.
584 *
585 */
SetLength(uint16_t aLength)586 void SetLength(uint16_t aLength)
587 {
588 Tlv::SetLength(kExtendedLength);
589 mLength = HostSwap16(aLength);
590 }
591
592 private:
593 uint16_t mLength;
594 } OT_TOOL_PACKED_END;
595
596 /**
597 * Casts a `Tlv` pointer to a given subclass `TlvType` pointer.
598 *
599 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
600 *
601 * @param[in] aTlv A pointer to a `Tlv` to convert/cast to a `TlvType`.
602 *
603 * @returns A `TlvType` pointer to `aTlv`.
604 *
605 */
As(Tlv * aTlv)606 template <class TlvType> TlvType *As(Tlv *aTlv) { return static_cast<TlvType *>(aTlv); }
607
608 /**
609 * Casts a `Tlv` pointer to a given subclass `TlvType` pointer.
610 *
611 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
612 *
613 * @param[in] aTlv A pointer to a `Tlv` to convert/cast to a `TlvType`.
614 *
615 * @returns A `TlvType` pointer to `aTlv`.
616 *
617 */
As(const Tlv * aTlv)618 template <class TlvType> const TlvType *As(const Tlv *aTlv) { return static_cast<const TlvType *>(aTlv); }
619
620 /**
621 * Casts a `Tlv` reference to a given subclass `TlvType` reference.
622 *
623 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
624 *
625 * @param[in] aTlv A reference to a `Tlv` to convert/cast to a `TlvType`.
626 *
627 * @returns A `TlvType` reference to `aTlv`.
628 *
629 */
As(Tlv & aTlv)630 template <class TlvType> TlvType &As(Tlv &aTlv) { return static_cast<TlvType &>(aTlv); }
631
632 /**
633 * Casts a `Tlv` reference to a given subclass `TlvType` reference.
634 *
635 * @tparam TlvType The TLV type to cast into. MUST be a subclass of `Tlv`.
636 *
637 * @param[in] aTlv A reference to a `Tlv` to convert/cast to a `TlvType`.
638 *
639 * @returns A `TlvType` reference to `aTlv`.
640 *
641 */
As(const Tlv & aTlv)642 template <class TlvType> const TlvType &As(const Tlv &aTlv) { return static_cast<const TlvType &>(aTlv); }
643
644 /**
645 * Defines constants for a TLV.
646 *
647 * @tparam kTlvTypeValue The TLV Type value.
648 *
649 */
650 template <uint8_t kTlvTypeValue> class TlvInfo
651 {
652 public:
653 static constexpr uint8_t kType = kTlvTypeValue; ///< The TLV Type value.
654 };
655
656 /**
657 * Defines constants and types for a simple TLV with an unsigned int value type.
658 *
659 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<UintTlvType>()`, and
660 * the related `Tlv::Find<UintTlvType>()` and `Tlv::Read<UintTlvType>()`.
661 *
662 * @tparam kTlvTypeValue The TLV Type value.
663 * @tparam UintType The TLV Value's type (must be an unsigned int, i.e. uint8_t, uint16_t, or uint32_t).
664 *
665 */
666 template <uint8_t kTlvTypeValue, typename UintType> class UintTlvInfo : public TlvInfo<kTlvTypeValue>
667 {
668 public:
669 static_assert(TypeTraits::IsSame<UintType, uint8_t>::kValue || TypeTraits::IsSame<UintType, uint16_t>::kValue ||
670 TypeTraits::IsSame<UintType, uint32_t>::kValue,
671 "UintTlv must be used used with unsigned int value type");
672
673 typedef UintType UintValueType; ///< The TLV Value unsigned int type.
674 };
675
676 /**
677 * Defines constants and types for a simple TLV with a single value.
678 *
679 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<SimpleTlvType>()`,
680 * and the related `Tlv::Find<SimpleTlvType>()` and `Tlv::Read<SimpleTlvType>()`.
681 *
682 * @tparam kTlvTypeValue The TLV Type value.
683 * @tparam TlvValueType The TLV Value's type (must not be an integral type).
684 *
685 */
686 template <uint8_t kTlvTypeValue, typename TlvValueType> class SimpleTlvInfo : public TlvInfo<kTlvTypeValue>
687 {
688 public:
689 static_assert(!TypeTraits::IsPointer<TlvValueType>::kValue, "TlvValueType must not be a pointer");
690 static_assert(!TypeTraits::IsSame<TlvValueType, uint8_t>::kValue, "SimpleTlv must not use int value type");
691 static_assert(!TypeTraits::IsSame<TlvValueType, uint16_t>::kValue, "SimpleTlv must not use int value type");
692 static_assert(!TypeTraits::IsSame<TlvValueType, uint32_t>::kValue, "SimpleTlv must not use int value type");
693 static_assert(!TypeTraits::IsSame<TlvValueType, int8_t>::kValue, "SimpleTlv must not use int value type");
694 static_assert(!TypeTraits::IsSame<TlvValueType, int16_t>::kValue, "SimpleTlv must not use int value type");
695 static_assert(!TypeTraits::IsSame<TlvValueType, int32_t>::kValue, "SimpleTlv must not use int value type");
696
697 typedef TlvValueType ValueType; ///< The TLV Value type.
698 };
699
700 /**
701 * Defines constants and types for a simple TLV with a UTF-8 string value.
702 *
703 * This class and its sub-classes are intended to be used as the template type in `Tlv::Append<StringTlvType>()`,
704 * and the related `Tlv::Find<StringTlvType>()` and `Tlv::Read<StringTlvType>()`.
705 *
706 * @tparam kTlvTypeValue The TLV Type value.
707 * @tparam kTlvMaxValueLength The maximum allowed string length (as TLV value).
708 *
709 */
710 template <uint8_t kTlvTypeValue, uint8_t kTlvMaxValueLength> class StringTlvInfo : public TlvInfo<kTlvTypeValue>
711 {
712 public:
713 static constexpr uint8_t kMaxStringLength = kTlvMaxValueLength; ///< Maximum string length.
714
715 typedef char StringType[kMaxStringLength + 1]; ///< String buffer for TLV value.
716 };
717
718 } // namespace ot
719
720 #endif // TLVS_HPP_
721