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 <optional>
20 : #include <protocols/secure_channel/Constants.h>
21 : #include <protocols/secure_channel/StatusReport.h>
22 :
23 : #include <lib/support/BufferReader.h>
24 : #include <lib/support/CodeUtils.h>
25 : #include <lib/support/TypeTraits.h>
26 :
27 : #include <type_traits>
28 :
29 : using namespace chip::Encoding;
30 : using GeneralStatusCode = chip::Protocols::SecureChannel::GeneralStatusCode;
31 :
32 : namespace chip {
33 : namespace Protocols {
34 : namespace SecureChannel {
35 :
36 25 : StatusReport::StatusReport() :
37 25 : mGeneralCode(GeneralStatusCode::kSuccess), mProtocolId(SecureChannel::Id), mProtocolCode(0), mProtocolData(nullptr)
38 25 : {}
39 :
40 18 : StatusReport::StatusReport(GeneralStatusCode generalCode, Protocols::Id protocolId, uint16_t protocolCode) :
41 18 : mGeneralCode(generalCode), mProtocolId(protocolId), mProtocolCode(protocolCode), mProtocolData(nullptr)
42 18 : {}
43 :
44 3 : StatusReport::StatusReport(GeneralStatusCode generalCode, Protocols::Id protocolId, uint16_t protocolCode,
45 3 : System::PacketBufferHandle protocolData) :
46 3 : mGeneralCode(generalCode),
47 3 : mProtocolId(protocolId), mProtocolCode(protocolCode), mProtocolData(std::move(protocolData))
48 3 : {}
49 :
50 25 : CHIP_ERROR StatusReport::Parse(System::PacketBufferHandle buf)
51 : {
52 25 : uint16_t tempGeneralCode = 0;
53 :
54 25 : VerifyOrReturnError(!buf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
55 :
56 24 : uint8_t * bufStart = buf->Start();
57 24 : LittleEndian::Reader bufReader(bufStart, buf->DataLength());
58 :
59 : uint32_t protocolId;
60 24 : ReturnErrorOnFailure(bufReader.Read16(&tempGeneralCode).Read32(&protocolId).Read16(&mProtocolCode).StatusCode());
61 23 : mProtocolId = Protocols::Id::FromFullyQualifiedSpecForm(protocolId);
62 23 : mGeneralCode = static_cast<GeneralStatusCode>(tempGeneralCode);
63 :
64 : // Any data that exists after the required fields is considered protocol-specific data.
65 23 : if (bufReader.OctetsRead() < buf->DataLength())
66 : {
67 6 : mProtocolData = System::PacketBufferHandle::NewWithData(buf->Start() + bufReader.OctetsRead(),
68 3 : buf->DataLength() - bufReader.OctetsRead(),
69 3 : /* aAdditionalSize = */ 0, /* aReservedSize = */ 0);
70 3 : if (mProtocolData.IsNull())
71 : {
72 0 : return CHIP_ERROR_NO_MEMORY;
73 : }
74 :
75 3 : if (IsBusy())
76 : {
77 2 : Encoding::LittleEndian::Reader reader(mProtocolData->Start(), mProtocolData->DataLength());
78 2 : uint16_t tmpMinimumWaitTime = 0;
79 2 : ReturnErrorOnFailure(reader.Read16(&tmpMinimumWaitTime).StatusCode());
80 2 : mMinimumWaitTime = std::make_optional<System::Clock::Milliseconds16>(tmpMinimumWaitTime);
81 : }
82 : }
83 : else
84 : {
85 20 : mProtocolData = nullptr;
86 : }
87 :
88 23 : return CHIP_NO_ERROR;
89 : }
90 :
91 42 : Encoding::LittleEndian::BufferWriter & StatusReport::WriteToBuffer(Encoding::LittleEndian::BufferWriter & buf) const
92 : {
93 42 : buf.Put16(to_underlying(mGeneralCode)).Put32(mProtocolId.ToFullyQualifiedSpecForm()).Put16(mProtocolCode);
94 42 : if (!mProtocolData.IsNull())
95 : {
96 6 : buf.Put(mProtocolData->Start(), mProtocolData->DataLength());
97 : }
98 42 : return buf;
99 : }
100 :
101 21 : size_t StatusReport::Size() const
102 : {
103 21 : LittleEndian::BufferWriter emptyBuf(nullptr, 0);
104 21 : return WriteToBuffer(emptyBuf).Needed();
105 : }
106 :
107 6 : bool StatusReport::IsBusy() const
108 : {
109 6 : return (mGeneralCode == GeneralStatusCode::kBusy && mProtocolCode == kProtocolCodeBusy);
110 : }
111 :
112 2 : System::PacketBufferHandle StatusReport::MakeBusyStatusReportMessage(System::Clock::Milliseconds16 minimumWaitTime)
113 : {
114 : using namespace Protocols::SecureChannel;
115 2 : constexpr uint8_t kBusyStatusReportProtocolDataSize = sizeof(minimumWaitTime.count()); // 16-bits
116 :
117 2 : auto handle = System::PacketBufferHandle::New(kBusyStatusReportProtocolDataSize, 0);
118 2 : VerifyOrReturnValue(!handle.IsNull(), handle,
119 : ChipLogError(SecureChannel, "Failed to allocate protocol data for busy status report"));
120 :
121 : // Build the protocol data with minimum wait time
122 2 : Encoding::LittleEndian::PacketBufferWriter protocolDataBufferWriter(std::move(handle));
123 2 : protocolDataBufferWriter.Put16(minimumWaitTime.count());
124 2 : handle = protocolDataBufferWriter.Finalize();
125 2 : VerifyOrReturnValue(!handle.IsNull(), handle,
126 : ChipLogError(SecureChannel, "Failed to finalize protocol data for busy status report"));
127 :
128 : // Build a busy status report
129 2 : StatusReport statusReport(GeneralStatusCode::kBusy, Protocols::SecureChannel::Id, kProtocolCodeBusy, std::move(handle));
130 2 : statusReport.mMinimumWaitTime = std::make_optional<System::Clock::Milliseconds16>(minimumWaitTime);
131 :
132 : // Build the status report message
133 2 : handle = System::PacketBufferHandle::New(statusReport.Size());
134 2 : VerifyOrReturnValue(!handle.IsNull(), handle, ChipLogError(SecureChannel, "Failed to allocate status report message"));
135 2 : Encoding::LittleEndian::PacketBufferWriter bbuf(std::move(handle));
136 :
137 2 : statusReport.WriteToBuffer(bbuf);
138 2 : return bbuf.Finalize();
139 2 : }
140 :
141 : } // namespace SecureChannel
142 : } // namespace Protocols
143 : } // namespace chip
|