1 /*
2 * Copyright (c) 2024 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 "message_data_header.h"
17 #include "dtbcollabmgr_log.h"
18 #include <optional>
19 #include "securec.h"
20
21 namespace OHOS {
22 namespace DistributedCollab {
23 namespace {
24 static constexpr uint32_t DSCHED_SHIFT_8 = 8;
25 static constexpr uint16_t UINT16_SHIFT_MASK_0 = 0x00ff;
26 static const std::string TAG = "DSchedCollabMessageDataHeader";
27 const std::map<uint16_t, uint32_t> HEADER_LEN_VERSION_MAP = {
28 { MessageDataHeader::PROTOCOL_VERSION, MessageDataHeader::HEADER_LEN }
29 };
30 }
31
Serialize()32 std::unique_ptr<AVTransDataBuffer> MessageDataHeader::Serialize()
33 {
34 std::unique_ptr<AVTransDataBuffer> buffer = std::make_unique<AVTransDataBuffer>(HEADER_LEN);
35
36 uint8_t* header = buffer->Data();
37 uint32_t bufLen = HEADER_LEN;
38 uint32_t itemCapacity = 0;
39
40 itemCapacity = WriteVersion(header, bufLen);
41 header += itemCapacity;
42 bufLen -= itemCapacity;
43
44 itemCapacity = WriteDataType(header, bufLen);
45 header += itemCapacity;
46 bufLen -= itemCapacity;
47
48 itemCapacity = WriteTotalLen(header, bufLen);
49 return buffer;
50 }
51
WriteVersion(uint8_t * header,const uint32_t bufLen)52 uint32_t MessageDataHeader::WriteVersion(uint8_t* header, const uint32_t bufLen)
53 {
54 MessageTlvItem item = { MESSAGE_TLV_TYPE::TLV_TYPE_VERSION, sizeof(version_), version_ };
55 WriteTlvItemToBuffer(item, header, bufLen);
56 return MessageTlvItem::HEADER_TYPE_BYTES + MessageTlvItem::HEADER_LEN_BYTES + sizeof(version_);
57 }
58
WriteDataType(uint8_t * header,const uint32_t bufLen)59 uint32_t MessageDataHeader::WriteDataType(uint8_t* header, const uint32_t bufLen)
60 {
61 MessageTlvItem item = { MESSAGE_TLV_TYPE::TLV_TYPE_DATA_TYPE, sizeof(dataType_), dataType_ };
62 WriteTlvItemToBuffer(item, header, bufLen);
63 return MessageTlvItem::HEADER_TYPE_BYTES + MessageTlvItem::HEADER_LEN_BYTES + sizeof(dataType_);
64 }
65
WriteTotalLen(uint8_t * header,const uint32_t bufLen)66 uint32_t MessageDataHeader::WriteTotalLen(uint8_t* header, const uint32_t bufLen)
67 {
68 MessageTlvItem item = { MESSAGE_TLV_TYPE::TLV_TYPE_TOTAL_LEN, sizeof(totalLen_), totalLen_ };
69 WriteTlvItemToBuffer(item, header, bufLen);
70 return MessageTlvItem::HEADER_TYPE_BYTES + MessageTlvItem::HEADER_LEN_BYTES + sizeof(totalLen_);
71 }
72
WriteTlvItemToBuffer(const MessageTlvItem & tlvItem,uint8_t * header,const uint32_t bufLen)73 int32_t MessageDataHeader::WriteTlvItemToBuffer(const MessageTlvItem& tlvItem,
74 uint8_t* header, const uint32_t bufLen)
75 {
76 uint8_t* current = header;
77 uint16_t typeInt = static_cast<uint16_t>(tlvItem.type);
78 *current++ = typeInt >> DSCHED_SHIFT_8;
79 *current++ = typeInt & UINT16_SHIFT_MASK_0;
80 *current++ = tlvItem.len >> DSCHED_SHIFT_8;
81 *current++ = tlvItem.len & UINT16_SHIFT_MASK_0;
82
83 int32_t ret = memcpy_s(current, bufLen - (current - header), &tlvItem.value, tlvItem.len);
84 if (ret != ERR_OK) {
85 HILOGE("copy tlv value failed!, ret %{public}d", ret);
86 return WRITE_TLV_ITEM_TO_BUFFER_FAILED;
87 }
88 return ERR_OK;
89 }
90
Deserialize(const uint8_t * buffer,const size_t bufLen)91 std::optional<MessageDataHeader> MessageDataHeader::Deserialize(const uint8_t* buffer, const size_t bufLen)
92 {
93 if (buffer == nullptr || bufLen < HEADER_LEN) {
94 HILOGE("invalid buffer to deserialize");
95 return std::nullopt;
96 }
97
98 MessageDataHeader messageHeader;
99 uint8_t* header = const_cast<uint8_t*>(buffer);
100 uint8_t* current = header;
101 uint8_t* end = header + BASE_HEADER_LEN;
102
103 MessageTlvItem item;
104 while (current + MessageTlvItem::HEADER_LEN_BYTES + MessageTlvItem::HEADER_TYPE_BYTES < end) {
105 if (messageHeader.ReadTlvItemFromBuffer(item, messageHeader, current, end) != ERR_OK) {
106 HILOGE("read tlv item failed");
107 return std::nullopt;
108 }
109 current += (MessageTlvItem::HEADER_LEN_BYTES + MessageTlvItem::HEADER_TYPE_BYTES);
110 current += item.len;
111 }
112
113 return messageHeader;
114 }
115
ReadTlvItemFromBuffer(MessageTlvItem & tlvItem,MessageDataHeader & messageHeader,const uint8_t * header,const uint8_t * end)116 int32_t MessageDataHeader::ReadTlvItemFromBuffer(MessageTlvItem& tlvItem, MessageDataHeader& messageHeader,
117 const uint8_t* header, const uint8_t* end)
118 {
119 // assign item format
120 uint8_t* current = const_cast<uint8_t*>(header);
121 tlvItem.type = static_cast<MESSAGE_TLV_TYPE>(ReadUint16(current));
122 current += MessageTlvItem::HEADER_TYPE_BYTES;
123 tlvItem.len = ReadUint16(current);
124 current += MessageTlvItem::HEADER_LEN_BYTES;
125
126 if (current + tlvItem.len > end) {
127 HILOGE("reserverd bytes not sufficient");
128 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
129 }
130
131 // assign session current by len
132 int32_t ret = ERR_OK;
133 switch (tlvItem.type) {
134 case MESSAGE_TLV_TYPE::TLV_TYPE_VERSION:
135 ret = ReadVersionFromBuffer(messageHeader, current, tlvItem.len);
136 break;
137
138 case MESSAGE_TLV_TYPE::TLV_TYPE_DATA_TYPE:
139 ret = ReadDataTypeFromBuffer(messageHeader, current, tlvItem.len);
140 break;
141
142 case MESSAGE_TLV_TYPE::TLV_TYPE_TOTAL_LEN:
143 ret = ReadTotalLenFromBuffer(messageHeader, current, tlvItem.len);
144 break;
145
146 default:
147 HILOGE("invalid data type: %{public}d", static_cast<uint16_t>(tlvItem.type));
148 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
149 }
150
151 return ret;
152 }
153
ReadUint16(const uint8_t * header)154 uint16_t MessageDataHeader::ReadUint16(const uint8_t* header)
155 {
156 return (header[0] << DSCHED_SHIFT_8) | header[1];
157 }
158
ReadVersionFromBuffer(MessageDataHeader & messageHeader,const uint8_t * header,const uint32_t len)159 int32_t MessageDataHeader::ReadVersionFromBuffer(MessageDataHeader& messageHeader,
160 const uint8_t* header, const uint32_t len)
161 {
162 int32_t ret = memcpy_s(&messageHeader.version_, sizeof(messageHeader.version_), header, len);
163 if (ret != ERR_OK) {
164 HILOGE("Set Version failed");
165 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
166 }
167 return ERR_OK;
168 }
169
ReadDataTypeFromBuffer(MessageDataHeader & messageHeader,const uint8_t * header,const uint32_t len)170 int32_t MessageDataHeader::ReadDataTypeFromBuffer(MessageDataHeader& messageHeader,
171 const uint8_t* header, const uint32_t len)
172 {
173 int32_t ret = memcpy_s(&messageHeader.dataType_, sizeof(messageHeader.dataType_), header, len);
174 if (ret != ERR_OK) {
175 HILOGE("Set DataType failed");
176 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
177 }
178 return ERR_OK;
179 }
180
ReadTotalLenFromBuffer(MessageDataHeader & messageHeader,const uint8_t * header,const uint32_t len)181 int32_t MessageDataHeader::ReadTotalLenFromBuffer(MessageDataHeader& messageHeader,
182 const uint8_t* header, const uint32_t len)
183 {
184 int32_t ret = memcpy_s(&messageHeader.totalLen_, sizeof(messageHeader.totalLen_), header, len);
185 if (ret != ERR_OK) {
186 HILOGE("Set TotalLen failed");
187 return READ_TLV_ITEM_FROM_BUFFER_FAILED;
188 }
189 return ERR_OK;
190 }
191 } // namespace DistributedCollab
192 } // namespace OHOS