1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for the message buffer pool and message buffers.
*/
#ifndef MESSAGE_HPP_
#define MESSAGE_HPP_
#include "openthread-core-config.h"
#include <stdint.h>
#include <openthread/message.h>
#include <openthread/platform/messagepool.h>
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "mac/mac_types.hpp"
#include "thread/link_quality.hpp"
namespace ot {
/**
* @addtogroup core-message
*
* @brief
* This module includes definitions for the message buffer pool and message buffers.
*
* @{
*
*/
enum
{
kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS,
kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE,
kChildMaskBytes = BitVectorBytes(OPENTHREAD_CONFIG_MLE_MAX_CHILDREN),
};
class Message;
class MessagePool;
class MessageQueue;
class PriorityQueue;
/**
* This structure contains metadata about a Message.
*
*/
struct MessageMetadata
{
Message * mNext; ///< A pointer to the next Message in a doubly linked list.
Message * mPrev; ///< A pointer to the previous Message in a doubly linked list.
MessagePool *mMessagePool; ///< Identifies the message pool for this message.
union
{
MessageQueue * mMessage; ///< Identifies the message queue (if any) where this message is queued.
PriorityQueue *mPriority; ///< Identifies the priority queue (if any) where this message is queued.
} mQueue; ///< Identifies the queue (if any) where this message is queued.
uint32_t mDatagramTag; ///< The datagram tag used for 6LoWPAN fragmentation or identification used for IPv6
///< fragmentation.
uint16_t mReserved; ///< Number of header bytes reserved for the message.
uint16_t mLength; ///< Number of bytes within the message.
uint16_t mOffset; ///< A byte offset within the message.
RssAverager mRssAverager; ///< The averager maintaining the received signal strength (RSS) average.
uint8_t mChildMask[kChildMaskBytes]; ///< A bit-vector to indicate which sleepy children need to receive this.
uint16_t mMeshDest; ///< Used for unicast non-link-local messages.
uint8_t mTimeout; ///< Seconds remaining before dropping the message.
union
{
uint16_t mPanId; ///< Used for MLE Discover Request and Response messages.
uint8_t mChannel; ///< Used for MLE Announce.
} mPanIdChannel; ///< Used for MLE Discover Request, Response, and Announce messages.
uint8_t mType : 2; ///< Identifies the type of message.
uint8_t mSubType : 4; ///< Identifies the message sub type.
bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required.
bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled.
uint8_t mPriority : 2; ///< Identifies the message priority level (higher value is higher priority).
bool mInPriorityQ : 1; ///< Indicates whether the message is queued in normal or priority queue.
bool mTxSuccess : 1; ///< Indicates whether the direct tx of the message was successful.
bool mDoNotEvict : 1; ///< Indicates whether or not this message may be evicted.
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
bool mTimeSync : 1; ///< Indicates whether the message is also used for time sync purpose.
uint8_t mTimeSyncSeq; ///< The time sync sequence.
int64_t mNetworkTimeOffset; ///< The time offset to the Thread network time, in microseconds.
#endif
};
/**
* This class represents a Message buffer.
*
*/
class Buffer : public otMessage, public LinkedListEntry<Buffer>
{
friend class Message;
public:
/**
* This method returns a pointer to the next message buffer.
*
* @returns A pointer to the next message buffer.
*
*/
Buffer *GetNextBuffer(void) { return GetNext(); }
/**
* This method returns a pointer to the next message buffer.
*
* @returns A pointer to the next message buffer.
*
*/
const Buffer *GetNextBuffer(void) const { return GetNext(); }
/**
* This method sets the pointer to the next message buffer.
*
* @param[in] aNext A pointer to the next buffer.
*
*/
void SetNextBuffer(Buffer *aNext) { SetNext(aNext); }
private:
/**
* This method returns the message metadata in the first message buffer.
*
* @returns The message metadata structure.
*
*/
MessageMetadata &GetMetadata(void) { return mBuffer.mHead.mMetadata; }
/**
* This method returns the message metadata in the first message buffer.
*
* @returns The message metadata structure.
*
*/
const MessageMetadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; }
/**
* This method returns a pointer to the first byte of data in the first message buffer.
*
* @returns A pointer to the first data byte.
*
*/
uint8_t *GetFirstData(void) { return mBuffer.mHead.mData; }
/**
* This method returns a pointer to the first byte of data in the first message buffer.
*
* @returns A pointer to the first data byte.
*
*/
const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; }
/**
* This method returns a pointer to the first data byte of a subsequent message buffer.
*
* @returns A pointer to the first data byte.
*
*/
uint8_t *GetData(void) { return mBuffer.mData; }
/**
* This method returns a pointer to the first data byte of a subsequent message buffer.
*
* @returns A pointer to the first data byte.
*
*/
const uint8_t *GetData(void) const { return mBuffer.mData; }
enum
{
kBufferDataSize = kBufferSize - sizeof(otMessage),
kHeadBufferDataSize = kBufferDataSize - sizeof(MessageMetadata),
};
protected:
union
{
struct
{
MessageMetadata mMetadata;
uint8_t mData[kHeadBufferDataSize];
} mHead;
uint8_t mData[kBufferDataSize];
} mBuffer;
};
/**
* This class represents a message.
*
*/
class Message : public Buffer
{
friend class MessagePool;
friend class MessageQueue;
friend class PriorityQueue;
public:
/**
* This enumeration represents the message type.
*
*/
enum Type
{
kTypeIp6 = 0, ///< A full uncompressed IPv6 packet
kType6lowpan = 1, ///< A 6lowpan frame
kTypeSupervision = 2, ///< A child supervision frame.
kTypeOther = 3, ///< Other (data) message.
};
/**
* This enumeration represents the message sub-type.
*
*/
enum SubType
{
kSubTypeNone = 0, ///< None
kSubTypeMleAnnounce = 1, ///< MLE Announce
kSubTypeMleDiscoverRequest = 2, ///< MLE Discover Request
kSubTypeMleDiscoverResponse = 3, ///< MLE Discover Response
kSubTypeJoinerEntrust = 4, ///< Joiner Entrust
kSubTypeMplRetransmission = 5, ///< MPL next retransmission message
kSubTypeMleGeneral = 6, ///< General MLE
kSubTypeJoinerFinalizeResponse = 7, ///< Joiner Finalize Response
kSubTypeMleChildUpdateRequest = 8, ///< MLE Child Update Request
kSubTypeMleDataResponse = 9, ///< MLE Data Response
kSubTypeMleChildIdRequest = 10, ///< MLE Child ID Request
};
enum Priority
{
kPriorityLow = OT_MESSAGE_PRIORITY_LOW, ///< Low priority level.
kPriorityNormal = OT_MESSAGE_PRIORITY_NORMAL, ///< Normal priority level.
kPriorityHigh = OT_MESSAGE_PRIORITY_HIGH, ///< High priority level.
kPriorityNet = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
};
enum
{
kNumPriorities = 4, ///< Number of priority levels.
};
/**
* This enumeration represents the link security mode (used by `Settings` constructor).
*
*/
enum LinkSecurityMode
{
kNoLinkSecurity, ///< Link security disabled (no link security).
kWithLinkSecurity, ///< Link security enabled.
};
/**
* This class represents settings used for creating a new message.
*
*/
class Settings
{
public:
/**
* This constructor initializes the Settings object.
*
* @param[in] aSecurityMode A link security mode.
* @param[in] aPriority A message priority.
*
*/
Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
/**
* This constructor initializes the `Settings` object from a given `otMessageSettings`.
*
* @param[in] aSettings A pointer to `otMessageSettings` to covert from. If NULL default settings (link
* security enabled with `kPriorityNormal` priority) would be used.
*
*/
Settings(const otMessageSettings *aSettings);
/**
* This method gets the message priority.
*
* @returns The message priority.
*
*/
Priority GetPriority(void) const { return mPriority; }
/**
* This method indicates whether the link security should be enabled.
*
* @returns TRUE if link security should be enabled, FALSE otherwise.
*
*/
bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; }
/**
* This static method returns the default settings with link security enabled and `kPriorityNormal` priority.
*
* @returns A reference to the default settings (link security enable and `kPriorityNormal` priority).
*
*/
static const Settings &GetDefault(void) { return kDefault; }
private:
static const Settings kDefault;
bool mLinkSecurityEnabled;
Priority mPriority;
};
/**
* This method frees this message buffer.
*
*/
void Free(void);
/**
* This method returns a pointer to the next message.
*
* @returns A pointer to the next message in the list or NULL if at the end of the list.
*
*/
Message *GetNext(void) const;
/**
* This method returns the number of bytes in the message.
*
* @returns The number of bytes in the message.
*/
uint16_t GetLength(void) const { return GetMetadata().mLength; }
/**
* This method sets the number of bytes in the message.
*
* @param[in] aLength Requested number of bytes in the message.
*
* @retval OT_ERROR_NONE Successfully set the length of the message.
* @retval OT_ERROR_NO_BUFS Failed to grow the size of the message because insufficient buffers were available.
*
*/
otError SetLength(uint16_t aLength);
/**
* This method returns the number of buffers in the message.
*
*/
uint8_t GetBufferCount(void) const;
/**
* This method returns the byte offset within the message.
*
* @returns A byte offset within the message.
*
*/
uint16_t GetOffset(void) const { return GetMetadata().mOffset; }
/**
* This method moves the byte offset within the message.
*
* @param[in] aDelta The number of bytes to move the current offset, which may be positive or negative.
*
*/
void MoveOffset(int aDelta);
/**
* This method sets the byte offset within the message.
*
* @param[in] aOffset The byte offset within the message.
*
*/
void SetOffset(uint16_t aOffset);
/**
* This method returns the type of the message.
*
* @returns The type of the message.
*
*/
Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); }
/**
* This method sets the message type.
*
* @param[in] aType The message type.
*
*/
void SetType(Type aType) { GetMetadata().mType = aType; }
/**
* This method returns the sub type of the message.
*
* @returns The sub type of the message.
*
*/
SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); }
/**
* This method sets the message sub type.
*
* @param[in] aSubType The message sub type.
*
*/
void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; }
/**
* This method returns whether or not the message is of MLE subtype.
*
* @retval TRUE If message is of MLE subtype.
* @retval FALSE If message is not of MLE subtype.
*
*/
bool IsSubTypeMle(void) const;
/**
* This method returns the message priority level.
*
* @returns The priority level associated with this message.
*
*/
Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); }
/**
* This method sets the messages priority.
* If the message is already queued in a priority queue, changing the priority ensures to
* update the message in the associated queue.
*
* @param[in] aPriority The message priority level.
*
* @retval OT_ERROR_NONE Successfully set the priority for the message.
* @retval OT_ERROR_INVALID_ARGS Priority level is not invalid.
*
*/
otError SetPriority(Priority aPriority);
/**
* This method prepends bytes to the front of the message.
*
* On success, this method grows the message by @p aLength bytes.
*
* @param[in] aBuf A pointer to a data buffer.
* @param[in] aLength The number of bytes to prepend.
*
* @retval OT_ERROR_NONE Successfully prepended the bytes.
* @retval OT_ERROR_NO_BUFS Not enough reserved bytes in the message.
*
*/
otError Prepend(const void *aBuf, uint16_t aLength);
/**
* This method removes header bytes from the message.
*
* @param[in] aLength Number of header bytes to remove.
*
*/
void RemoveHeader(uint16_t aLength);
/**
* This method appends bytes to the end of the message.
*
* On success, this method grows the message by @p aLength bytes.
*
* @param[in] aBuf A pointer to a data buffer.
* @param[in] aLength The number of bytes to append.
*
* @retval OT_ERROR_NONE Successfully appended the bytes.
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
*
*/
otError Append(const void *aBuf, uint16_t aLength);
/**
* This method reads bytes from the message.
*
* @param[in] aOffset Byte offset within the message to begin reading.
* @param[in] aLength Number of bytes to read.
* @param[in] aBuf A pointer to a data buffer.
*
* @returns The number of bytes read.
*
*/
uint16_t Read(uint16_t aOffset, uint16_t aLength, void *aBuf) const;
/**
* This method writes bytes to the message.
*
* @param[in] aOffset Byte offset within the message to begin writing.
* @param[in] aLength Number of bytes to write.
* @param[in] aBuf A pointer to a data buffer.
*
* @returns The number of bytes written.
*
*/
int Write(uint16_t aOffset, uint16_t aLength, const void *aBuf);
/**
* This method copies bytes from one message to another.
*
* @param[in] aSourceOffset Byte offset within the source message to begin reading.
* @param[in] aDestinationOffset Byte offset within the destination message to begin writing.
* @param[in] aLength Number of bytes to copy.
* @param[in] aMessage Message to copy to.
*
* @returns The number of bytes copied.
*
*/
int CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_t aLength, Message &aMessage) const;
/**
* This method creates a copy of the message.
*
* It allocates the new message from the same message pool as the original one and copies @p aLength octets
* of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
* cloned message are also copied from the original one.
*
* @param[in] aLength Number of payload bytes to copy.
*
* @returns A pointer to the message or NULL if insufficient message buffers are available.
*
*/
Message *Clone(uint16_t aLength) const;
/**
* This method creates a copy of the message.
*
* It allocates the new message from the same message pool as the original one and copies the entire payload. The
* `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
* copied from the original one.
*
* @returns A pointer to the message or NULL if insufficient message buffers are available.
*
*/
Message *Clone(void) const { return Clone(GetLength()); }
/**
* This method returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6
* fragmentation.
*
* @returns The 6LoWPAN datagram tag or the IPv6 fragment identification.
*
*/
uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; }
/**
* This method sets the datagram tag used for 6LoWPAN fragmentation.
*
* @param[in] aTag The 6LoWPAN datagram tag.
*
*/
void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
/**
* This method returns whether or not the message forwarding is scheduled for the child.
*
* @param[in] aChildIndex The index into the child table.
*
* @retval TRUE If the message is scheduled to be forwarded to the child.
* @retval FALSE If the message is not scheduled to be forwarded to the child.
*
*/
bool GetChildMask(uint16_t aChildIndex) const;
/**
* This method unschedules forwarding of the message to the child.
*
* @param[in] aChildIndex The index into the child table.
*
*/
void ClearChildMask(uint16_t aChildIndex);
/**
* This method schedules forwarding of the message to the child.
*
* @param[in] aChildIndex The index into the child table.
*
*/
void SetChildMask(uint16_t aChildIndex);
/**
* This method returns whether or not the message forwarding is scheduled for at least one child.
*
* @retval TRUE If message forwarding is scheduled for at least one child.
* @retval FALSE If message forwarding is not scheduled for any child.
*
*/
bool IsChildPending(void) const;
/**
* This method returns the RLOC16 of the mesh destination.
*
* @note Only use this for non-link-local unicast messages.
*
* @returns The IEEE 802.15.4 Destination PAN ID.
*
*/
uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; }
/**
* This method sets the RLOC16 of the mesh destination.
*
* @note Only use this when sending non-link-local unicast messages.
*
* @param[in] aMeshDest The IEEE 802.15.4 Destination PAN ID.
*
*/
void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; }
/**
* This method returns the IEEE 802.15.4 Destination PAN ID.
*
* @note Only use this when sending MLE Discover Request or Response messages.
*
* @returns The IEEE 802.15.4 Destination PAN ID.
*
*/
uint16_t GetPanId(void) const { return GetMetadata().mPanIdChannel.mPanId; }
/**
* This method sets the IEEE 802.15.4 Destination PAN ID.
*
* @note Only use this when sending MLE Discover Request or Response messages.
*
* @param[in] aPanId The IEEE 802.15.4 Destination PAN ID.
*
*/
void SetPanId(uint16_t aPanId) { GetMetadata().mPanIdChannel.mPanId = aPanId; }
/**
* This method returns the IEEE 802.15.4 Channel to use for transmission.
*
* @note Only use this when sending MLE Announce messages.
*
* @returns The IEEE 802.15.4 Channel to use for transmission.
*
*/
uint8_t GetChannel(void) const { return GetMetadata().mPanIdChannel.mChannel; }
/**
* This method sets the IEEE 802.15.4 Channel to use for transmission.
*
* @note Only use this when sending MLE Announce messages.
*
* @param[in] aChannel The IEEE 802.15.4 Channel to use for transmission.
*
*/
void SetChannel(uint8_t aChannel) { GetMetadata().mPanIdChannel.mChannel = aChannel; }
/**
* This method returns the timeout used for 6LoWPAN reassembly.
*
* @returns The time remaining in seconds.
*
*/
uint8_t GetTimeout(void) const { return GetMetadata().mTimeout; }
/**
* This method sets the timeout used for 6LoWPAN reassembly.
*
* @param[in] aTimeout The timeout value.
*
*/
void SetTimeout(uint8_t aTimeout) { GetMetadata().mTimeout = aTimeout; }
/**
* This method decrements the timeout.
*
*/
void DecrementTimeout(void) { GetMetadata().mTimeout--; }
/**
* This method returns whether or not message forwarding is scheduled for direct transmission.
*
* @retval TRUE If message forwarding is scheduled for direct transmission.
* @retval FALSE If message forwarding is not scheduled for direct transmission.
*
*/
bool GetDirectTransmission(void) const { return GetMetadata().mDirectTx; }
/**
* This method unschedules forwarding using direct transmission.
*
*/
void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
/**
* This method schedules forwarding using direct transmission.
*
*/
void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
/**
* This method indicates whether the direct transmission of message was successful.
*
* @retval TRUE If direct transmission of message was successful (all fragments were delivered and acked).
* @retval FALSE If direct transmission of message failed (at least one fragment failed).
*
*/
bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; }
/**
* This method sets whether the direct transmission of message was successful.
*
* @param[in] aTxSuccess TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
* fragment transmission failed).
*
*/
void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; }
/**
* This method indicates whether the message may be evicted.
*
* @retval TRUE If the message must not be evicted.
* @retval FALSE If the message may be evicted.
*
*/
bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; }
/**
* This method sets whether the message may be evicted.
*
* @param[in] aDoNotEvict TRUE if the message may not be evicted, FALSE otherwise.
*
*/
void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
/**
* This method indicates whether or not link security is enabled for the message.
*
* @retval TRUE If link security is enabled.
* @retval FALSE If link security is not enabled.
*
*/
bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; }
/**
* This method sets whether or not link security is enabled for the message.
*
* @param[in] aEnabled TRUE if link security is enabled, FALSE otherwise.
*
*/
void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; }
/**
* This method updates the average RSS (Received Signal Strength) associated with the message by adding the given
* RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each
* received with a different signal strength.
*
* @param[in] aRss A new RSS value (in dBm) to be added to average.
*
*/
void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); }
/**
* This method returns the average RSS (Received Signal Strength) associated with the message.
*
* @returns The current average RSS value (in dBm) or OT_RADIO_RSSI_INVALID if no average is available.
*
*/
int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
/**
* This method returns a const reference to RssAverager of the message.
*
* @returns A const reference to the RssAverager of the message.
*
*/
const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; }
/**
* This static method updates a checksum.
*
* @param[in] aChecksum The checksum value to update.
* @param[in] aValue The 16-bit value to update @p aChecksum with.
*
* @returns The updated checksum.
*
*/
static uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aValue);
/**
* This static method updates a checksum.
*
* @param[in] aChecksum The checksum value to update.
* @param[in] aBuf A pointer to a buffer.
* @param[in] aLength The number of bytes in @p aBuf.
*
* @returns The updated checksum.
*
*/
static uint16_t UpdateChecksum(uint16_t aChecksum, const void *aBuf, uint16_t aLength);
/**
* This method is used to update a checksum value.
*
* @param[in] aChecksum Initial checksum value.
* @param[in] aOffset Byte offset within the message to begin checksum computation.
* @param[in] aLength Number of bytes to compute the checksum over.
*
* @retval The updated checksum value.
*
*/
uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const;
/**
* This method returns a pointer to the message queue (if any) where this message is queued.
*
* @returns A pointer to the message queue or NULL if not in any message queue.
*
*/
MessageQueue *GetMessageQueue(void) const
{
return (!GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mMessage : NULL;
}
/**
* This method returns a pointer to the priority message queue (if any) where this message is queued.
*
* @returns A pointer to the priority queue or NULL if not in any priority queue.
*
*/
PriorityQueue *GetPriorityQueue(void) const
{
return (GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mPriority : NULL;
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
* This method indicates whether or not the message is also used for time sync purpose.
*
* @retval TRUE If the message is also used for time sync purpose.
* @retval FALSE If the message is not used for time sync purpose.
*
*/
bool IsTimeSync(void) const { return GetMetadata().mTimeSync; }
/**
* This method sets whether or not the message is also used for time sync purpose.
*
* @param[in] aEnabled TRUE if the message is also used for time sync purpose, FALSE otherwise.
*
*/
void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; }
/**
* This method sets the offset to network time.
*
* @param[in] aNetworkTimeOffset The offset to network time.
*
*/
void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
/**
* This method gets the offset to network time.
*
* @returns The offset to network time.
*
*/
int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
/**
* This method sets the time sync sequence.
*
* @param[in] aTimeSyncSeq The time sync sequence.
*
*/
void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
/**
* This method gets the time sync sequence.
*
* @returns The time sync sequence.
*
*/
uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
private:
/**
* This method returns a pointer to the message pool to which this message belongs
*
* @returns A pointer to the message pool.
*
*/
MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
/**
* This method sets the message pool this message to which this message belongs.
*
* @param[in] aMessagePool A pointer to the message pool
*
*/
void SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
/**
* This method returns `true` if the message is enqueued in any queue (`MessageQueue` or `PriorityQueue`).
*
* @returns `true` if the message is in any queue, `false` otherwise.
*
*/
bool IsInAQueue(void) const { return (GetMetadata().mQueue.mMessage != NULL); }
/**
* This method sets the message queue information for the message.
*
* @param[in] aMessageQueue A pointer to the message queue where this message is queued.
*
*/
void SetMessageQueue(MessageQueue *aMessageQueue);
/**
* This method sets the message queue information for the message.
*
* @param[in] aPriorityQueue A pointer to the priority queue where this message is queued.
*
*/
void SetPriorityQueue(PriorityQueue *aPriorityQueue);
/**
* This method returns a reference to the `mNext` pointer.
*
* @returns A reference to the mNext pointer.
*
*/
Message *&Next(void) { return GetMetadata().mNext; }
/**
* This method returns a reference to the `mNext` pointer (const pointer).
*
*
* @returns A reference to the mNext pointer.
*
*/
Message *const &Next(void) const { return GetMetadata().mNext; }
/**
* This method returns a reference to the `mPrev` pointer.
*
* @returns A reference to the mPrev pointer.
*
*/
Message *&Prev(void) { return GetMetadata().mPrev; }
/**
* This method returns the number of reserved header bytes.
*
* @returns The number of reserved header bytes.
*
*/
uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
/**
* This method sets the number of reserved header bytes.
*
* @param[in] aReservedHeader The number of header bytes to reserve.
*
*/
void SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
/**
* This method adds or frees message buffers to meet the requested length.
*
* @param[in] aLength The number of bytes that the message buffer needs to handle.
*
* @retval OT_ERROR_NONE Successfully resized the message.
* @retval OT_ERROR_NO_BUFS Could not grow the message due to insufficient available message buffers.
*
*/
otError ResizeMessage(uint16_t aLength);
};
/**
* This class implements a message queue.
*
*/
class MessageQueue : public otMessageQueue
{
friend class Message;
friend class PriorityQueue;
public:
/**
* This enumeration represents a position (head or tail) in the queue. This is used to specify where a new message
* should be added in the queue.
*
*/
enum QueuePosition
{
kQueuePositionHead, ///< Indicates the head (front) of the list.
kQueuePositionTail, ///< Indicates the tail (end) of the list.
};
/**
* This constructor initializes the message queue.
*
*/
MessageQueue(void);
/**
* This method returns a pointer to the first message.
*
* @returns A pointer to the first message.
*
*/
Message *GetHead(void) const;
/**
* This method adds a message to the end of the list.
*
* @param[in] aMessage The message to add.
*
*/
void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
/**
* This method adds a message at a given position (head/tail) of the list.
*
* @param[in] aMessage The message to add.
* @param[in] aPosition The position (head or tail) where to add the message.
*
*/
void Enqueue(Message &aMessage, QueuePosition aPosition);
/**
* This method removes a message from the list.
*
* @param[in] aMessage The message to remove.
*
*/
void Dequeue(Message &aMessage);
/**
* This method returns the number of messages and buffers enqueued.
*
* @param[out] aMessageCount Returns the number of messages enqueued.
* @param[out] aBufferCount Returns the number of buffers enqueued.
*
*/
void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
private:
/**
* This method returns the tail of the list (last message in the list)
*
* @returns A pointer to the tail of the list.
*
*/
Message *GetTail(void) const { return static_cast<Message *>(mData); }
/**
* This method set the tail of the list.
*
* @param[in] aMessage A pointer to the message to set as new tail.
*
*/
void SetTail(Message *aMessage) { mData = aMessage; }
};
/**
* This class implements a priority queue.
*
*/
class PriorityQueue
{
friend class Message;
friend class MessageQueue;
friend class MessagePool;
public:
/**
* This constructor initializes the priority queue.
*
*/
PriorityQueue(void);
/**
* This method returns a pointer to the first message.
*
* @returns A pointer to the first message.
*
*/
Message *GetHead(void) const;
/**
* This method returns a pointer to the first message for a given priority level.
*
* @param[in] aPriority Priority level.
*
* @returns A pointer to the first message with given priority level or NULL if there is no messages with
* this priority level.
*
*/
Message *GetHeadForPriority(Message::Priority aPriority) const;
/**
* This method adds a message to the queue.
*
* @param[in] aMessage The message to add.
*
*/
void Enqueue(Message &aMessage);
/**
* This method removes a message from the list.
*
* @param[in] aMessage The message to remove.
*
*/
void Dequeue(Message &aMessage);
/**
* This method returns the number of messages and buffers enqueued.
*
* @param[out] aMessageCount Returns the number of messages enqueued.
* @param[out] aBufferCount Returns the number of buffers enqueued.
*
*/
void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
/**
* This method returns the tail of the list (last message in the list)
*
* @returns A pointer to the tail of the list.
*
*/
Message *GetTail(void) const;
private:
/**
* This method increases (moves forward) the given priority while ensuring to wrap from
* priority value `kNumPriorities` -1 back to 0.
*
* @param[in] aPriority A given priority level
*
* @returns Increased/Moved forward priority level
*/
uint8_t PrevPriority(uint8_t aPriority) const
{
return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
}
/**
* This private method finds the first non-NULL tail starting from the given priority level and moving forward.
* It wraps from priority value `kNumPriorities` -1 back to 0.
*
* aStartPriorityLevel Starting priority level.
*
* @returns The first non-NULL tail pointer, or NULL if all the
*
*/
Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
private:
Message *mTails[Message::kNumPriorities]; ///< Tail pointers associated with different priority levels.
};
/**
* This class represents a message pool
*
*/
class MessagePool : public InstanceLocator, private NonCopyable
{
friend class Message;
friend class MessageQueue;
friend class PriorityQueue;
public:
/**
* This constructor initializes the object.
*
*/
explicit MessagePool(Instance &aInstance);
/**
* This method is used to obtain a new message.
*
* The link security is enabled by default on the newly obtained message.
*
* @param[in] aType The message type.
* @param[in] aReserveHeader The number of header bytes to reserve.
* @param[in] aPriority The priority level of the message.
*
* @returns A pointer to the message or NULL if no message buffers are available.
*
*/
Message *New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority);
public:
/**
* This method is used to obtain a new message with specified settings.
*
* @param[in] aType The message type.
* @param[in] aReserveHeader The number of header bytes to reserve.
* @param[in] aSettings The message settings.
*
* @returns A pointer to the message or NULL if no message buffers are available.
*
*/
Message *New(Message::Type aType,
uint16_t aReserveHeader,
const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method is used to free a message and return all message buffers to the buffer pool.
*
* @param[in] aMessage The message to free.
*
*/
void Free(Message *aMessage);
/**
* This method returns the number of free buffers.
*
* @returns The number of free buffers.
*
*/
uint16_t GetFreeBufferCount(void) const;
private:
Buffer *NewBuffer(Message::Priority aPriority);
void FreeBuffers(Buffer *aBuffer);
otError ReclaimBuffers(int aNumBuffers, Message::Priority aPriority);
#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT == 0
uint16_t mNumFreeBuffers;
Buffer mBuffers[kNumBuffers];
LinkedList<Buffer> mFreeBuffers;
#endif
};
/**
* @}
*
*/
} // namespace ot
#endif // MESSAGE_HPP_