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 "obex_headers.h"
17 #include <algorithm>
18 #include <cstring>
19 #include <iostream>
20 #include <sstream>
21 #include <unordered_map>
22 #include "log.h"
23 #include "obex_utils.h"
24 #include "securec.h"
25 
26 namespace OHOS {
27 namespace bluetooth {
28 /************************* OBEX ObexHdrType *******************************/
29 const uint8_t ObexHdrType::UNICODE_TEXT;
30 const uint8_t ObexHdrType::BYTES;
31 const uint8_t ObexHdrType::BYTE;
32 const uint8_t ObexHdrType::WORD;
33 const uint8_t ObexHdrType::MASK;
34 /************************* OBEX ObexHdrSrmMode *******************************/
35 const uint8_t ObexHdrSrmMode::NORMAL;
36 const uint8_t ObexHdrSrmMode::SINGLE;
37 /************************* OBEX ObexHdrSrmpMode *******************************/
38 const uint8_t ObexHdrSrmpMode::WAIT;
39 
40 const uint8_t ObexHeader::MIN_PACKET_LENGTH;
41 const uint8_t ObexHeader::TARGET_LENGTH;
42 const uint8_t ObexHeader::U16STRING_NULL_LENGTH;
43 const uint8_t ObexHeader::U16STRING_LENGTH;
44 const uint8_t ObexHeader::UINT16_LENGTH;
45 const uint8_t ObexHeader::UINT32_LENGTH;
46 const uint8_t ObexHeader::UINT64_LENGTH;
47 const uint8_t ObexHeader::HDR_UNICODE_PREFIX_LENGTH;
48 const uint8_t ObexHeader::HDR_BYTES_PREFIX_LENGTH;
49 
50 const std::unordered_map<uint8_t, std::string> ObexHeader::HEADER_ID_NAME_MAP = {
51     {0x00, "UNKNOWN"},
52     {0xC0, "COUNT"},
53     {0x01, "NAME"},
54     {0x42, "TYPE"},
55     {0xC3, "LENGTH"},
56     {0x44, "TIME_ISO8601"},
57     {0xC4, "TIME_4BYTE_VERSION"},
58     {0x05, "DESCRIPTION"},
59     {0x46, "TARGET"},
60     {0x47, "HTTP"},
61     {0x48, "BODY"},
62     {0x49, "END_OF_BODY"},
63     {0x4A, "WHO"},
64     {0xCB, "CONNECTION_ID"},
65     {0x4C, "APP_PARAMETERS"},
66     {0x4D, "AUTH_CHALLENGE"},
67     {0x4E, "AUTH_RESPONSE"},
68     {0xCF, "CREATOR_ID"},
69     {0x50, "WAN_UUID"},
70     {0x51, "OBJECT_CLASS"},
71     {0x52, "SESSION_PARAMETERS"},
72     {0x93, "SESSION_SEQUENCE_NUMBER"},
73     {0x94, "ACTION_ID"},
74     {0x15, "DEST_NAME"},
75     {0xD6, "PERMISSIONS"},
76     {0x97, "SRM"},
77     {0x98, "SRMP"}
78 };
79 
ObexHeader()80 ObexHeader::ObexHeader()
81     : code_(0x00),
82       packetLength_(0x00),
83       obexVersionNum_(nullptr),
84       flags_(nullptr),
85       maxPacketLength_(nullptr),
86       constants_(nullptr)
87 {}
88 
GetHeaderName(uint8_t headerId)89 const std::string &ObexHeader::GetHeaderName(uint8_t headerId)
90 {
91     if (HEADER_ID_NAME_MAP.find(headerId) != HEADER_ID_NAME_MAP.end()) {
92         return HEADER_ID_NAME_MAP.at(headerId);
93     }
94     return HEADER_ID_NAME_MAP.at(0x00);
95 }
96 
ParseFields(const uint8_t * buf,const uint8_t & code,uint16_t & pos,bool isRequest,bool isConnect)97 void ObexHeader::ParseFields(const uint8_t *buf, const uint8_t &code, uint16_t &pos, bool isRequest, bool isConnect)
98 {
99     if (isRequest) {
100         if (code == static_cast<uint8_t>(ObexOpeId::CONNECT)) {
101             uint8_t version = buf[pos++];
102             uint8_t flags = buf[pos++];
103             uint16_t maxPacketLength = ObexUtils::GetBufData16(buf, pos);
104             pos += UINT16_LENGTH;
105             SetFieldObexVersionNum(version);
106             SetFieldFlags(flags);
107             SetFieldMaxPacketLength(maxPacketLength);
108         } else if (code == static_cast<uint8_t>(ObexOpeId::SETPATH)) {
109             uint8_t flags = buf[pos++];
110             uint8_t constants = buf[pos++];
111             SetFieldFlags(flags);
112             SetFieldConstants(constants);
113         }
114     } else if (isConnect) {
115         // Connect response
116         uint8_t version = buf[pos++];
117         uint8_t flags = buf[pos++];
118         uint16_t maxPacketLength = ObexUtils::GetBufData16(buf, pos);
119         pos += UINT16_LENGTH;
120         SetFieldObexVersionNum(version);
121         SetFieldFlags(flags);
122         SetFieldMaxPacketLength(maxPacketLength);
123     }
124 }
125 
ParseOptionalHeaders(const uint8_t * buf,const uint16_t & size,uint16_t & pos)126 bool ObexHeader::ParseOptionalHeaders(const uint8_t *buf, const uint16_t &size, uint16_t &pos)
127 {
128     while (pos < size) {
129         uint8_t headerId = buf[pos++];
130         uint8_t headerDataType = headerId & ObexHdrType::MASK;
131         OBEX_LOG_DEBUG(
132             "ObexHeader Parse headerId=%02X(%{public}s), type=%02X",
133             headerId, GetHeaderName(headerId).c_str(), headerDataType);
134         switch (headerDataType) {
135             case ObexHdrType::BYTE:
136                 AppendByte(headerId, buf[pos++]);
137                 break;
138             case ObexHdrType::BYTES:
139                 ParseBytes(headerId, buf, pos);
140                 break;
141             case ObexHdrType::UNICODE_TEXT:
142                 ParseUnicodeText(headerId, buf, pos);
143                 break;
144             case ObexHdrType::WORD:
145                 AppendWord(headerId, ObexUtils::GetBufData32(buf, pos));
146                 pos += UINT32_LENGTH;
147                 break;
148             default:
149                 OBEX_LOG_ERROR("parse error");
150                 return false;
151         }
152     }
153     return true;
154 }
155 
Parse(const uint8_t * buf,const uint16_t size,bool isRequest,bool isConnect)156 bool ObexHeader::Parse(const uint8_t *buf, const uint16_t size, bool isRequest, bool isConnect)
157 {
158     OBEX_LOG_DEBUG("ObexHeader Parse: isRequest[%{public}d],isConnect:[%{public}d], buf size=[%{public}d]",
159         isRequest, isConnect, size);
160     isRequest_ = isRequest;
161     uint16_t pos = 0;
162     uint8_t code = buf[pos++];
163     uint16_t packetLengthForCheck = ObexUtils::GetBufData16(buf, pos);
164     OBEX_LOG_DEBUG("ObexHeader Parse: packetLength=%{public}d", int(packetLengthForCheck));
165     pos += UINT16_LENGTH;
166     if (packetLengthForCheck != size) {
167         OBEX_LOG_ERROR("packetLength size is wrong packetSize=%{public}d, actualSize=%{public}d",
168         int(packetLengthForCheck), int(size));
169         return false;
170     }
171     code_ = code;
172     packetLength_ = MIN_PACKET_LENGTH;
173 
174     ParseFields(buf, code, pos, isRequest, isConnect);
175 
176     if (!ParseOptionalHeaders(buf, size, pos)) {
177         return false;
178     }
179 
180     if (packetLength_ != packetLengthForCheck) {
181         OBEX_LOG_ERROR(
182             "parse error packetLength_[%{public}d] != packetLengthForCheck[%{public}d]",
183             packetLength_, packetLengthForCheck);
184         ObexUtils::ObexHeaderDebug(*this);
185         return false;
186     }
187     return true;
188 }
189 
ParseBytes(const uint8_t & headerId,const uint8_t * buf,uint16_t & pos)190 void ObexHeader::ParseBytes(const uint8_t &headerId, const uint8_t *buf, uint16_t &pos)
191 {
192     uint16_t dataLen = ObexUtils::GetBufData16(buf, pos) - HDR_BYTES_PREFIX_LENGTH;
193     pos += UINT16_LENGTH;
194     std::unique_ptr<ObexOptionalHeader> header = nullptr;
195     switch (headerId) {
196         case ObexHeader::TYPE:
197             header = std::make_unique<ObexOptionalStringHeader>(headerId, &buf[pos], dataLen);
198             Append(header);
199             break;
200         case ObexHeader::APP_PARAMETERS:
201         case ObexHeader::SESSION_PARAMETERS:
202         case ObexHeader::AUTH_CHALLENGE:
203         case ObexHeader::AUTH_RESPONSE:
204             header = std::make_unique<ObexOptionalTlvHeader>(headerId, &buf[pos], dataLen);
205             Append(header);
206             break;
207         default:
208             header = std::make_unique<ObexOptionalBytesHeader>(headerId, &buf[pos], dataLen);
209             Append(header);
210             break;
211     }
212     pos += dataLen;
213 }
214 
ParseUnicodeText(const uint8_t & headerId,const uint8_t * buf,uint16_t & pos)215 void ObexHeader::ParseUnicodeText(const uint8_t &headerId, const uint8_t *buf, uint16_t &pos)
216 {
217     uint16_t bytesLen = ObexUtils::GetBufData16(buf, pos) - HDR_UNICODE_PREFIX_LENGTH;
218     pos += UINT16_LENGTH;
219     if (bytesLen > 0) {
220         auto tmpBuf = std::make_unique<uint8_t[]>(bytesLen);
221         if (memcpy_s(tmpBuf.get(), bytesLen, &buf[pos], bytesLen) != EOK) {
222             OBEX_LOG_ERROR("ParseUnicodeText, memcpy_s fail");
223             return;
224         }
225         if (!ObexUtils::SysIsBigEndian()) {
226             ObexUtils::DataReverse(tmpBuf.get(), bytesLen, UINT16_LENGTH);
227         }
228         std::u16string str((char16_t *)tmpBuf.get());
229         AppendUnicode(headerId, str);
230     } else {
231         AppendUnicode(headerId, u"");
232     }
233     pos += bytesLen;
234 }
235 
ObexHeader(const ObexHeader & header,bool fieldOnly)236 ObexHeader::ObexHeader(const ObexHeader &header, bool fieldOnly)
237 {
238     code_ = header.GetFieldCode();
239     isRequest_ = header.isRequest_;
240     uint16_t filedPacketLength = MIN_PACKET_LENGTH;
241     if (header.GetFieldObexVersionNum() != nullptr) {
242         obexVersionNum_ = std::make_unique<uint8_t>();
243         *obexVersionNum_ = *header.GetFieldObexVersionNum();
244         filedPacketLength += 1;
245     }
246     if (header.GetFieldFlags() != nullptr) {
247         flags_ = std::make_unique<uint8_t>();
248         *flags_ = *header.GetFieldFlags();
249         filedPacketLength += 1;
250     }
251     if (header.GetFieldMaxPacketLength() != nullptr) {
252         maxPacketLength_ = std::make_unique<uint16_t>();
253         *maxPacketLength_ = *header.GetFieldMaxPacketLength();
254         filedPacketLength += UINT16_LENGTH;
255     }
256     if (header.GetFieldConstants() != nullptr) {
257         constants_ = std::make_unique<uint8_t>();
258         *constants_ = *header.GetFieldConstants();
259         filedPacketLength += 1;
260     }
261     if (fieldOnly) {
262         packetLength_ = filedPacketLength;
263     } else {
264         packetLength_ = header.GetFieldPacketLength();
265         for (auto &optHeader : header.GetOptionalHeaders()) {
266             headerIndexMap_.insert(std::pair<uint8_t, size_t>(optHeader->GetHeaderId(), optionalHeaders_.size()));
267             optionalHeaders_.push_back(optHeader->Clone());
268         }
269         SetExtendBodyObject(header.GetExtendBodyObject());
270     }
271 }
272 
CreateRequest(ObexOpeId opcode)273 std::unique_ptr<ObexHeader> ObexHeader::CreateRequest(ObexOpeId opcode)
274 {
275     auto header = std::make_unique<ObexHeader>();
276     header->isRequest_ = true;
277     header->code_ = static_cast<uint8_t>(opcode);
278     // code + pack length
279     header->packetLength_ = MIN_PACKET_LENGTH;
280     if (opcode == ObexOpeId::CONNECT) {
281         header->SetFieldObexVersionNum(OBEX_VERSION);
282         header->SetFieldFlags(0x00);
283         header->SetFieldMaxPacketLength(OBEX_DEFAULT_MTU);
284     } else if (opcode == ObexOpeId::SETPATH) {
285         // 0bit backup a level before applying name (equivalent to ../ on many systems)
286         // 1bit Don’t create folder if it does not exist, return an error instead.
287         header->SetFieldFlags(0x00);
288         header->SetFieldConstants(0x00);
289     }
290     return header;
291 }
292 
CreateResponse(ObexRspCode rspCode,bool isConnectResp)293 std::unique_ptr<ObexHeader> ObexHeader::CreateResponse(ObexRspCode rspCode, bool isConnectResp)
294 {
295     auto header = std::make_unique<ObexHeader>();
296     header->isRequest_ = false;
297     header->code_ = static_cast<uint8_t>(rspCode);
298     // code + pack length
299     header->packetLength_ = MIN_PACKET_LENGTH;
300     if (isConnectResp) {
301         header->SetFieldObexVersionNum(OBEX_VERSION);
302         header->SetFieldFlags(0x00);
303         header->SetFieldMaxPacketLength(OBEX_DEFAULT_MTU);
304     }
305     return header;
306 }
307 
ParseRequest(const uint8_t * buf,const uint16_t size)308 std::unique_ptr<ObexHeader> ObexHeader::ParseRequest(const uint8_t *buf, const uint16_t size)
309 {
310     auto header = std::make_unique<ObexHeader>();
311     if (header->Parse(buf, size, true, false)) {
312         return header;
313     }
314     return nullptr;
315 }
316 
ParseResponse(const uint8_t * buf,const uint16_t size,bool isConnect)317 std::unique_ptr<ObexHeader> ObexHeader::ParseResponse(const uint8_t *buf, const uint16_t size, bool isConnect)
318 {
319     auto header = std::make_unique<ObexHeader>();
320     if (header->Parse(buf, size, false, isConnect)) {
321         return header;
322     }
323     return nullptr;
324 }
325 
GetFieldCode() const326 uint8_t ObexHeader::GetFieldCode() const
327 {
328     return code_;
329 }
330 
GetFieldPacketLength() const331 uint16_t ObexHeader::GetFieldPacketLength() const
332 {
333     return packetLength_;
334 }
335 
GetFieldObexVersionNum() const336 const uint8_t *ObexHeader::GetFieldObexVersionNum() const
337 {
338     if (obexVersionNum_ == nullptr) {
339         return nullptr;
340     }
341     return obexVersionNum_.get();
342 }
343 
GetFieldFlags() const344 const uint8_t *ObexHeader::GetFieldFlags() const
345 {
346     if (flags_ == nullptr) {
347         return nullptr;
348     }
349     return flags_.get();
350 }
351 
GetFieldMaxPacketLength() const352 const uint16_t *ObexHeader::GetFieldMaxPacketLength() const
353 {
354     if (maxPacketLength_ == nullptr) {
355         return nullptr;
356     }
357     return maxPacketLength_.get();
358 }
359 
GetFieldConstants() const360 const uint8_t *ObexHeader::GetFieldConstants() const
361 {
362     if (constants_ == nullptr) {
363         return nullptr;
364     }
365     return constants_.get();
366 }
367 
SetRespCode(uint8_t code)368 void ObexHeader::SetRespCode(uint8_t code)
369 {
370     if (!isRequest_) {
371         code_ = code;
372     }
373 }
374 
SetFinalBit(bool finalBit)375 void ObexHeader::SetFinalBit(bool finalBit)
376 {
377     if (finalBit) {
378         code_ = code_ | OBEX_FINAL_BIT_MASK;
379     } else {
380         code_ = code_ & ~OBEX_FINAL_BIT_MASK;
381     }
382 }
383 
SetFieldObexVersionNum(const uint8_t obexVersionNum)384 void ObexHeader::SetFieldObexVersionNum(const uint8_t obexVersionNum)
385 {
386     if (obexVersionNum_ == nullptr) {
387         obexVersionNum_ = std::make_unique<uint8_t>();
388         packetLength_ += 1;
389     }
390     *obexVersionNum_ = obexVersionNum;
391 }
392 
SetFieldFlags(const uint8_t flags)393 void ObexHeader::SetFieldFlags(const uint8_t flags)
394 {
395     if (flags_ == nullptr) {
396         flags_ = std::make_unique<uint8_t>();
397         packetLength_ += 1;
398     }
399     *flags_ = flags;
400 }
401 
SetFieldMaxPacketLength(const uint16_t maxPacketLength)402 void ObexHeader::SetFieldMaxPacketLength(const uint16_t maxPacketLength)
403 {
404     if (maxPacketLength_ == nullptr) {
405         maxPacketLength_ = std::make_unique<uint16_t>();
406         packetLength_ += UINT16_LENGTH;
407     }
408     *maxPacketLength_ = maxPacketLength;
409 }
410 
SetFieldConstants(uint8_t constants)411 void ObexHeader::SetFieldConstants(uint8_t constants)
412 {
413     if (constants_ == nullptr) {
414         constants_ = std::make_unique<uint8_t>();
415         packetLength_ += 1;
416     }
417     *constants_ = constants;
418 }
419 
Append(std::unique_ptr<ObexOptionalHeader> & header)420 void ObexHeader::Append(std::unique_ptr<ObexOptionalHeader> &header)
421 {
422     uint8_t headerId = header->GetHeaderId();
423     if (HasHeader(headerId)) {
424         OBEX_LOG_ERROR("duplicate headerId: 0x%02X", headerId);
425         return;
426     }
427     headerIndexMap_[headerId] = optionalHeaders_.size();
428     packetLength_ += header->GetHeaderTotalSize();
429     optionalHeaders_.push_back(std::move(header));
430 }
431 
432 template<typename T>
GetItem(uint8_t headerId) const433 const T ObexHeader::GetItem(uint8_t headerId) const
434 {
435     const ObexOptionalHeader *headerItem = Get(headerId);
436     if (headerItem == nullptr) {
437         return nullptr;
438     }
439     return static_cast<T>(const_cast<ObexOptionalHeader *>(headerItem));
440 }
441 
AppendUnicode(const uint8_t headerId,const std::u16string & text)442 void ObexHeader::AppendUnicode(const uint8_t headerId, const std::u16string &text)
443 {
444     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalUnicodeHeader>(headerId, text);
445     Append(header);
446 }
447 
AppendByte(const uint8_t headerId,const uint8_t byte)448 void ObexHeader::AppendByte(const uint8_t headerId, const uint8_t byte)
449 {
450     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalByteHeader>(headerId, byte);
451     Append(header);
452 }
453 
AppendBytes(const uint8_t headerId,const uint8_t * byteBuf,const uint32_t size)454 void ObexHeader::AppendBytes(const uint8_t headerId, const uint8_t *byteBuf, const uint32_t size)
455 {
456     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalBytesHeader>(headerId, byteBuf, size);
457     Append(header);
458 }
459 
AppendWord(const uint8_t headerId,const uint32_t word)460 void ObexHeader::AppendWord(const uint8_t headerId, const uint32_t word)
461 {
462     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalWordHeader>(headerId, word);
463     Append(header);
464 }
465 
AppendString(const uint8_t headerId,const std::string & str)466 void ObexHeader::AppendString(const uint8_t headerId, const std::string &str)
467 {
468     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalStringHeader>(headerId, str);
469     Append(header);
470 }
471 
AppendTlvTriplets(const uint8_t headerId,ObexTlvParamters & tlvParamters)472 void ObexHeader::AppendTlvTriplets(const uint8_t headerId, ObexTlvParamters &tlvParamters)
473 {
474     std::unique_ptr<ObexOptionalHeader> header = std::make_unique<ObexOptionalTlvHeader>(headerId, tlvParamters);
475     Append(header);
476 }
477 
GetOptionalHeaders() const478 std::vector<std::unique_ptr<ObexOptionalHeader>> const &ObexHeader::GetOptionalHeaders() const
479 {
480     return optionalHeaders_;
481 }
482 
483 // Header add methods
484 // bytes
AppendItemTarget(const uint8_t * target,const uint16_t length)485 bool ObexHeader::AppendItemTarget(const uint8_t *target, const uint16_t length)
486 {
487     if (optionalHeaders_.size() != 0) {
488         bool error = true;
489         if (optionalHeaders_.size() == 1) {
490             if (optionalHeaders_.at(0)->GetHeaderId() == ObexHeader::SESSION_SEQUENCE_NUMBER) {
491                 error = false;
492             }
493         }
494         if (error) {
495             OBEX_LOG_ERROR("Target must the first header in the request");
496             return false;
497         }
498     }
499     if (length != TARGET_LENGTH) {
500         OBEX_LOG_ERROR("AppendItemTarget length is wrong!");
501         return false;
502     }
503     AppendBytes(ObexHeader::TARGET, target, length);
504     return true;
505 }
506 
AppendItemTimeIso8601(const uint8_t * time,const uint16_t length)507 void ObexHeader::AppendItemTimeIso8601(const uint8_t *time, const uint16_t length)
508 {
509     AppendBytes(ObexHeader::TIME_ISO8601, time, length);
510 }
511 
AppendItemHttp(const uint8_t * http,const uint16_t length)512 void ObexHeader::AppendItemHttp(const uint8_t *http, const uint16_t length)
513 {
514     AppendBytes(ObexHeader::HTTP, http, length);
515 }
516 
AppendItemBody(const uint8_t * body,const uint16_t length)517 void ObexHeader::AppendItemBody(const uint8_t *body, const uint16_t length)
518 {
519     AppendBytes(ObexHeader::BODY, body, length);
520 }
521 
AppendItemEndBody(const uint8_t * endBody,const uint16_t length)522 void ObexHeader::AppendItemEndBody(const uint8_t *endBody, const uint16_t length)
523 {
524     AppendBytes(ObexHeader::END_OF_BODY, endBody, length);
525 }
526 
AppendItemWho(const uint8_t * who,const uint16_t length)527 void ObexHeader::AppendItemWho(const uint8_t *who, const uint16_t length)
528 {
529     AppendBytes(ObexHeader::WHO, who, length);
530 }
531 
AppendItemObjectClass(const uint8_t * objectClass,const uint16_t length)532 void ObexHeader::AppendItemObjectClass(const uint8_t *objectClass, const uint16_t length)
533 {
534     AppendBytes(ObexHeader::OBJECT_CLASS, objectClass, length);
535 }
536 
537 // tlv
AppendItemAppParams(ObexTlvParamters & params)538 void ObexHeader::AppendItemAppParams(ObexTlvParamters &params)
539 {
540     AppendTlvTriplets(ObexHeader::APP_PARAMETERS, params);
541 }
542 
AppendItemAuthChallenges(ObexDigestChallenge & challenges)543 void ObexHeader::AppendItemAuthChallenges(ObexDigestChallenge &challenges)
544 {
545     AppendTlvTriplets(ObexHeader::AUTH_CHALLENGE, challenges);
546 }
547 
AppendItemAuthResponse(ObexDigestResponse & responses)548 void ObexHeader::AppendItemAuthResponse(ObexDigestResponse &responses)
549 {
550     AppendTlvTriplets(ObexHeader::AUTH_RESPONSE, responses);
551 }
552 
AppendItemSessionParams(ObexSessionParameters & params)553 bool ObexHeader::AppendItemSessionParams(ObexSessionParameters &params)
554 {
555     if (optionalHeaders_.size() != 0) {
556         OBEX_LOG_ERROR("SessionParams must the first header in the request");
557         return false;
558     }
559     AppendTlvTriplets(ObexHeader::SESSION_PARAMETERS, params);
560     return true;
561 }
562 
563 // String
AppendItemType(const std::string & type)564 void ObexHeader::AppendItemType(const std::string &type)
565 {
566     AppendString(ObexHeader::TYPE, type);
567 }
568 
569 // Word
AppendItemConnectionId(const uint32_t connectionId)570 bool ObexHeader::AppendItemConnectionId(const uint32_t connectionId)
571 {
572     if (optionalHeaders_.size() != 0) {
573         bool error = true;
574         if (optionalHeaders_.size() == 1) {
575             if (optionalHeaders_.at(0)->GetHeaderId() == ObexHeader::SESSION_SEQUENCE_NUMBER) {
576                 error = false;
577             }
578         }
579         if (error) {
580             OBEX_LOG_ERROR("ConnectionId must the first header in the request");
581             return false;
582         }
583     }
584     AppendWord(ObexHeader::CONNECTION_ID, connectionId);
585     return true;
586 }
587 
AppendItemCount(const uint32_t count)588 void ObexHeader::AppendItemCount(const uint32_t count)
589 {
590     AppendWord(ObexHeader::COUNT, count);
591 }
592 
AppendItemLength(const uint32_t length)593 void ObexHeader::AppendItemLength(const uint32_t length)
594 {
595     AppendWord(ObexHeader::LENGTH, length);
596 }
597 
AppendItemTime4byte(const uint32_t time)598 void ObexHeader::AppendItemTime4byte(const uint32_t time)
599 {
600     AppendWord(ObexHeader::TIME_4BYTE_VERSION, time);
601 }
602 
AppendItemPermissions(const uint32_t permissions)603 void ObexHeader::AppendItemPermissions(const uint32_t permissions)
604 {
605     AppendWord(ObexHeader::PERMISSIONS, permissions);
606 }
607 
608 // Unicode
AppendItemName(const std::u16string & name)609 void ObexHeader::AppendItemName(const std::u16string &name)
610 {
611     AppendUnicode(ObexHeader::NAME, name);
612 }
613 
AppendItemDescription(const std::u16string & description)614 void ObexHeader::AppendItemDescription(const std::u16string &description)
615 {
616     AppendUnicode(ObexHeader::DESCRIPTION, description);
617 }
618 
AppendItemDestName(const std::u16string & destName)619 void ObexHeader::AppendItemDestName(const std::u16string &destName)
620 {
621     AppendUnicode(ObexHeader::DEST_NAME, destName);
622 }
623 
624 // byte
AppendItemSessionSeqNum(const uint8_t num)625 bool ObexHeader::AppendItemSessionSeqNum(const uint8_t num)
626 {
627     if (optionalHeaders_.size() != 0) {
628         OBEX_LOG_ERROR("SessionSeqNum must the first header in the request");
629         return false;
630     }
631     AppendByte(ObexHeader::SESSION_SEQUENCE_NUMBER, num);
632     return true;
633 }
634 
AppendItemActionId(const ObexActionType actionId)635 void ObexHeader::AppendItemActionId(const ObexActionType actionId)
636 {
637     AppendByte(ObexHeader::ACTION_ID, static_cast<uint8_t>(actionId));
638 }
639 
AppendItemSrm(const bool srm)640 void ObexHeader::AppendItemSrm(const bool srm)
641 {
642     AppendByte(ObexHeader::SRM, srm ? ObexHdrSrmMode::SINGLE : ObexHdrSrmMode::NORMAL);
643 }
644 
AppendItemSrmp()645 void ObexHeader::AppendItemSrmp()
646 {
647     AppendByte(ObexHeader::SRMP, ObexHdrSrmpMode::WAIT);
648 }
649 
650 // obex header get methods
Get(uint8_t headerId) const651 const ObexOptionalHeader *ObexHeader::Get(uint8_t headerId) const
652 {
653     if (!HasHeader(headerId)) {
654         return nullptr;
655     }
656     size_t index = headerIndexMap_.at(headerId);
657     return optionalHeaders_.at(index).get();
658 }
659 
660 // ObexOptionalHeader
GetItemTarget() const661 const ObexOptionalHeader *ObexHeader::GetItemTarget() const
662 {
663     return Get(ObexHeader::TARGET);
664 }
665 
GetItemTimeIso8601() const666 const ObexOptionalHeader *ObexHeader::GetItemTimeIso8601() const
667 {
668     return Get(ObexHeader::TIME_ISO8601);
669 }
670 
GetItemHttp() const671 const ObexOptionalHeader *ObexHeader::GetItemHttp() const
672 {
673     return Get(ObexHeader::HTTP);
674 }
675 
GetItemBody() const676 const ObexOptionalHeader *ObexHeader::GetItemBody() const
677 {
678     return Get(ObexHeader::BODY);
679 }
680 
GetItemEndBody() const681 const ObexOptionalHeader *ObexHeader::GetItemEndBody() const
682 {
683     return Get(ObexHeader::END_OF_BODY);
684 }
685 
GetItemWho() const686 const ObexOptionalHeader *ObexHeader::GetItemWho() const
687 {
688     return Get(ObexHeader::WHO);
689 }
690 
GetItemObjectClass() const691 const ObexOptionalHeader *ObexHeader::GetItemObjectClass() const
692 {
693     return Get(ObexHeader::OBJECT_CLASS);
694 }
695 
696 // ObexOptionalTlvHeader
GetItemAuthChallenges() const697 const ObexOptionalTlvHeader *ObexHeader::GetItemAuthChallenges() const
698 {
699     return GetItem<ObexOptionalTlvHeader *>(ObexHeader::AUTH_CHALLENGE);
700 }
701 
GetItemSessionParams() const702 const ObexOptionalTlvHeader *ObexHeader::GetItemSessionParams() const
703 {
704     return GetItem<ObexOptionalTlvHeader *>(ObexHeader::SESSION_PARAMETERS);
705 }
706 
GetItemAppParams() const707 const ObexOptionalTlvHeader *ObexHeader::GetItemAppParams() const
708 {
709     return GetItem<ObexOptionalTlvHeader *>(ObexHeader::APP_PARAMETERS);
710 }
711 
GetItemAuthResponse() const712 const ObexOptionalTlvHeader *ObexHeader::GetItemAuthResponse() const
713 {
714     return GetItem<ObexOptionalTlvHeader *>(ObexHeader::AUTH_RESPONSE);
715 }
716 
717 // ObexOptionalStringHeader
GetItemType() const718 const ObexOptionalStringHeader *ObexHeader::GetItemType() const
719 {
720     return GetItem<ObexOptionalStringHeader *>(ObexHeader::TYPE);
721 }
722 
723 // ObexOptionalWordHeader
GetItemCount() const724 const ObexOptionalWordHeader *ObexHeader::GetItemCount() const
725 {
726     return GetItem<ObexOptionalWordHeader *>(ObexHeader::COUNT);
727 }
728 
GetItemLength() const729 const ObexOptionalWordHeader *ObexHeader::GetItemLength() const
730 {
731     return GetItem<ObexOptionalWordHeader *>(ObexHeader::LENGTH);
732 }
733 
GetItemTime4byte() const734 const ObexOptionalWordHeader *ObexHeader::GetItemTime4byte() const
735 {
736     return GetItem<ObexOptionalWordHeader *>(ObexHeader::TIME_4BYTE_VERSION);
737 }
738 
GetItemConnectionId() const739 const ObexOptionalWordHeader *ObexHeader::GetItemConnectionId() const
740 {
741     return GetItem<ObexOptionalWordHeader *>(ObexHeader::CONNECTION_ID);
742 }
743 
GetItemPermissions() const744 const ObexOptionalWordHeader *ObexHeader::GetItemPermissions() const
745 {
746     return GetItem<ObexOptionalWordHeader *>(ObexHeader::PERMISSIONS);
747 }
748 
749 // ObexOptionalUnicodeHeader
GetItemName() const750 const ObexOptionalUnicodeHeader *ObexHeader::GetItemName() const
751 {
752     return GetItem<ObexOptionalUnicodeHeader *>(ObexHeader::NAME);
753 }
754 
GetItemDescription() const755 const ObexOptionalUnicodeHeader *ObexHeader::GetItemDescription() const
756 {
757     return GetItem<ObexOptionalUnicodeHeader *>(ObexHeader::DESCRIPTION);
758 }
759 
GetItemDestName() const760 const ObexOptionalUnicodeHeader *ObexHeader::GetItemDestName() const
761 {
762     return GetItem<ObexOptionalUnicodeHeader *>(ObexHeader::DEST_NAME);
763 }
764 
765 // ObexOptionalByteHeader
GetItemSessionSeqNum() const766 const ObexOptionalByteHeader *ObexHeader::GetItemSessionSeqNum() const
767 {
768     return GetItem<ObexOptionalByteHeader *>(ObexHeader::SESSION_SEQUENCE_NUMBER);
769 }
770 
GetItemActionId() const771 const ObexOptionalByteHeader *ObexHeader::GetItemActionId() const
772 {
773     return GetItem<ObexOptionalByteHeader *>(ObexHeader::ACTION_ID);
774 }
775 
HasHeader(const uint8_t headerId) const776 bool ObexHeader::HasHeader(const uint8_t headerId) const
777 {
778     return headerIndexMap_.find(headerId) != headerIndexMap_.end();
779 }
780 
RemoveItem(const uint8_t headerId)781 void ObexHeader::RemoveItem(const uint8_t headerId)
782 {
783     if (!HasHeader(headerId)) {
784         return;
785     }
786     size_t index = headerIndexMap_.at(headerId);
787     auto &header = optionalHeaders_.at(index);
788     packetLength_ -= header->GetHeaderTotalSize();
789     optionalHeaders_.erase(optionalHeaders_.begin() + index);
790     headerIndexMap_.clear();
791     for (size_t i = 0; i < optionalHeaders_.size(); i++) {
792         auto &item = optionalHeaders_.at(i);
793         headerIndexMap_[item->GetHeaderId()] = i;
794     }
795 }
796 
GetItemSrm() const797 bool ObexHeader::GetItemSrm() const
798 {
799     auto headerItem = GetItem<ObexOptionalByteHeader *>(ObexHeader::SRM);
800     if (headerItem == nullptr) {
801         return false;
802     }
803     return headerItem->GetByte() == ObexHdrSrmMode::SINGLE;
804 }
805 
GetItemSrmp() const806 bool ObexHeader::GetItemSrmp() const
807 {
808     auto headerItem = GetItem<ObexOptionalByteHeader *>(ObexHeader::SRMP);
809     if (headerItem == nullptr) {
810         return false;
811     }
812     return headerItem->GetByte() == ObexHdrSrmpMode::WAIT;
813 }
814 
Build() const815 std::unique_ptr<ObexPacket> ObexHeader::Build() const
816 {
817     auto obexPacket = std::make_unique<ObexPacket>(packetLength_);
818     uint8_t *packetBuf = obexPacket->GetBuffer();
819     uint16_t pos = 0;
820     packetBuf[pos++] = code_;
821     bool isBigEndian = ObexUtils::SysIsBigEndian();
822     ObexUtils::SetBufData16(packetBuf, pos, packetLength_);
823     pos += UINT16_LENGTH;
824     if (obexVersionNum_ != nullptr) {
825         packetBuf[pos++] = obexVersionNum_.get()[0];
826     }
827     if (flags_ != nullptr) {
828         packetBuf[pos++] = flags_.get()[0];
829     }
830     if (constants_ != nullptr) {
831         packetBuf[pos++] = constants_.get()[0];
832     }
833     if (maxPacketLength_ != nullptr) {
834         ObexUtils::SetBufData16(packetBuf, pos, maxPacketLength_.get()[0]);
835         pos += UINT16_LENGTH;
836     }
837     for (auto &headerItem : optionalHeaders_) {
838         packetBuf[pos++] = headerItem->GetHeaderId();
839         if (headerItem->HasLengthField()) {
840             ObexUtils::SetBufData16(packetBuf, pos, headerItem->GetHeaderTotalSize());
841             pos += UINT16_LENGTH;
842         }
843         (void)memcpy_s(
844             &packetBuf[pos], packetLength_ - pos, headerItem->GetBytes().get(), headerItem->GetHeaderDataSize());
845         if (!isBigEndian && headerItem->GetHeaderUnitLen() > 1) {
846             ObexUtils::DataReverse(&packetBuf[pos], headerItem->GetHeaderDataSize(), headerItem->GetHeaderUnitLen());
847         }
848         pos += headerItem->GetHeaderDataSize();
849     }
850     return obexPacket;
851 }
852 
GetExtendBodyObject() const853 const std::shared_ptr<ObexBodyObject> &ObexHeader::GetExtendBodyObject() const
854 {
855     return extendBodyObject_;
856 }
857 
SetExtendBodyObject(const std::shared_ptr<ObexBodyObject> & extendBodyObject)858 void ObexHeader::SetExtendBodyObject(const std::shared_ptr<ObexBodyObject> &extendBodyObject)
859 {
860     extendBodyObject_ = extendBodyObject;
861 }
862 
TlvTriplet()863 TlvTriplet::TlvTriplet()
864 {
865     tagId_ = 0x00;
866     len_ = 0x00;
867     unitLen_ = 1;
868 }
869 
TlvTriplet(const uint8_t tagId,const uint8_t len,const uint8_t * val,const uint8_t unitLen)870 TlvTriplet::TlvTriplet(const uint8_t tagId, const uint8_t len, const uint8_t *val, const uint8_t unitLen)
871 {
872     tagId_ = tagId;
873     len_ = len;
874     unitLen_ = unitLen;
875     val_.insert(val_.end(), val, val + len);
876 }
877 
TlvTriplet(const TlvTriplet & tlvTriplet)878 TlvTriplet::TlvTriplet(const TlvTriplet &tlvTriplet)
879     : TlvTriplet(tlvTriplet.tagId_, tlvTriplet.len_, tlvTriplet.val_.data(), tlvTriplet.unitLen_)
880 {}
881 
TlvTriplet(const uint8_t tagId,const uint8_t val)882 TlvTriplet::TlvTriplet(const uint8_t tagId, const uint8_t val)
883     : TlvTriplet(tagId, static_cast<uint8_t>(1), reinterpret_cast<const uint8_t *>(&val), static_cast<uint8_t>(1))
884 {}
885 
TlvTriplet(const uint8_t tagId,const uint16_t val)886 TlvTriplet::TlvTriplet(const uint8_t tagId, const uint16_t val)
887     : TlvTriplet(tagId, static_cast<uint8_t>(2), reinterpret_cast<const uint8_t *>(&val), static_cast<uint8_t>(2))
888 {}
889 
TlvTriplet(const uint8_t tagId,const uint32_t val)890 TlvTriplet::TlvTriplet(const uint8_t tagId, const uint32_t val)
891     : TlvTriplet(tagId, static_cast<uint8_t>(4), reinterpret_cast<const uint8_t *>(&val), static_cast<uint8_t>(4))
892 {}
893 
TlvTriplet(const uint8_t tagId,const uint64_t val)894 TlvTriplet::TlvTriplet(const uint8_t tagId, const uint64_t val)
895     : TlvTriplet(tagId, static_cast<uint8_t>(8), reinterpret_cast<const uint8_t *>(&val), static_cast<uint8_t>(8))
896 {}
897 
GetTagId() const898 uint8_t TlvTriplet::GetTagId() const
899 {
900     return tagId_;
901 }
902 
GetLen() const903 uint8_t TlvTriplet::GetLen() const
904 {
905     return len_;
906 }
907 
GetUnitLen() const908 uint8_t TlvTriplet::GetUnitLen() const
909 {
910     return unitLen_;
911 }
912 
GetVal() const913 const uint8_t *TlvTriplet::GetVal() const
914 {
915     return val_.data();
916 }
917 
GetUint16() const918 uint16_t TlvTriplet::GetUint16() const
919 {
920     if (len_ == ObexHeader::UINT16_LENGTH) {
921         if (unitLen_ > 1) {
922             return *(reinterpret_cast<const uint16_t *>(GetVal()));
923         }
924         return ObexUtils::GetBufData16(GetVal());
925     }
926     return 0;
927 }
928 
GetUint32() const929 uint32_t TlvTriplet::GetUint32() const
930 {
931     if (len_ == ObexHeader::UINT32_LENGTH) {
932         if (unitLen_ > 1) {
933             return *(reinterpret_cast<const uint32_t *>(GetVal()));
934         }
935         return ObexUtils::GetBufData32(GetVal());
936     }
937     return 0;
938 }
939 
GetUint64() const940 uint64_t TlvTriplet::GetUint64() const
941 {
942     if (len_ == ObexHeader::UINT64_LENGTH) {
943         if (unitLen_ > 1) {
944             return *(reinterpret_cast<const uint64_t *>(GetVal()));
945         }
946         return ObexUtils::GetBufData64(GetVal());
947     }
948     return 0;
949 }
950 
ObexOptionalHeader(uint8_t headerId)951 ObexOptionalHeader::ObexOptionalHeader(uint8_t headerId)
952 {
953     headerId_ = headerId;
954     dataSize_ = 0;
955     unitLen_ = 1;
956 }
957 
GetHeaderId() const958 uint8_t ObexOptionalHeader::GetHeaderId() const
959 {
960     return headerId_;
961 }
962 
GetHeaderTotalSize() const963 uint16_t ObexOptionalHeader::GetHeaderTotalSize() const
964 {
965     uint8_t prefixLen = 1;
966     if (HasLengthField()) {
967         prefixLen += ObexHeader::UINT16_LENGTH;
968     }
969     return prefixLen + GetHeaderDataSize();
970 }
971 
GetHeaderDataSize() const972 uint16_t ObexOptionalHeader::GetHeaderDataSize() const
973 {
974     return dataSize_;
975 }
976 
GetHeaderUnitLen() const977 uint8_t ObexOptionalHeader::GetHeaderUnitLen() const
978 {
979     return unitLen_;
980 }
981 
982 // ObexOptionalBytesHeader
ObexOptionalBytesHeader(const uint8_t headerId,const uint8_t * data,const uint16_t dataSize,const uint16_t unitLen)983 ObexOptionalBytesHeader::ObexOptionalBytesHeader(
984     const uint8_t headerId, const uint8_t *data, const uint16_t dataSize, const uint16_t unitLen)
985     : ObexOptionalHeader(headerId)
986 {
987     dataSize_ = dataSize;
988     data_.insert(data_.end(), data, data + dataSize);
989     unitLen_ = unitLen;
990 }
991 
GetBytes() const992 std::unique_ptr<uint8_t[]> ObexOptionalBytesHeader::GetBytes() const
993 {
994     if (dataSize_ < 1) {
995         return nullptr;
996     }
997     if (data_.size() == 0) {
998         return nullptr;
999     }
1000     auto buf = std::make_unique<uint8_t[]>(dataSize_);
1001     (void)memcpy_s(buf.get(), dataSize_, data_.data(), dataSize_);
1002     return buf;
1003 }
1004 
HasLengthField() const1005 bool ObexOptionalBytesHeader::HasLengthField() const
1006 {
1007     return true;
1008 }
1009 
GetHeaderClassType() const1010 ObexHeaderDataType ObexOptionalBytesHeader::GetHeaderClassType() const
1011 {
1012     return ObexHeaderDataType::BYTES;
1013 }
1014 
GetHeaderClassTypeName() const1015 std::string ObexOptionalBytesHeader::GetHeaderClassTypeName() const
1016 {
1017     return "ObexOptionalBytesHeader";
1018 }
1019 
Clone() const1020 std::unique_ptr<ObexOptionalHeader> ObexOptionalBytesHeader::Clone() const
1021 {
1022     return std::make_unique<ObexOptionalBytesHeader>(GetHeaderId(), data_.data(), dataSize_, unitLen_);
1023 }
1024 
1025 // ObexOptionalStringHeader
ObexOptionalStringHeader(const uint8_t headerId,const std::string & str)1026 ObexOptionalStringHeader::ObexOptionalStringHeader(const uint8_t headerId, const std::string &str)
1027     : ObexOptionalBytesHeader(headerId, reinterpret_cast<uint8_t *>(const_cast<char *>(str.c_str())),
1028     (str.size() == 0) ? 0 : (str.size() + 1), 1)
1029 {}
1030 
ObexOptionalStringHeader(const uint8_t headerId,const uint8_t * data,const uint16_t dataSize)1031 ObexOptionalStringHeader::ObexOptionalStringHeader(const uint8_t headerId,
1032     const uint8_t *data, const uint16_t dataSize)
1033     : ObexOptionalBytesHeader(headerId, data, dataSize)
1034 {}
1035 
GetString() const1036 std::string ObexOptionalStringHeader::GetString() const
1037 {
1038     if (dataSize_ == 0) {
1039         return "";
1040     }
1041     std::string str((char *)data_.data(), dataSize_ - 1);
1042     return str;
1043 }
1044 
GetHeaderClassType() const1045 ObexHeaderDataType ObexOptionalStringHeader::GetHeaderClassType() const
1046 {
1047     return ObexHeaderDataType::STRING;
1048 }
1049 
GetHeaderClassTypeName() const1050 std::string ObexOptionalStringHeader::GetHeaderClassTypeName() const
1051 {
1052     return "ObexOptionalStringHeader";
1053 }
1054 
Clone() const1055 std::unique_ptr<ObexOptionalHeader> ObexOptionalStringHeader::Clone() const
1056 {
1057     return std::make_unique<ObexOptionalStringHeader>(GetHeaderId(), GetString());
1058 }
1059 
1060 // ObexOptionalUnicodeHeader
ObexOptionalUnicodeHeader(const uint8_t headerId,const std::u16string & unicodeText)1061 ObexOptionalUnicodeHeader::ObexOptionalUnicodeHeader(const uint8_t headerId, const std::u16string &unicodeText)
1062     : ObexOptionalBytesHeader(headerId, reinterpret_cast<uint8_t *>(const_cast<char16_t *>(unicodeText.c_str())),
1063     (unicodeText.size() == 0) ? 0 : ((unicodeText.size() + 1) * ObexHeader::U16STRING_LENGTH),
1064     ObexHeader::U16STRING_LENGTH)
1065 {}
GetUnicodeText() const1066 std::u16string ObexOptionalUnicodeHeader::GetUnicodeText() const
1067 {
1068     if (dataSize_ == 0) {
1069         return u"";
1070     }
1071     std::u16string str(
1072         (char16_t *)data_.data(), (dataSize_ - ObexHeader::U16STRING_NULL_LENGTH) / ObexHeader::U16STRING_LENGTH);
1073     return str;
1074 }
1075 
GetHeaderClassType() const1076 ObexHeaderDataType ObexOptionalUnicodeHeader::GetHeaderClassType() const
1077 {
1078     return ObexHeaderDataType::UNICODE_TEXT;
1079 }
1080 
GetHeaderClassTypeName() const1081 std::string ObexOptionalUnicodeHeader::GetHeaderClassTypeName() const
1082 {
1083     return "ObexOptionalUnicodeHeader";
1084 }
1085 
Clone() const1086 std::unique_ptr<ObexOptionalHeader> ObexOptionalUnicodeHeader::Clone() const
1087 {
1088     return std::make_unique<ObexOptionalUnicodeHeader>(GetHeaderId(), GetUnicodeText());
1089 }
1090 
1091 // ObexOptionalByteHeader
ObexOptionalByteHeader(const uint8_t headerId,const uint8_t byte)1092 ObexOptionalByteHeader::ObexOptionalByteHeader(const uint8_t headerId, const uint8_t byte)
1093     : ObexOptionalBytesHeader(headerId, reinterpret_cast<uint8_t *>(const_cast<uint8_t *>(&byte)), 1)
1094 {}
HasLengthField() const1095 bool ObexOptionalByteHeader::HasLengthField() const
1096 {
1097     return false;
1098 }
1099 
GetByte() const1100 uint8_t ObexOptionalByteHeader::GetByte() const
1101 {
1102     return data_.data()[0];
1103 }
1104 
GetHeaderClassType() const1105 ObexHeaderDataType ObexOptionalByteHeader::GetHeaderClassType() const
1106 {
1107     return ObexHeaderDataType::BYTE;
1108 }
1109 
GetHeaderClassTypeName() const1110 std::string ObexOptionalByteHeader::GetHeaderClassTypeName() const
1111 {
1112     return "ObexOptionalByteHeader";
1113 }
1114 
Clone() const1115 std::unique_ptr<ObexOptionalHeader> ObexOptionalByteHeader::Clone() const
1116 {
1117     return std::make_unique<ObexOptionalByteHeader>(GetHeaderId(), GetByte());
1118 }
1119 
1120 // ObexOptionalWordHeader
ObexOptionalWordHeader(const uint8_t headerId,const uint32_t word)1121 ObexOptionalWordHeader::ObexOptionalWordHeader(const uint8_t headerId, const uint32_t word)
1122     : ObexOptionalBytesHeader(headerId, reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&word)),
1123     ObexHeader::UINT32_LENGTH, ObexHeader::UINT32_LENGTH)
1124 {}
GetWord() const1125 uint32_t ObexOptionalWordHeader::GetWord() const
1126 {
1127     return ((const uint32_t *)data_.data())[0];
1128 }
1129 
GetHeaderClassType() const1130 ObexHeaderDataType ObexOptionalWordHeader::GetHeaderClassType() const
1131 {
1132     return ObexHeaderDataType::WORD;
1133 }
1134 
GetHeaderClassTypeName() const1135 std::string ObexOptionalWordHeader::GetHeaderClassTypeName() const
1136 {
1137     return "ObexOptionalWordHeader";
1138 }
1139 
Clone() const1140 std::unique_ptr<ObexOptionalHeader> ObexOptionalWordHeader::Clone() const
1141 {
1142     return std::make_unique<ObexOptionalWordHeader>(GetHeaderId(), GetWord());
1143 }
1144 
HasLengthField() const1145 bool ObexOptionalWordHeader::HasLengthField() const
1146 {
1147     return false;
1148 }
1149 
1150 // ObexOptionalTLVHeader
ObexOptionalTlvHeader(const uint8_t headerId)1151 ObexOptionalTlvHeader::ObexOptionalTlvHeader(const uint8_t headerId) : ObexOptionalHeader(headerId)
1152 {
1153     dataSize_ = 0;
1154     unitLen_ = 1;
1155 }
1156 
ObexOptionalTlvHeader(const uint8_t headerId,const ObexTlvParamters & tlvParamters)1157 ObexOptionalTlvHeader::ObexOptionalTlvHeader(const uint8_t headerId, const ObexTlvParamters &tlvParamters)
1158     : ObexOptionalTlvHeader(headerId)
1159 {
1160     uint16_t dataSize = 0;
1161     auto newTlvParamters = std::make_unique<ObexTlvParamters>();
1162     for (auto &param : tlvParamters.GetTlvTriplets()) {
1163         dataSize += param->GetLen() + TAG_PREFIX_LEN;
1164         newTlvParamters->AppendTlvtriplet(*(param.get()));
1165     }
1166     tlvParamters_ = std::move(newTlvParamters);
1167     dataSize_ = dataSize;
1168 }
1169 
ObexOptionalTlvHeader(const uint8_t headerId,const uint8_t * data,const uint16_t dataSize)1170 ObexOptionalTlvHeader::ObexOptionalTlvHeader(const uint8_t headerId, const uint8_t *data, const uint16_t dataSize)
1171     : ObexOptionalTlvHeader(headerId)
1172 {
1173     auto newTlvParamters = std::make_unique<ObexTlvParamters>();
1174     uint16_t pos = 0;
1175     while (pos < dataSize) {
1176         const uint8_t tagId = data[pos++];
1177         const uint8_t len = data[pos++];
1178         TlvTriplet tlv(tagId, len, &data[pos]);
1179         newTlvParamters->AppendTlvtriplet(tlv);
1180         pos += len;
1181     }
1182     tlvParamters_ = std::move(newTlvParamters);
1183     dataSize_ = dataSize;
1184 }
1185 
GetTlvParamters() const1186 const std::unique_ptr<ObexTlvParamters> &ObexOptionalTlvHeader::GetTlvParamters() const
1187 {
1188     return tlvParamters_;
1189 }
1190 
GetTlvtriplet(const uint8_t tagId) const1191 const TlvTriplet *ObexOptionalTlvHeader::GetTlvtriplet(const uint8_t tagId) const
1192 {
1193     if (tlvParamters_ == nullptr) {
1194         return nullptr;
1195     }
1196     return tlvParamters_->GetTlvtriplet(tagId);
1197 }
1198 
HasLengthField() const1199 bool ObexOptionalTlvHeader::HasLengthField() const
1200 {
1201     return true;
1202 }
1203 
GetHeaderClassType() const1204 ObexHeaderDataType ObexOptionalTlvHeader::GetHeaderClassType() const
1205 {
1206     return ObexHeaderDataType::TLV;
1207 }
1208 
GetHeaderClassTypeName() const1209 std::string ObexOptionalTlvHeader::GetHeaderClassTypeName() const
1210 {
1211     return "ObexOptionalTlvHeader";
1212 }
1213 
GetBytes() const1214 std::unique_ptr<uint8_t[]> ObexOptionalTlvHeader::GetBytes() const
1215 {
1216     if (dataSize_ < 1) {
1217         return nullptr;
1218     }
1219     auto buf = std::make_unique<uint8_t[]>(dataSize_);
1220     (void)memset_s(buf.get(), dataSize_, 0x00, dataSize_);
1221     size_t p = 0;
1222     bool isBigEndian = ObexUtils::SysIsBigEndian();
1223     for (auto &param : GetTlvParamters()->GetTlvTriplets()) {
1224         *(buf.get() + p) = param->GetTagId();
1225         p++;
1226         *(buf.get() + p) = param->GetLen();
1227         p++;
1228         (void)memcpy_s(buf.get() + p, dataSize_ - p, param->GetVal(), param->GetLen());
1229         if (!isBigEndian && param->GetUnitLen() > 1) {
1230             ObexUtils::DataReverse(buf.get() + p, param->GetLen(), param->GetUnitLen());
1231         }
1232         p += param->GetLen();
1233     }
1234     return buf;
1235 }
1236 
Clone() const1237 std::unique_ptr<ObexOptionalHeader> ObexOptionalTlvHeader::Clone() const
1238 {
1239     return std::make_unique<ObexOptionalTlvHeader>(GetHeaderId(), *GetTlvParamters().get());
1240 }
1241 
1242 // ObexTlvParamters
GetTlvTriplets() const1243 const std::vector<std::unique_ptr<TlvTriplet>> &ObexTlvParamters::GetTlvTriplets() const
1244 {
1245     return tlvTriplets_;
1246 }
1247 
GetTlvtriplet(const uint8_t tagId) const1248 const TlvTriplet *ObexTlvParamters::GetTlvtriplet(const uint8_t tagId) const
1249 {
1250     auto itr = std::find_if(tlvTriplets_.begin(), tlvTriplets_.end(),
1251         [tagId](const std::unique_ptr<TlvTriplet> &rhs)->bool {
1252         return (tagId == rhs->GetTagId());
1253     });
1254     if (itr != tlvTriplets_.end()) {
1255         return itr->get();
1256     }
1257     return nullptr;
1258 }
1259 
AppendTlvtriplet(const TlvTriplet & tlvTriplet)1260 void ObexTlvParamters::AppendTlvtriplet(const TlvTriplet &tlvTriplet)
1261 {
1262     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(tlvTriplet));
1263 }
1264 
1265 // ObexDigestChallenge
1266 
1267 /************************* OBEX Auth Digest Challenge *******************************/
1268 const uint8_t ObexDigestChallenge::NONCE;
1269 const uint8_t ObexDigestChallenge::OPTIONS;
1270 const uint8_t ObexDigestChallenge::REALM;
GetNonce() const1271 const TlvTriplet *ObexDigestChallenge::GetNonce() const
1272 {
1273     return GetTlvtriplet(ObexDigestChallenge::NONCE);
1274 }
1275 
GetOptions() const1276 const TlvTriplet *ObexDigestChallenge::GetOptions() const
1277 {
1278     return GetTlvtriplet(ObexDigestChallenge::OPTIONS);
1279 }
1280 
GetRealm() const1281 const TlvTriplet *ObexDigestChallenge::GetRealm() const
1282 {
1283     return GetTlvtriplet(ObexDigestChallenge::REALM);
1284 }
1285 
AppendNonce(const uint8_t * nonce,const uint8_t length)1286 void ObexDigestChallenge::AppendNonce(const uint8_t *nonce, const uint8_t length)
1287 {
1288     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestChallenge::NONCE, length, nonce));
1289 }
1290 
AppendOptions(const uint8_t options)1291 void ObexDigestChallenge::AppendOptions(const uint8_t options)
1292 {
1293     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestChallenge::OPTIONS, options));
1294 }
1295 
AppendRealm(const uint8_t * realm,const uint8_t length)1296 void ObexDigestChallenge::AppendRealm(const uint8_t *realm, const uint8_t length)
1297 {
1298     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestChallenge::REALM, length, realm));
1299 }
1300 
1301 /************************* OBEX Auth Digest Response *******************************/
1302 const uint8_t ObexDigestResponse::REQUEST_DIGEST;
1303 const uint8_t ObexDigestResponse::USER_ID;
1304 const uint8_t ObexDigestResponse::NONCE;
1305 const uint8_t ObexDigestResponse::MAX_USER_ID_LEN;
1306 
GetRequestDigest() const1307 const TlvTriplet *ObexDigestResponse::GetRequestDigest() const
1308 {
1309     return GetTlvtriplet(ObexDigestResponse::REQUEST_DIGEST);
1310 }
1311 
GetUserId() const1312 const TlvTriplet *ObexDigestResponse::GetUserId() const
1313 {
1314     return GetTlvtriplet(ObexDigestResponse::USER_ID);
1315 }
1316 
GetNonce() const1317 const TlvTriplet *ObexDigestResponse::GetNonce() const
1318 {
1319     return GetTlvtriplet(ObexDigestResponse::NONCE);
1320 }
1321 
AppendRequestDigest(const uint8_t * requestDigest,const uint8_t length)1322 void ObexDigestResponse::AppendRequestDigest(const uint8_t *requestDigest, const uint8_t length)
1323 {
1324     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestResponse::REQUEST_DIGEST, length, requestDigest));
1325 }
1326 
AppendUserId(const uint8_t * userId,const uint8_t length)1327 void ObexDigestResponse::AppendUserId(const uint8_t *userId, const uint8_t length)
1328 {
1329     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestResponse::USER_ID, length, userId));
1330 }
1331 
AppendNonce(const uint8_t * nonce,const uint8_t length)1332 void ObexDigestResponse::AppendNonce(const uint8_t *nonce, const uint8_t length)
1333 {
1334     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexDigestResponse::NONCE, length, nonce));
1335 }
1336 
1337 /************************* OBEX Session Parameter ID *******************************/
1338 const uint8_t ObexSessionParameters::DEVICE_ADDRESS;
1339 const uint8_t ObexSessionParameters::NONCE;
1340 const uint8_t ObexSessionParameters::SESSION_ID;
1341 const uint8_t ObexSessionParameters::NEXT_SEQUENCE_NUMBER;
1342 const uint8_t ObexSessionParameters::TIMEOUT;
1343 const uint8_t ObexSessionParameters::SESSION_OPCODE;
GetDeviceAddress() const1344 const TlvTriplet *ObexSessionParameters::GetDeviceAddress() const
1345 {
1346     return GetTlvtriplet(ObexSessionParameters::DEVICE_ADDRESS);
1347 }
1348 
GetNonce() const1349 const TlvTriplet *ObexSessionParameters::GetNonce() const
1350 {
1351     return GetTlvtriplet(ObexSessionParameters::NONCE);
1352 }
1353 
GetSessionId() const1354 const TlvTriplet *ObexSessionParameters::GetSessionId() const
1355 {
1356     return GetTlvtriplet(ObexSessionParameters::SESSION_ID);
1357 }
1358 
GetNextSeqNum() const1359 const TlvTriplet *ObexSessionParameters::GetNextSeqNum() const
1360 {
1361     return GetTlvtriplet(ObexSessionParameters::NEXT_SEQUENCE_NUMBER);
1362 }
1363 
GetTimeout() const1364 const TlvTriplet *ObexSessionParameters::GetTimeout() const
1365 {
1366     return GetTlvtriplet(ObexSessionParameters::TIMEOUT);
1367 }
1368 
GetSessionOpcode() const1369 const TlvTriplet *ObexSessionParameters::GetSessionOpcode() const
1370 {
1371     return GetTlvtriplet(ObexSessionParameters::SESSION_OPCODE);
1372 }
1373 
AppendDeviceAddress(const uint8_t * deviceAddress,const uint8_t length)1374 void ObexSessionParameters::AppendDeviceAddress(const uint8_t *deviceAddress, const uint8_t length)
1375 {
1376     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexSessionParameters::DEVICE_ADDRESS, length, deviceAddress));
1377 }
1378 
AppendNonce(const uint8_t * nonce,const uint8_t length)1379 void ObexSessionParameters::AppendNonce(const uint8_t *nonce, const uint8_t length)
1380 {
1381     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexSessionParameters::NONCE, length, nonce));
1382 }
1383 
AppendSessionId(const uint8_t * sessionId,const uint8_t length)1384 void ObexSessionParameters::AppendSessionId(const uint8_t *sessionId, const uint8_t length)
1385 {
1386     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexSessionParameters::SESSION_ID, length, sessionId));
1387 }
1388 
AppendNextSeqNum(const uint8_t nextSeqNum)1389 void ObexSessionParameters::AppendNextSeqNum(const uint8_t nextSeqNum)
1390 {
1391     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexSessionParameters::NEXT_SEQUENCE_NUMBER, nextSeqNum));
1392 }
1393 
AppendTimeout(const uint32_t timeout)1394 void ObexSessionParameters::AppendTimeout(const uint32_t timeout)
1395 {
1396     tlvTriplets_.push_back(std::make_unique<TlvTriplet>(ObexSessionParameters::TIMEOUT, timeout));
1397 }
1398 
AppendSessionOpcode(const SessionOpcode opcode)1399 void ObexSessionParameters::AppendSessionOpcode(const SessionOpcode opcode)
1400 {
1401     tlvTriplets_.push_back(
1402         std::make_unique<TlvTriplet>(ObexSessionParameters::SESSION_OPCODE, static_cast<uint8_t>(opcode)));
1403 }
1404 }  // namespace bluetooth
1405 }  // namespace OHOS