1 /*
2  * Copyright (c) 2020 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dmslite_packet.h"
17 
18 #include <stdbool.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 
22 #include "dmsfwk_interface.h"
23 #include "dmslite_inner_common.h"
24 #include "dmslite_log.h"
25 #include "dmslite_utils.h"
26 #include "securec.h"
27 
28 #define PACKET_DATA_SIZE 1024
29 #define TLV_LENGTH_SHIFT_BITS 7
30 #define LOW_BIT_MASK   0x7F
31 #define HIGH_BIT_MASK   0x80
32 #define BYTE_MASK   0xFF
33 #define METADATA_SIZE 16
34 
35 #define ONE_BYTE_BITS_NUM   8
36 #define ONE_BYTE_LENGTH   1
37 #define TYPE_FILED_LENGTH  1
38 
39 #define MIN_BYTE_NUM   1
40 #define MAX_BYTE_NUM   2
41 
42 static char g_buffer[PACKET_DATA_SIZE] = { 0 };
43 static uint16_t g_counter = 0;
44 
45 static bool StringToHex(const char *stringValue);
46 static void EncodeLengthOfTlv(uint16_t length);
47 static uint64_t ConvertIntLittle2Big(const uint8_t *dataIn, uint8_t typeSize);
48 static bool MarshallInt(uint64_t field, FieldType fieldType, uint8_t fieldSize);
49 static void IntToHex(uint64_t value, uint8_t typeSize);
50 
PreprareBuild()51 bool PreprareBuild()
52 {
53     g_counter = 0;
54     if (memset_s(g_buffer, PACKET_DATA_SIZE, 0x00, PACKET_DATA_SIZE) != EOK) {
55         HILOGW("Packet buffer is not cleared");
56         return false;
57     }
58     return true;
59 }
60 
CleanBuild()61 void CleanBuild()
62 {
63     g_counter = 0;
64     if (memset_s(g_buffer, PACKET_DATA_SIZE, 0x00, PACKET_DATA_SIZE) != EOK) {
65         HILOGW("Packet buffer is not cleared");
66     }
67 }
68 
MarshallUint8(uint8_t field,FieldType fieldType)69 bool MarshallUint8(uint8_t field, FieldType fieldType)
70 {
71     return MarshallInt(field, fieldType, sizeof(uint8_t));
72 }
73 
MarshallUint16(uint16_t field,FieldType fieldType)74 bool MarshallUint16(uint16_t field, FieldType fieldType)
75 {
76     return MarshallInt(field, fieldType, sizeof(uint16_t));
77 }
78 
MarshallUint32(uint32_t field,FieldType fieldType)79 bool MarshallUint32(uint32_t field, FieldType fieldType)
80 {
81     return MarshallInt(field, fieldType, sizeof(uint32_t));
82 }
83 
MarshallUint64(uint64_t field,FieldType fieldType)84 bool MarshallUint64(uint64_t field, FieldType fieldType)
85 {
86     return MarshallInt(field, fieldType, sizeof(uint16_t));
87 }
88 
MarshallInt8(int8_t field,FieldType fieldType)89 bool MarshallInt8(int8_t field, FieldType fieldType)
90 {
91     return MarshallInt(field, fieldType, sizeof(int8_t));
92 }
93 
MarshallInt16(int16_t field,FieldType fieldType)94 bool MarshallInt16(int16_t field, FieldType fieldType)
95 {
96     return MarshallInt(field, fieldType, sizeof(int16_t));
97 }
98 
MarshallInt32(int32_t field,FieldType fieldType)99 bool MarshallInt32(int32_t field, FieldType fieldType)
100 {
101     return MarshallInt(field, fieldType, sizeof(int32_t));
102 }
103 
MarshallInt64(int64_t field,FieldType fieldType)104 bool MarshallInt64(int64_t field, FieldType fieldType)
105 {
106     return MarshallInt(field, fieldType, sizeof(int64_t));
107 }
108 
GetPacketSize()109 uint16_t GetPacketSize()
110 {
111     return g_counter;
112 }
113 
GetPacketBufPtr()114 const char* GetPacketBufPtr()
115 {
116     return g_buffer;
117 }
118 
MarshallString(const char * field,uint8_t type)119 bool MarshallString(const char *field, uint8_t type)
120 {
121     if (field == NULL) {
122         return false;
123     }
124 
125     // one more byte for '\0'
126     size_t sz = strlen(field) + 1;
127     if (g_counter + (TYPE_FILED_LENGTH + MAX_BYTE_NUM + sz) > PACKET_DATA_SIZE) {
128         HILOGE("MarshallString field is too big to fit");
129         return false;
130     }
131 
132     IntToHex(type, sizeof(uint8_t));
133     EncodeLengthOfTlv(sz);
134     StringToHex(field);
135     return true;
136 }
137 
MarshallRawData(const void * field,uint8_t type,uint16_t length)138 bool MarshallRawData(const void *field, uint8_t type, uint16_t length)
139 {
140     if (field == NULL) {
141         return false;
142     }
143 
144     if (g_counter + (TYPE_FILED_LENGTH + MAX_BYTE_NUM + length) > PACKET_DATA_SIZE) {
145         HILOGE("MarshallString field is too big to fit");
146         return false;
147     }
148 
149     IntToHex(type, sizeof(uint8_t));
150     EncodeLengthOfTlv(length);
151     for (uint32_t i = 0; i < length; i++) {
152         char ch = ((const char *)field)[i];
153         g_buffer[g_counter++] = ch;
154     }
155     return true;
156 }
157 
StringToHex(const char * stringValue)158 static bool StringToHex(const char *stringValue)
159 {
160     if (stringValue == NULL) {
161         return false;
162     }
163 
164     uint32_t len = strlen(stringValue);
165     for (uint32_t i = 0; i < len; i++) {
166         char ch = stringValue[i];
167         g_buffer[g_counter++] = ch;
168     }
169     g_buffer[g_counter++] = '\0';
170 
171     return true;
172 }
173 
EncodeLengthOfTlv(uint16_t length)174 static void EncodeLengthOfTlv(uint16_t length)
175 {
176     g_buffer[g_counter] = ((length >> TLV_LENGTH_SHIFT_BITS) & LOW_BIT_MASK);
177     if (g_buffer[g_counter]) {
178         char highByte = (char)((uint8_t)g_buffer[g_counter] | HIGH_BIT_MASK);
179         g_buffer[g_counter++] = highByte;
180     }
181     g_buffer[g_counter++] = (length & LOW_BIT_MASK);
182 }
183 
IntToHex(uint64_t value,uint8_t typeSize)184 static void IntToHex(uint64_t value, uint8_t typeSize)
185 {
186     uint8_t *bytes = (uint8_t*)&value;
187     /* put byte one by one from low address to high address */
188     for (int8_t i = 0; i < typeSize; i++) {
189         uint8_t val = bytes[i];
190         g_buffer[g_counter++] = val;
191     }
192 }
193 
ConvertIntLittle2Big(const uint8_t * dataIn,uint8_t typeSize)194 static uint64_t ConvertIntLittle2Big(const uint8_t *dataIn, uint8_t typeSize)
195 {
196     uint64_t dataOut = 0;
197     switch (typeSize) {
198         case INT_16:
199             Convert16DataLittle2Big(dataIn, (uint8_t*)&dataOut);
200             break;
201         case INT_32:
202             Convert32DataLittle2Big(dataIn, (uint8_t*)&dataOut);
203             break;
204         case INT_64:
205             Convert64DataLittle2Big(dataIn, (uint8_t*)&dataOut);
206             break;
207         default:
208             break;
209     }
210     return dataOut;
211 }
212 
MarshallInt(uint64_t field,FieldType fieldType,uint8_t fieldSize)213 static bool MarshallInt(uint64_t field, FieldType fieldType, uint8_t fieldSize)
214 {
215     if (g_counter + (TYPE_FILED_LENGTH + MAX_BYTE_NUM + fieldSize) > PACKET_DATA_SIZE) {
216         HILOGE("MarshallInt field is too big to fit");
217         return false;
218     }
219 
220     IntToHex(fieldType, sizeof(uint8_t));
221     EncodeLengthOfTlv(fieldSize);
222     IntToHex(IsBigEndian() ? field : ConvertIntLittle2Big((uint8_t*)&field, fieldSize), fieldSize);
223     return true;
224 }
225