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