• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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