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 "BdxUri.h" 20 : 21 : #include <lib/core/CHIPEncoding.h> 22 : #include <lib/core/CHIPSafeCasts.h> 23 : #include <lib/support/BufferWriter.h> 24 : #include <lib/support/BytesToHex.h> 25 : #include <lib/support/CodeUtils.h> 26 : 27 : #include <cstring> 28 : 29 : namespace chip { 30 : namespace bdx { 31 : 32 : constexpr size_t kSchemeLen = sizeof(kScheme) - 1; 33 : constexpr size_t kHostPos = kSchemeLen; 34 : constexpr size_t kHostLen = sizeof(NodeId) * 2; 35 : constexpr size_t kHostEnd = kHostPos + kHostLen; 36 : constexpr size_t kSeparatorLen = 1; 37 : constexpr size_t kMinUriLen = kHostEnd + kSeparatorLen + 1 /* file-designator */; 38 : 39 : static_assert(sizeof(NodeId) == sizeof(uint64_t), "The code below assumes NodeId is uint64_t"); 40 : 41 8 : CHIP_ERROR ParseURI(CharSpan uri, NodeId & nodeId, CharSpan & fileDesignator) 42 : { 43 8 : VerifyOrReturnError(uri.size() >= kMinUriLen, CHIP_ERROR_INVALID_STRING_LENGTH); 44 7 : VerifyOrReturnError(memcmp(uri.data(), kScheme, kSchemeLen) == 0, CHIP_ERROR_INVALID_SCHEME_PREFIX); 45 : 46 : uint8_t nodeIdBytes[sizeof(NodeId)]; 47 6 : VerifyOrReturnError(Encoding::HexToBytes(uri.data() + kHostPos, kHostLen, nodeIdBytes, sizeof(nodeIdBytes)) == 48 : sizeof(nodeIdBytes), 49 : CHIP_ERROR_INVALID_DESTINATION_NODE_ID); 50 : 51 4 : nodeId = Encoding::BigEndian::Get64(nodeIdBytes); 52 4 : VerifyOrReturnError(IsOperationalNodeId(nodeId), CHIP_ERROR_INVALID_DESTINATION_NODE_ID); 53 3 : VerifyOrReturnError(uri.data()[kHostEnd] == '/', CHIP_ERROR_MISSING_URI_SEPARATOR); 54 : 55 2 : fileDesignator = uri.SubSpan(kHostEnd + kSeparatorLen); 56 : 57 2 : return CHIP_NO_ERROR; 58 : } 59 : 60 4 : CHIP_ERROR MakeURI(NodeId nodeId, CharSpan fileDesignator, MutableCharSpan & uri) 61 : { 62 4 : VerifyOrReturnError(fileDesignator.size() > 0, CHIP_ERROR_INVALID_STRING_LENGTH); 63 : 64 : uint8_t nodeIdBytes[sizeof(NodeId)]; 65 2 : Encoding::BigEndian::Put64(nodeIdBytes, nodeId); 66 : 67 : char nodeIdHex[sizeof(NodeId) * 2]; 68 2 : ReturnErrorOnFailure(Encoding::BytesToUppercaseHexBuffer(nodeIdBytes, sizeof(nodeIdBytes), nodeIdHex, sizeof(nodeIdHex))); 69 : 70 2 : char * buffer = uri.data(); 71 2 : size_t bufferSize = uri.size(); 72 2 : memset(buffer, 0, bufferSize); 73 : 74 : // Reduce the buffer writer size by one to reserve the last byte for the null-terminator 75 2 : Encoding::BufferWriter writer(Uint8::from_char(buffer), bufferSize - 1); 76 2 : writer.Put(kScheme, kSchemeLen); 77 2 : writer.Put(nodeIdHex, sizeof(nodeIdHex)); 78 2 : writer.Put("/"); 79 2 : writer.Put(fileDesignator.data(), fileDesignator.size()); 80 : 81 2 : VerifyOrReturnError(writer.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); 82 2 : uri.reduce_size(writer.WritePos()); 83 : 84 2 : return CHIP_NO_ERROR; 85 : } 86 : 87 : } // namespace bdx 88 : } // namespace chip