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 : /**
20 : * @file
21 : * This file implements an object for a Matter User Directed Commissioning unsolicited
22 : * initiator (client).
23 : *
24 : */
25 :
26 : #include "UserDirectedCommissioning.h"
27 : #include <transport/raw/Base.h>
28 :
29 : #ifdef __ZEPHYR__
30 : #include <zephyr/kernel.h>
31 : #endif // __ZEPHYR__
32 :
33 : #include <unistd.h>
34 :
35 : namespace chip {
36 : namespace Protocols {
37 : namespace UserDirectedCommissioning {
38 :
39 0 : CHIP_ERROR UserDirectedCommissioningClient::SendUDCMessage(TransportMgrBase * transportMgr, IdentificationDeclaration id,
40 : chip::Transport::PeerAddress peerAddress)
41 : {
42 : uint8_t idBuffer[IdentificationDeclaration::kUdcTLVDataMaxBytes];
43 0 : uint32_t length = id.WritePayload(idBuffer, sizeof(idBuffer));
44 0 : if (length == 0)
45 : {
46 0 : ChipLogError(AppServer, "UDC: error writing payload\n");
47 0 : return CHIP_ERROR_INTERNAL;
48 : }
49 :
50 0 : chip::System::PacketBufferHandle payload = chip::MessagePacketBuffer::NewWithData(idBuffer, length);
51 0 : if (payload.IsNull())
52 : {
53 0 : ChipLogError(AppServer, "Unable to allocate packet buffer\n");
54 0 : return CHIP_ERROR_NO_MEMORY;
55 : }
56 0 : ReturnErrorOnFailure(EncodeUDCMessage(payload));
57 :
58 0 : id.DebugLog();
59 0 : ChipLogProgress(Inet, "Sending UDC msg");
60 :
61 : // send UDC message 5 times per spec (no ACK on this message)
62 0 : for (unsigned int i = 0; i < 5; i++)
63 : {
64 0 : auto msgCopy = payload.CloneData();
65 0 : VerifyOrReturnError(!msgCopy.IsNull(), CHIP_ERROR_NO_MEMORY);
66 :
67 0 : auto err = transportMgr->SendMessage(peerAddress, std::move(msgCopy));
68 0 : if (err != CHIP_NO_ERROR)
69 : {
70 0 : ChipLogError(AppServer, "UDC SendMessage failed: %" CHIP_ERROR_FORMAT, err.Format());
71 0 : return err;
72 : }
73 : // Zephyr doesn't provide usleep implementation.
74 : #ifdef __ZEPHYR__
75 : k_usleep(100 * 1000); // 100ms
76 : #else
77 0 : usleep(100 * 1000); // 100ms
78 : #endif // __ZEPHYR__
79 0 : }
80 :
81 0 : ChipLogProgress(Inet, "UDC msg sent");
82 0 : return CHIP_NO_ERROR;
83 0 : }
84 :
85 1 : CHIP_ERROR UserDirectedCommissioningClient::EncodeUDCMessage(const System::PacketBufferHandle & payload)
86 : {
87 1 : PayloadHeader payloadHeader;
88 1 : PacketHeader packetHeader;
89 :
90 1 : payloadHeader.SetMessageType(MsgType::IdentificationDeclaration).SetInitiator(true).SetNeedsAck(false);
91 :
92 1 : VerifyOrReturnError(!payload.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
93 1 : VerifyOrReturnError(!payload->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
94 1 : VerifyOrReturnError(payload->TotalLength() <= kMaxAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);
95 :
96 1 : ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(payload));
97 :
98 1 : ReturnErrorOnFailure(packetHeader.EncodeBeforeData(payload));
99 :
100 1 : return CHIP_NO_ERROR;
101 1 : }
102 :
103 : /**
104 : * Reset the connection state to a completely uninitialized status.
105 : */
106 1 : uint32_t IdentificationDeclaration::WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize)
107 : {
108 : CHIP_ERROR err;
109 :
110 1 : chip::TLV::TLVWriter writer;
111 1 : chip::TLV::TLVType listContainerType = chip::TLV::kTLVType_List;
112 :
113 1 : memcpy(payloadBuffer, mInstanceName, sizeof(mInstanceName));
114 :
115 1 : writer.Init(payloadBuffer + sizeof(mInstanceName), payloadBufferSize - sizeof(mInstanceName));
116 :
117 1 : chip::TLV::TLVType outerContainerType = chip::TLV::kTLVType_Structure;
118 1 : VerifyOrExit(CHIP_NO_ERROR ==
119 : (err = writer.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::kTLVType_Structure, outerContainerType)),
120 : LogErrorOnFailure(err));
121 :
122 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kVendorIdTag), GetVendorId())), LogErrorOnFailure(err));
123 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kProductIdTag), GetProductId())), LogErrorOnFailure(err));
124 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutString(chip::TLV::ContextTag(kDeviceNameTag), mDeviceName)),
125 : LogErrorOnFailure(err));
126 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutString(chip::TLV::ContextTag(kPairingInstTag), mPairingInst)),
127 : LogErrorOnFailure(err));
128 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kPairingHintTag), mPairingHint)), LogErrorOnFailure(err));
129 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kCdPortTag), GetCdPort())), LogErrorOnFailure(err));
130 :
131 1 : VerifyOrExit(
132 : CHIP_NO_ERROR ==
133 : (err = writer.PutBytes(chip::TLV::ContextTag(kRotatingIdTag), mRotatingId, static_cast<uint8_t>(mRotatingIdLen))),
134 : LogErrorOnFailure(err));
135 :
136 1 : if (mNumTargetAppInfos > 0)
137 : {
138 : // AppVendorIdList
139 1 : VerifyOrExit(CHIP_NO_ERROR ==
140 : (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppListTag), chip::TLV::kTLVType_List,
141 : listContainerType)),
142 : LogErrorOnFailure(err));
143 4 : for (size_t i = 0; i < mNumTargetAppInfos; i++)
144 : {
145 : // start the TargetApp structure
146 3 : VerifyOrExit(CHIP_NO_ERROR ==
147 : (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppTag), chip::TLV::kTLVType_Structure,
148 : outerContainerType)),
149 : LogErrorOnFailure(err));
150 : // add the vendor Id
151 3 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppVendorIdTag), mTargetAppInfos[i].vendorId)),
152 : LogErrorOnFailure(err));
153 3 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppProductIdTag), mTargetAppInfos[i].productId)),
154 : LogErrorOnFailure(err));
155 : // end the TargetApp structure
156 3 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
157 : }
158 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(listContainerType)), LogErrorOnFailure(err));
159 : }
160 :
161 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kNoPasscodeTag), mNoPasscode)),
162 : LogErrorOnFailure(err));
163 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCdUponPasscodeDialogTag), mCdUponPasscodeDialog)),
164 : LogErrorOnFailure(err));
165 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCommissionerPasscodeTag), mCommissionerPasscode)),
166 : LogErrorOnFailure(err));
167 1 : VerifyOrExit(CHIP_NO_ERROR ==
168 : (err = writer.PutBoolean(chip::TLV::ContextTag(kCommissionerPasscodeReadyTag), mCommissionerPasscodeReady)),
169 : LogErrorOnFailure(err));
170 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCancelPasscodeTag), mCancelPasscode)),
171 : LogErrorOnFailure(err));
172 :
173 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
174 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Finalize()), LogErrorOnFailure(err));
175 :
176 1 : return writer.GetLengthWritten() + static_cast<uint32_t>(sizeof(mInstanceName));
177 :
178 0 : exit:
179 0 : ChipLogError(AppServer, "IdentificationDeclaration::WritePayload exiting early error %" CHIP_ERROR_FORMAT, err.Format());
180 0 : return 0;
181 : }
182 :
183 1 : CHIP_ERROR CommissionerDeclaration::ReadPayload(uint8_t * udcPayload, size_t payloadBufferSize)
184 : {
185 : CHIP_ERROR err;
186 :
187 1 : TLV::TLVReader reader;
188 1 : reader.Init(udcPayload, payloadBufferSize);
189 :
190 : // read the envelope
191 1 : ReturnErrorOnFailure(reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()));
192 :
193 1 : chip::TLV::TLVType outerContainerType = chip::TLV::kTLVType_Structure;
194 1 : ReturnErrorOnFailure(reader.EnterContainer(outerContainerType));
195 :
196 8 : while ((err = reader.Next()) == CHIP_NO_ERROR)
197 : {
198 7 : chip::TLV::Tag containerTag = reader.GetTag();
199 7 : if (!TLV::IsContextTag(containerTag))
200 : {
201 0 : ChipLogError(AppServer, "Unexpected non-context TLV tag.");
202 0 : return CHIP_ERROR_INVALID_TLV_TAG;
203 : }
204 7 : uint8_t tagNum = static_cast<uint8_t>(chip::TLV::TagNumFromTag(containerTag));
205 :
206 7 : switch (tagNum)
207 : {
208 1 : case kErrorCodeTag:
209 1 : err = reader.Get(mErrorCode);
210 1 : break;
211 1 : case kNeedsPasscodeTag:
212 1 : err = reader.Get(mNeedsPasscode);
213 1 : break;
214 1 : case kNoAppsFoundTag:
215 1 : err = reader.Get(mNoAppsFound);
216 1 : break;
217 1 : case kPasscodeDialogDisplayedTag:
218 1 : err = reader.Get(mPasscodeDialogDisplayed);
219 1 : break;
220 1 : case kCommissionerPasscodeTag:
221 1 : err = reader.Get(mCommissionerPasscode);
222 1 : break;
223 1 : case kQRCodeDisplayedTag:
224 1 : err = reader.Get(mQRCodeDisplayed);
225 1 : break;
226 1 : case kCancelPasscodeTag:
227 1 : err = reader.Get(mCancelPasscode);
228 1 : break;
229 : }
230 : }
231 :
232 1 : if (err == CHIP_END_OF_TLV)
233 : {
234 : // Exiting container
235 1 : ReturnErrorOnFailure(reader.ExitContainer(outerContainerType));
236 : }
237 :
238 1 : ChipLogProgress(AppServer, "UDC TLV parse complete");
239 1 : return CHIP_NO_ERROR;
240 : }
241 :
242 0 : void UserDirectedCommissioningClient::OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msg,
243 : Transport::MessageTransportContext * ctxt)
244 : {
245 : char addrBuffer[chip::Transport::PeerAddress::kMaxToStringSize];
246 0 : source.ToString(addrBuffer);
247 :
248 0 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() from %s", addrBuffer);
249 :
250 0 : PacketHeader packetHeader;
251 :
252 0 : ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
253 :
254 0 : if (packetHeader.IsEncrypted())
255 : {
256 0 : ChipLogError(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() UDC encryption flag set - ignoring");
257 0 : return;
258 : }
259 :
260 0 : PayloadHeader payloadHeader;
261 0 : ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
262 :
263 0 : ChipLogProgress(AppServer,
264 : "UserDirectedCommissioningClient::OnMessageReceived() CommissionerDeclaration DataLength() = %" PRIu32,
265 : static_cast<uint32_t>(msg->DataLength()));
266 :
267 : uint8_t udcPayload[IdentificationDeclaration::kUdcTLVDataMaxBytes];
268 0 : size_t udcPayloadLength = std::min<size_t>(msg->DataLength(), sizeof(udcPayload));
269 0 : msg->Read(udcPayload, udcPayloadLength);
270 :
271 0 : CommissionerDeclaration cd;
272 0 : cd.ReadPayload(udcPayload, sizeof(udcPayload));
273 0 : cd.DebugLog();
274 :
275 : // Call the registered mCommissionerDeclarationHandler, if any.
276 0 : if (mCommissionerDeclarationHandler != nullptr)
277 : {
278 0 : mCommissionerDeclarationHandler->OnCommissionerDeclarationMessage(source, cd);
279 : }
280 : else
281 : {
282 0 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() No registered handler for UDC messages");
283 : }
284 0 : }
285 :
286 : } // namespace UserDirectedCommissioning
287 : } // namespace Protocols
288 : } // namespace chip
|