/src/connectedhomeip/src/protocols/bdx/BdxUri.cpp
Line | Count | Source |
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 | | CHIP_ERROR ParseURI(CharSpan uri, NodeId & nodeId, CharSpan & fileDesignator) |
42 | 0 | { |
43 | 0 | VerifyOrReturnError(uri.size() >= kMinUriLen, CHIP_ERROR_INVALID_STRING_LENGTH); |
44 | 0 | VerifyOrReturnError(memcmp(uri.data(), kScheme, kSchemeLen) == 0, CHIP_ERROR_INVALID_SCHEME_PREFIX); |
45 | | |
46 | 0 | uint8_t nodeIdBytes[sizeof(NodeId)]; |
47 | 0 | VerifyOrReturnError(Encoding::HexToBytes(uri.data() + kHostPos, kHostLen, nodeIdBytes, sizeof(nodeIdBytes)) == |
48 | 0 | sizeof(nodeIdBytes), |
49 | 0 | CHIP_ERROR_INVALID_DESTINATION_NODE_ID); |
50 | | |
51 | 0 | nodeId = Encoding::BigEndian::Get64(nodeIdBytes); |
52 | 0 | VerifyOrReturnError(IsOperationalNodeId(nodeId), CHIP_ERROR_INVALID_DESTINATION_NODE_ID); |
53 | 0 | VerifyOrReturnError(uri.data()[kHostEnd] == '/', CHIP_ERROR_MISSING_URI_SEPARATOR); |
54 | | |
55 | 0 | fileDesignator = uri.SubSpan(kHostEnd + kSeparatorLen); |
56 | |
|
57 | 0 | return CHIP_NO_ERROR; |
58 | 0 | } |
59 | | |
60 | | CHIP_ERROR MakeURI(NodeId nodeId, CharSpan fileDesignator, MutableCharSpan & uri) |
61 | 0 | { |
62 | 0 | VerifyOrReturnError(fileDesignator.size() > 0, CHIP_ERROR_INVALID_STRING_LENGTH); |
63 | | |
64 | 0 | uint8_t nodeIdBytes[sizeof(NodeId)]; |
65 | 0 | Encoding::BigEndian::Put64(nodeIdBytes, nodeId); |
66 | |
|
67 | 0 | char nodeIdHex[sizeof(NodeId) * 2]; |
68 | 0 | ReturnErrorOnFailure(Encoding::BytesToUppercaseHexBuffer(nodeIdBytes, sizeof(nodeIdBytes), nodeIdHex, sizeof(nodeIdHex))); |
69 | | |
70 | 0 | char * buffer = uri.data(); |
71 | 0 | size_t bufferSize = uri.size(); |
72 | 0 | memset(buffer, 0, bufferSize); |
73 | | |
74 | | // Reduce the buffer writer size by one to reserve the last byte for the null-terminator |
75 | 0 | Encoding::BufferWriter writer(Uint8::from_char(buffer), bufferSize - 1); |
76 | 0 | writer.Put(kScheme, kSchemeLen); |
77 | 0 | writer.Put(nodeIdHex, sizeof(nodeIdHex)); |
78 | 0 | writer.Put("/"); |
79 | 0 | writer.Put(fileDesignator.data(), fileDesignator.size()); |
80 | |
|
81 | 0 | VerifyOrReturnError(writer.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); |
82 | 0 | uri.reduce_size(writer.WritePos()); |
83 | |
|
84 | 0 | return CHIP_NO_ERROR; |
85 | 0 | } |
86 | | |
87 | | } // namespace bdx |
88 | | } // namespace chip |