Change script for apply upstream code
[platform/upstream/connectedhomeip.git] / src / lib / protocols / common / CHIPMessage.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2013-2017 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *      This file defines macros and objects commonly used for the
23  *      processing of CHIP messages.
24  *
25  */
26
27 #ifndef _CHIP_MESSAGE_H
28 #define _CHIP_MESSAGE_H
29
30 #include <core/CHIPEncoding.h>
31 #include <core/CHIPError.h>
32 #include <core/CHIPTLV.h>
33 #include <support/DLLUtil.h>
34
35 #include <system/SystemPacketBuffer.h>
36
37 /*
38  * these macros are the guts of the packing and parsing stuff and they're used
39  * everywhere.
40  *
41  * here are the writers
42  * parameters:
43  * - PTR, a pointer into a buffer of type uint8_t
44  * - VAL, a value to write
45  */
46 #define WRITEBYTE(PTR, VAL)                                                                                                        \
47     do                                                                                                                             \
48     {                                                                                                                              \
49         *(PTR)++ = (uint8_t)(VAL);                                                                                                 \
50     } while (0)
51
52 #define WRITE16(PTR, VAL)                                                                                                          \
53     do                                                                                                                             \
54     {                                                                                                                              \
55         WRITEBYTE((PTR), ((VAL) >> 0));                                                                                            \
56         WRITEBYTE((PTR), ((VAL) >> 8));                                                                                            \
57     } while (0)
58
59 #define WRITE32(PTR, VAL)                                                                                                          \
60     do                                                                                                                             \
61     {                                                                                                                              \
62         WRITEBYTE((PTR), ((VAL) >> 0));                                                                                            \
63         WRITEBYTE((PTR), ((VAL) >> 8));                                                                                            \
64         WRITEBYTE((PTR), ((VAL) >> 16));                                                                                           \
65         WRITEBYTE((PTR), ((VAL) >> 24));                                                                                           \
66     } while (0)
67
68 /*
69  * and the readers
70  * parameter: PTR, a pointer into a buffer of type uint8_t
71  * value: the value read form the buffer
72  */
73 #define READBYTE(PTR) (*(uint8_t *) (PTR)++)
74 /*
75  * parameters:
76  * - PTR, a pointer into a buffer of type uint8_t
77  * - DEST, where to put what's read from *p
78  */
79 #define READ16(PTR, DEST)                                                                                                          \
80     do                                                                                                                             \
81     {                                                                                                                              \
82         uint16_t __byte0 = (uint16_t) READBYTE(PTR);                                                                               \
83         uint16_t __byte1 = (uint16_t) READBYTE(PTR);                                                                               \
84         DEST             = __byte0 + (__byte1 << 8);                                                                               \
85     } while (0)
86
87 #define READ32(PTR, DEST)                                                                                                          \
88     do                                                                                                                             \
89     {                                                                                                                              \
90         uint16_t __byte0 = (uint16_t) READBYTE(PTR);                                                                               \
91         uint16_t __byte1 = (uint16_t) READBYTE(PTR);                                                                               \
92         uint16_t __byte2 = (uint16_t) READBYTE(PTR);                                                                               \
93         uint16_t __byte3 = (uint16_t) READBYTE(PTR);                                                                               \
94         DEST             = __byte0 + (__byte1 << 8) + (__byte2 << 16) + (__byte3 << 24);                                           \
95     } while (0)
96
97 /*
98  * the message iterator class allows packet handling to operate in
99  * a regular manner, do a bit of work, check the result, get out if
100  * it's not good and so on. this results in a bunch of boilerplate
101  * code, which is captured here.
102  */
103 #define TRY(OPERATION)                                                                                                             \
104     do                                                                                                                             \
105     {                                                                                                                              \
106         CHIP_ERROR e = (OPERATION);                                                                                                \
107         if (e != CHIP_NO_ERROR)                                                                                                    \
108             return e;                                                                                                              \
109     } while (0)
110
111 #define RESCUE(ERR, OPERATION, OUT)                                                                                                \
112     do                                                                                                                             \
113     {                                                                                                                              \
114         ERR = (OPERATION);                                                                                                         \
115         if (ERR != CHIP_NO_ERROR)                                                                                                  \
116             goto OUT;                                                                                                              \
117     } while (0)
118
119 namespace chip {
120
121 namespace Protocols {
122
123 /**
124  *  @class RetainedPacketBuffer
125  *
126  *  @brief
127  *    This is a base class that serves as a convenience object for
128  *    automatically reference counting a System::PacketBuffer.
129  *
130  */
131 class DLL_EXPORT RetainedPacketBuffer
132 {
133 public:
134     // Con/destructors
135     RetainedPacketBuffer();
136     RetainedPacketBuffer(const RetainedPacketBuffer & aRetainedPacketBuffer);
137     ~RetainedPacketBuffer();
138
139     RetainedPacketBuffer & operator=(const RetainedPacketBuffer & aRetainedPacketBuffer);
140
141     virtual bool IsRetaining() const;
142
143     void Retain(System::PacketBuffer * aBuffer);
144     virtual void Release();
145
146     inline System::PacketBuffer * GetBuffer() { return (mBuffer); }
147
148 protected:
149     System::PacketBuffer * mBuffer; ///< A pointer to the retained packet buffer.
150 };
151
152 /**
153  * In order to use message buffers sensibly, we define this iterator,
154  * which can be used to keep track of boundaries and so on.
155  */
156 class DLL_EXPORT MessageIterator : public RetainedPacketBuffer
157 {
158 public:
159     // constructor
160     MessageIterator(System::PacketBuffer *);
161     // reading and writing
162     CHIP_ERROR readByte(uint8_t *);
163     CHIP_ERROR read16(uint16_t *);
164     CHIP_ERROR read32(uint32_t *);
165     CHIP_ERROR read64(uint64_t *);
166     CHIP_ERROR readString(uint16_t, char *);
167     CHIP_ERROR readBytes(uint16_t, uint8_t *);
168     CHIP_ERROR writeByte(uint8_t);
169     CHIP_ERROR write16(uint16_t);
170     CHIP_ERROR write32(uint32_t);
171     CHIP_ERROR write64(uint64_t);
172     CHIP_ERROR writeString(uint16_t, char *);
173     CHIP_ERROR writeBytes(uint16_t, uint8_t *);
174     // standard iterator operations
175     MessageIterator & operator++();
176     MessageIterator & operator+(uint16_t);
177     MessageIterator & operator-(uint16_t);
178     bool operator==(const MessageIterator &);
179     bool operator!=(const MessageIterator &);
180     uint8_t & operator*();
181     void append();
182     // size checking
183     bool hasData(uint16_t);
184     bool hasRoom(uint16_t);
185     // finishing
186     void finishWriting();
187     // data members
188     uint8_t * thePoint;
189 };
190 /**
191  * Here's how to handle strings in CHIP. This class has 8-bit
192  * and 16-bit variants.
193  */
194 class DLL_EXPORT ReferencedString : public RetainedPacketBuffer
195 {
196 public:
197     // constructor
198     ReferencedString();
199     // initializers
200     CHIP_ERROR init(uint16_t aLength, char * aString, System::PacketBuffer * aBuffer);
201     CHIP_ERROR init(uint16_t aLength, char * aString);
202     CHIP_ERROR init(uint8_t aLength, char * aString, System::PacketBuffer * aBuffer);
203     CHIP_ERROR init(uint8_t aLength, char * aString);
204     // pack and parse
205     CHIP_ERROR pack(MessageIterator &);
206     static CHIP_ERROR parse(MessageIterator &, ReferencedString &);
207     // comparison
208     bool operator==(const ReferencedString &) const;
209     // print string generation (for testing)
210     char * printString();
211     // data members
212     uint16_t theLength;
213     char * theString;
214     bool isShort;
215 };
216 /**
217  * Similarly, we need to be able to represent a big old blob
218  * of TLV data.
219  */
220 class DLL_EXPORT ReferencedTLVData : public RetainedPacketBuffer
221 {
222 public:
223     /*
224      * under certain circumstances, e.g. when we don't want to blow out the
225      * stack by writing some big thing into it in preparation for sending
226      * a message with a referenced extent in it, we want to only write the
227      * bits AFTER we've obtained the outgoing buffer. we do that using one
228      * of these.
229      *
230      * NOTE!!! the handler set up below does NOT return an error and, in
231      * the case where one is supplied, the pack method will not return an
232      * error either. this means that the NHL-supplied handler MUST handler
233      * all errors that arise from the formatting of TLV.
234      *
235      * parameters:
236      * - TLVWriter&, a TLV writer to use to write things out
237      * - void*, a state object known to the application
238      */
239
240     typedef void (*TLVWriteCallback)(TLV::TLVWriter & aWriter, void * aAppState);
241
242     // constructor
243
244     ReferencedTLVData();
245
246     // initializers
247
248     CHIP_ERROR init(System::PacketBuffer * aBuffer);
249     CHIP_ERROR init(MessageIterator & i);
250     CHIP_ERROR init(uint16_t aLength, uint16_t aMaxLength, uint8_t * aByteString);
251     CHIP_ERROR init(TLVWriteCallback aWriteCallback, void * anAppState);
252
253     /*
254      * ReferencedTLVData needs to override the free() and isFree()
255      * methods because "freedom", in this case, is more than nothing
256      * left to lose.
257      */
258
259     void free();
260
261     bool isFree();
262
263     /**
264      * Check if a ReferencedTLVData object has anything in it.
265      *
266      * There are two possible ways such an object could "have"
267      * something. Either it could have 0 length OR it could have no
268      * write callback.
269      *
270      * @return true if the data set has 0 length or there's no write
271      * callback in hand, false otherwise.
272      */
273
274     inline bool isEmpty() { return (theLength == 0 && theWriteCallback == nullptr); }
275
276     // packing and parsing
277
278     /**
279      * @fn CHIP_ERROR ReferencedTLVData::pack(System::PacketBuffer *buff)
280      *
281      * @brief Pack a ReferencedTLVData object directly into a PacketBuffer
282      *
283      * @param [in] buff the buffer to fill.
284      *
285      * @return a CHIP_ERROR reflecting the success of the underlying
286      * pack call.
287      */
288
289     inline CHIP_ERROR pack(System::PacketBuffer * buff)
290     {
291         MessageIterator i(buff);
292
293         return pack(i);
294     }
295
296     CHIP_ERROR pack(MessageIterator & i, uint32_t maxLen = 0xFFFFFFFFUL);
297
298     /**
299      * Return the data length assuming that the object has been packed
300      * into a buffer.
301      *
302      * @return the integer length of the packed data.
303      */
304
305     inline uint16_t packedLength() { return theLength; }
306
307     /**
308      * @fn CHIP_ERROR parse(System::PacketBuffer *buff, ReferencedTLVData &aTarget)
309      *
310      * @brief Parse a ReferencedTLVData object from a supplied PacketBuffer
311      *
312      * Parse a ReferencedTLVData object out of an inet buffer
313      * (assuming it just contains TLV).
314      *
315      * @param [in] buff the buffer to read from.
316      *
317      * @param [out] aTarget a ReferencedTLVData object to "fill" with the result.
318      *
319      * @return a CHIP_ERROR reflecting the success of the underlying
320      * parse call.
321      */
322
323     static inline CHIP_ERROR parse(System::PacketBuffer * buff, ReferencedTLVData & aTarget)
324     {
325         MessageIterator i(buff);
326
327         return parse(i, aTarget);
328     }
329
330     static CHIP_ERROR parse(MessageIterator & i, ReferencedTLVData & aTarget);
331
332     // comparison
333
334     bool operator==(const ReferencedTLVData &) const;
335
336     // data members
337
338     uint16_t theLength;
339     uint16_t theMaxLength;
340     uint8_t * theData;
341
342 private:
343     TLVWriteCallback theWriteCallback;
344     void * theAppState;
345 };
346
347 } // namespace Protocols
348 } // namespace chip
349
350 #endif // _CHIP_MESSAGE_H