Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #include <protocols/secure_channel/Constants.h>
20 : #include <protocols/secure_channel/StatusReport.h>
21 :
22 : #include <lib/support/BufferReader.h>
23 : #include <lib/support/CodeUtils.h>
24 : #include <lib/support/TypeTraits.h>
25 :
26 : #include <type_traits>
27 :
28 : using namespace chip::Encoding;
29 : using GeneralStatusCode = chip::Protocols::SecureChannel::GeneralStatusCode;
30 :
31 : namespace chip {
32 : namespace Protocols {
33 : namespace SecureChannel {
34 :
35 25 : StatusReport::StatusReport() :
36 25 : mGeneralCode(GeneralStatusCode::kSuccess), mProtocolId(SecureChannel::Id), mProtocolCode(0), mProtocolData(nullptr)
37 25 : {}
38 :
39 18 : StatusReport::StatusReport(GeneralStatusCode generalCode, Protocols::Id protocolId, uint16_t protocolCode) :
40 18 : mGeneralCode(generalCode), mProtocolId(protocolId), mProtocolCode(protocolCode), mProtocolData(nullptr)
41 18 : {}
42 :
43 3 : StatusReport::StatusReport(GeneralStatusCode generalCode, Protocols::Id protocolId, uint16_t protocolCode,
44 3 : System::PacketBufferHandle protocolData) :
45 3 : mGeneralCode(generalCode),
46 3 : mProtocolId(protocolId), mProtocolCode(protocolCode), mProtocolData(std::move(protocolData))
47 3 : {}
48 :
49 25 : CHIP_ERROR StatusReport::Parse(System::PacketBufferHandle buf)
50 : {
51 25 : uint16_t tempGeneralCode = 0;
52 :
53 25 : VerifyOrReturnError(!buf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
54 :
55 24 : uint8_t * bufStart = buf->Start();
56 24 : LittleEndian::Reader bufReader(bufStart, buf->DataLength());
57 :
58 : uint32_t protocolId;
59 24 : ReturnErrorOnFailure(bufReader.Read16(&tempGeneralCode).Read32(&protocolId).Read16(&mProtocolCode).StatusCode());
60 23 : mProtocolId = Protocols::Id::FromFullyQualifiedSpecForm(protocolId);
61 23 : mGeneralCode = static_cast<GeneralStatusCode>(tempGeneralCode);
62 :
63 : // Any data that exists after the required fields is considered protocol-specific data.
64 23 : if (bufReader.OctetsRead() < buf->DataLength())
65 : {
66 6 : mProtocolData = System::PacketBufferHandle::NewWithData(buf->Start() + bufReader.OctetsRead(),
67 3 : buf->DataLength() - bufReader.OctetsRead(),
68 3 : /* aAdditionalSize = */ 0, /* aReservedSize = */ 0);
69 3 : if (mProtocolData.IsNull())
70 : {
71 0 : return CHIP_ERROR_NO_MEMORY;
72 : }
73 : }
74 : else
75 : {
76 20 : mProtocolData = nullptr;
77 : }
78 :
79 23 : return CHIP_NO_ERROR;
80 : }
81 :
82 42 : Encoding::LittleEndian::BufferWriter & StatusReport::WriteToBuffer(Encoding::LittleEndian::BufferWriter & buf) const
83 : {
84 42 : buf.Put16(to_underlying(mGeneralCode)).Put32(mProtocolId.ToFullyQualifiedSpecForm()).Put16(mProtocolCode);
85 42 : if (!mProtocolData.IsNull())
86 : {
87 6 : buf.Put(mProtocolData->Start(), mProtocolData->DataLength());
88 : }
89 42 : return buf;
90 : }
91 :
92 21 : size_t StatusReport::Size() const
93 : {
94 21 : LittleEndian::BufferWriter emptyBuf(nullptr, 0);
95 21 : return WriteToBuffer(emptyBuf).Needed();
96 : }
97 :
98 2 : System::PacketBufferHandle StatusReport::MakeBusyStatusReportMessage(System::Clock::Milliseconds16 minimumWaitTime)
99 : {
100 : using namespace Protocols::SecureChannel;
101 2 : constexpr uint8_t kBusyStatusReportProtocolDataSize = sizeof(minimumWaitTime.count()); // 16-bits
102 :
103 2 : auto handle = System::PacketBufferHandle::New(kBusyStatusReportProtocolDataSize, 0);
104 2 : VerifyOrReturnValue(!handle.IsNull(), handle,
105 : ChipLogError(SecureChannel, "Failed to allocate protocol data for busy status report"));
106 :
107 : // Build the protocol data with minimum wait time
108 2 : Encoding::LittleEndian::PacketBufferWriter protocolDataBufferWriter(std::move(handle));
109 2 : protocolDataBufferWriter.Put16(minimumWaitTime.count());
110 2 : handle = protocolDataBufferWriter.Finalize();
111 2 : VerifyOrReturnValue(!handle.IsNull(), handle,
112 : ChipLogError(SecureChannel, "Failed to finalize protocol data for busy status report"));
113 :
114 : // Build a busy status report
115 2 : StatusReport statusReport(GeneralStatusCode::kBusy, Protocols::SecureChannel::Id, kProtocolCodeBusy, std::move(handle));
116 :
117 : // Build the status report message
118 2 : handle = System::PacketBufferHandle::New(statusReport.Size());
119 2 : VerifyOrReturnValue(!handle.IsNull(), handle, ChipLogError(SecureChannel, "Failed to allocate status report message"));
120 2 : Encoding::LittleEndian::PacketBufferWriter bbuf(std::move(handle));
121 :
122 2 : statusReport.WriteToBuffer(bbuf);
123 2 : return bbuf.Finalize();
124 2 : }
125 :
126 : } // namespace SecureChannel
127 : } // namespace Protocols
128 : } // namespace chip
|