• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "dms_packet.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <functional>
21 #include <limits>
22 #include <string>
23 
24 namespace {
25 #define CHECK_BOUNDARY()                                                                                    \
26     if ((integerValue < std::numeric_limits<T>::min()) || (integerValue > std::numeric_limits<T>::max())) { \
27         printf("CHECK_BOUNDARY: bad boundary\n");                                                           \
28         return false;                                                                                       \
29     }
30 
31 constexpr uint8_t TLV_LENGTH_SHIFT_BITS = 7;
32 constexpr uint8_t LOW_BIT_MASK = 0x7F;
33 constexpr uint8_t HIGH_BIT_MASK = 0x80;
34 constexpr uint8_t BYTE_MASK = 0xFF;
35 
36 constexpr uint8_t ONE_BYTE_BITS_NUM = 8;
37 constexpr uint8_t ONE_BYTE_LENGTH = 1;
38 constexpr uint8_t TYPE_FILED_LENGTH = 1;
39 
40 constexpr uint8_t MIN_BYTE_NUM_OF_LENGTH_FILED = 1;
41 constexpr uint8_t MAX_BYTE_NUM_OF_LENGTH_FILED = 2;
42 }
43 
DmsPacket(char * buffer,uint16_t bufferCapacity)44 DmsPacket::DmsPacket(char* buffer, uint16_t bufferCapacity)
45     : buffer_(buffer), bufferCapacity_(bufferCapacity), counter_(0) {}
46 
BuildDmsPacket(const DmsMsgInfo & dmsMsgInfo,uint16_t & bufferSize)47 bool DmsPacket::BuildDmsPacket(const DmsMsgInfo& dmsMsgInfo, uint16_t& bufferSize)
48 {
49     bufferSize = 0;
50     if (buffer_ == nullptr || bufferCapacity_ > PACKET_DATA_SIZE) {
51         printf("DmsPacket:BuildDmsPacket bad parameters [bufferCapacity = %d]", bufferCapacity_);
52         return false;
53     }
54 
55     if (!MarshallDmsMsgInfo(dmsMsgInfo)) {
56         printf("DmsPacket:MarshallDmsMsgInfo failed\n");
57         return false;
58     }
59 
60     bufferSize = counter_;
61     return true;
62 }
63 
MarshallStringField(const std::string & field,MSG_TYPE_SEQ type,uint16_t & dataLength)64 bool DmsPacket::MarshallStringField(const std::string& field, MSG_TYPE_SEQ type, uint16_t& dataLength)
65 {
66     if (field.empty()) {
67         return false;
68     }
69 
70     // one more byte for '\0'
71     size_t sz = field.size() + 1;
72     uint8_t bytesNum = 0;
73     IntToHex<uint8_t>(static_cast<uint8_t>(type));
74     bytesNum = EncodeLengthOfTlv(sz);
75     dataLength += TYPE_FILED_LENGTH + bytesNum;
76     if (dataLength + sz > bufferCapacity_) {
77         printf("DmsPacket:MarshallStringField DmsMsgInfo is too big to fit\n");
78         return false;
79     }
80     StringToHex(field);
81     dataLength += sz;
82 
83     return true;
84 }
85 
MarshallDmsMsgInfo(const DmsMsgInfo & dmsMsgInfo)86 bool DmsPacket::MarshallDmsMsgInfo(const DmsMsgInfo& dmsMsgInfo)
87 {
88     uint16_t dataLength = 0;
89     uint8_t bytesNum = 0;
90 
91     // marshall command id
92     IntToHex<uint8_t>(static_cast<uint8_t>(MSG_TYPE_SEQ::COMMAND_ID));
93     bytesNum = EncodeLengthOfTlv(ONE_BYTE_LENGTH);
94     IntToHex<uint8_t>(dmsMsgInfo.commandId);
95     dataLength += (TYPE_FILED_LENGTH + bytesNum + ONE_BYTE_LENGTH);
96 
97     // marshall callee package name
98     if (!MarshallStringField(dmsMsgInfo.calleePkgName, MSG_TYPE_SEQ::CALLEE_PKG_NAME, dataLength)) {
99         return false;
100     }
101 
102     // marshall callee ability name
103     if (!MarshallStringField(dmsMsgInfo.calleeAbilityName, MSG_TYPE_SEQ::CALLEE_ABILITY_NAME, dataLength)) {
104         return false;
105     }
106 
107     // marshall caller signature
108     if (!MarshallStringField(dmsMsgInfo.callerSignature, MSG_TYPE_SEQ::CALLER_SIGNATURE, dataLength)) {
109         return false;
110     }
111 
112     return true;
113 }
114 
StringToHex(const std::string & stringValue)115 bool DmsPacket::StringToHex(const std::string& stringValue)
116 {
117     if (stringValue.empty()) {
118         return false;
119     }
120 
121     for_each(std::begin(stringValue), std::end(stringValue), [this] (char ch) {
122         buffer_[counter_++] = ch;
123     });
124     buffer_[counter_++] = '\0';
125 
126     return true;
127 }
128 
129 template<typename T>
IntToHex(uint64_t integerValue)130 typename std::enable_if<std::is_unsigned<T>::value, bool>::type DmsPacket::IntToHex(uint64_t integerValue)
131 {
132     CHECK_BOUNDARY();
133     ToHex(integerValue, sizeof(T));
134     return true;
135 }
136 
137 template<typename T>
IntToHex(int64_t integerValue)138 typename std::enable_if<std::is_signed<T>::value, bool>::type DmsPacket::IntToHex(int64_t integerValue)
139 {
140     CHECK_BOUNDARY();
141     ToHex(integerValue, sizeof(T));
142     return true;
143 }
144 
EncodeLengthOfTlv(uint16_t length)145 uint8_t DmsPacket::EncodeLengthOfTlv(uint16_t length)
146 {
147     uint8_t bytesNum = MIN_BYTE_NUM_OF_LENGTH_FILED;
148     buffer_[counter_] = ((length >> TLV_LENGTH_SHIFT_BITS) & LOW_BIT_MASK);
149     if (buffer_[counter_]) {
150         buffer_[counter_++] |= HIGH_BIT_MASK;
151         buffer_[counter_++] = (length & LOW_BIT_MASK);
152         bytesNum = MAX_BYTE_NUM_OF_LENGTH_FILED;
153     } else {
154         buffer_[counter_++] = (length & LOW_BIT_MASK);
155     }
156 
157     return bytesNum;
158 }
159 
ToHex(uint64_t value,uint8_t typeSize)160 void DmsPacket::ToHex(uint64_t value, uint8_t typeSize)
161 {
162     for (int8_t i = typeSize - 1; i >= 0; i--) {
163         uint8_t val = (value >> (static_cast<uint8_t>(i) * ONE_BYTE_BITS_NUM)) & BYTE_MASK;
164         buffer_[counter_++] = val;
165     }
166 }
167