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 manipulating MeshCoP timestamps.
32  *
33  */
34 
35 #ifndef MESHCOP_TIMESTAMP_HPP_
36 #define MESHCOP_TIMESTAMP_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include <string.h>
41 
42 #include <openthread/dataset.h>
43 #include <openthread/platform/toolchain.h>
44 
45 #include "common/clearable.hpp"
46 #include "common/encoding.hpp"
47 #include "common/random.hpp"
48 
49 namespace ot {
50 namespace MeshCoP {
51 
52 using ot::Encoding::BigEndian::HostSwap16;
53 using ot::Encoding::BigEndian::HostSwap32;
54 
55 /**
56  * This class implements Timestamp generation and parsing.
57  *
58  */
59 OT_TOOL_PACKED_BEGIN
60 class Timestamp : public Clearable<Timestamp>
61 {
62 public:
63     /**
64      * This method converts the timestamp to `otTimestamp`.
65      *
66      */
67     void ConvertTo(otTimestamp &aTimestamp) const;
68 
69     /**
70      * This method sets the timestamp from `otTimestamp`.
71      *
72      */
73     void SetFromTimestamp(const otTimestamp &aTimestamp);
74 
75     /**
76      * This method returns the Seconds value.
77      *
78      * @returns The Seconds value.
79      *
80      */
GetSeconds(void) const81     uint64_t GetSeconds(void) const
82     {
83         return (static_cast<uint64_t>(HostSwap16(mSeconds16)) << 32) + HostSwap32(mSeconds32);
84     }
85 
86     /**
87      * This method sets the Seconds value.
88      *
89      * @param[in]  aSeconds  The Seconds value.
90      *
91      */
SetSeconds(uint64_t aSeconds)92     void SetSeconds(uint64_t aSeconds)
93     {
94         mSeconds16 = HostSwap16(static_cast<uint16_t>(aSeconds >> 32));
95         mSeconds32 = HostSwap32(static_cast<uint32_t>(aSeconds & 0xffffffff));
96     }
97 
98     /**
99      * This method returns the Ticks value.
100      *
101      * @returns The Ticks value.
102      *
103      */
GetTicks(void) const104     uint16_t GetTicks(void) const { return HostSwap16(mTicks) >> kTicksOffset; }
105 
106     /**
107      * This method sets the Ticks value.
108      *
109      * @param[in]  aTicks  The Ticks value.
110      *
111      */
SetTicks(uint16_t aTicks)112     void SetTicks(uint16_t aTicks)
113     {
114         mTicks = HostSwap16((HostSwap16(mTicks) & ~kTicksMask) | ((aTicks << kTicksOffset) & kTicksMask));
115     }
116 
117     /**
118      * This method returns the Authoritative value.
119      *
120      * @returns The Authoritative value.
121      *
122      */
GetAuthoritative(void) const123     bool GetAuthoritative(void) const { return (HostSwap16(mTicks) & kAuthoritativeMask) != 0; }
124 
125     /**
126      * This method sets the Authoritative value.
127      *
128      * @param[in]  aAuthoritative  The Authoritative value.
129      *
130      */
SetAuthoritative(bool aAuthoritative)131     void SetAuthoritative(bool aAuthoritative)
132     {
133         mTicks = HostSwap16((HostSwap16(mTicks) & kTicksMask) |
134                             ((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask));
135     }
136 
137     /**
138      * This method increments the timestamp by a random number of ticks [0, 32767].
139      *
140      */
141     void AdvanceRandomTicks(void);
142 
143     /**
144      * This method indicates whether the timestamp indicates an MLE Orphan Announce message.
145      *
146      * @retval TRUE   The timestamp indicates an Orphan Announce message.
147      * @retval FALSE  If the timestamp does not indicate an Orphan Announce message.
148      *
149      */
IsOrphanTimestamp(void) const150     bool IsOrphanTimestamp(void) const { return GetSeconds() == 0 && GetTicks() == 0 && GetAuthoritative(); }
151 
152     /**
153      * This static method compares two timestamps.
154      *
155      * Either one or both @p aFirst or @p aSecond can be `nullptr`. A non-null timestamp is considered greater than
156      * a null one. If both are null, they are considered as equal.
157      *
158      * @param[in]  aFirst   A pointer to the first timestamp to compare (can be nullptr).
159      * @param[in]  aSecond  A pointer to the second timestamp to compare (can be nullptr).
160      *
161      * @retval -1  if @p aFirst is less than @p aSecond (`aFirst < aSecond`).
162      * @retval  0  if @p aFirst is equal to @p aSecond (`aFirst == aSecond`).
163      * @retval  1  if @p aFirst is greater than @p aSecond (`aFirst > aSecond`).
164      *
165      */
166     static int Compare(const Timestamp *aFirst, const Timestamp *aSecond);
167 
168     /**
169      * This static method compares two timestamps.
170      *
171      * @param[in]  aFirst   A reference to the first timestamp to compare.
172      * @param[in]  aSecond  A reference to the second timestamp to compare.
173      *
174      * @retval -1  if @p aFirst is less than @p aSecond (`aFirst < aSecond`).
175      * @retval  0  if @p aFirst is equal to @p aSecond (`aFirst == aSecond`).
176      * @retval  1  if @p aFirst is greater than @p aSecond (`aFirst > aSecond`).
177      *
178      */
179     static int Compare(const Timestamp &aFirst, const Timestamp &aSecond);
180 
181 private:
182     static constexpr uint8_t  kTicksOffset         = 1;
183     static constexpr uint16_t kTicksMask           = 0x7fff << kTicksOffset;
184     static constexpr uint16_t kMaxRandomTicks      = 0x7fff;
185     static constexpr uint8_t  kAuthoritativeOffset = 0;
186     static constexpr uint16_t kAuthoritativeMask   = 1 << kAuthoritativeOffset;
187 
188     uint16_t mSeconds16; // bits 32-47
189     uint32_t mSeconds32; // bits 0-31
190     uint16_t mTicks;
191 } OT_TOOL_PACKED_END;
192 
193 } // namespace MeshCoP
194 } // namespace ot
195 
196 #endif // MESHCOP_TIMESTAMP_HPP_
197