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 23 : StatusReport::StatusReport() : 36 23 : mGeneralCode(GeneralStatusCode::kSuccess), mProtocolId(SecureChannel::Id), mProtocolCode(0), mProtocolData(nullptr) 37 23 : {} 38 : 39 17 : StatusReport::StatusReport(GeneralStatusCode generalCode, Protocols::Id protocolId, uint16_t protocolCode) : 40 17 : mGeneralCode(generalCode), mProtocolId(protocolId), mProtocolCode(protocolCode), mProtocolData(nullptr) 41 17 : {} 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 23 : CHIP_ERROR StatusReport::Parse(System::PacketBufferHandle buf) 50 : { 51 23 : uint16_t tempGeneralCode = 0; 52 : 53 23 : ReturnErrorCodeIf(buf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); 54 : 55 22 : uint8_t * bufStart = buf->Start(); 56 22 : LittleEndian::Reader bufReader(bufStart, buf->DataLength()); 57 : 58 : uint32_t protocolId; 59 22 : ReturnErrorOnFailure(bufReader.Read16(&tempGeneralCode).Read32(&protocolId).Read16(&mProtocolCode).StatusCode()); 60 21 : mProtocolId = Protocols::Id::FromFullyQualifiedSpecForm(protocolId); 61 21 : mGeneralCode = static_cast<GeneralStatusCode>(tempGeneralCode); 62 : 63 : // Any data that exists after the required fields is considered protocol-specific data. 64 21 : 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 18 : mProtocolData = nullptr; 77 : } 78 : 79 21 : return CHIP_NO_ERROR; 80 : } 81 : 82 40 : Encoding::LittleEndian::BufferWriter & StatusReport::WriteToBuffer(Encoding::LittleEndian::BufferWriter & buf) const 83 : { 84 40 : buf.Put16(to_underlying(mGeneralCode)).Put32(mProtocolId.ToFullyQualifiedSpecForm()).Put16(mProtocolCode); 85 40 : if (!mProtocolData.IsNull()) 86 : { 87 6 : buf.Put(mProtocolData->Start(), mProtocolData->DataLength()); 88 : } 89 40 : return buf; 90 : } 91 : 92 20 : size_t StatusReport::Size() const 93 : { 94 20 : LittleEndian::BufferWriter emptyBuf(nullptr, 0); 95 20 : 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