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 : }
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 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kPasscodeLengthTag), GetPasscodeLength())),
173 : LogErrorOnFailure(err));
174 :
175 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
176 1 : VerifyOrExit(CHIP_NO_ERROR == (err = writer.Finalize()), LogErrorOnFailure(err));
177 :
178 1 : return writer.GetLengthWritten() + static_cast<uint32_t>(sizeof(mInstanceName));
179 :
180 0 : exit:
181 0 : ChipLogError(AppServer, "IdentificationDeclaration::WritePayload exiting early error %" CHIP_ERROR_FORMAT, err.Format());
182 0 : return 0;
183 : }
184 :
185 1 : CHIP_ERROR CommissionerDeclaration::ReadPayload(uint8_t * udcPayload, size_t payloadBufferSize)
186 : {
187 : CHIP_ERROR err;
188 :
189 1 : TLV::TLVReader reader;
190 1 : reader.Init(udcPayload, payloadBufferSize);
191 :
192 : // read the envelope
193 1 : ReturnErrorOnFailure(reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()));
194 :
195 1 : chip::TLV::TLVType outerContainerType = chip::TLV::kTLVType_Structure;
196 1 : ReturnErrorOnFailure(reader.EnterContainer(outerContainerType));
197 :
198 9 : while ((err = reader.Next()) == CHIP_NO_ERROR)
199 : {
200 8 : chip::TLV::Tag containerTag = reader.GetTag();
201 8 : if (!TLV::IsContextTag(containerTag))
202 : {
203 0 : ChipLogError(AppServer, "Unexpected non-context TLV tag.");
204 0 : return CHIP_ERROR_INVALID_TLV_TAG;
205 : }
206 8 : uint8_t tagNum = static_cast<uint8_t>(chip::TLV::TagNumFromTag(containerTag));
207 :
208 8 : switch (tagNum)
209 : {
210 1 : case kErrorCodeTag:
211 1 : err = reader.Get(mErrorCode);
212 1 : break;
213 1 : case kNeedsPasscodeTag:
214 1 : err = reader.Get(mNeedsPasscode);
215 1 : break;
216 1 : case kNoAppsFoundTag:
217 1 : err = reader.Get(mNoAppsFound);
218 1 : break;
219 1 : case kPasscodeDialogDisplayedTag:
220 1 : err = reader.Get(mPasscodeDialogDisplayed);
221 1 : break;
222 1 : case kCommissionerPasscodeTag:
223 1 : err = reader.Get(mCommissionerPasscode);
224 1 : break;
225 1 : case kQRCodeDisplayedTag:
226 1 : err = reader.Get(mQRCodeDisplayed);
227 1 : break;
228 1 : case kCancelPasscodeTag:
229 1 : err = reader.Get(mCancelPasscode);
230 1 : break;
231 1 : case kPasscodeLengthTag:
232 1 : err = reader.Get(mPasscodeLength);
233 1 : break;
234 : }
235 : }
236 :
237 1 : if (err == CHIP_END_OF_TLV)
238 : {
239 : // Exiting container
240 1 : ReturnErrorOnFailure(reader.ExitContainer(outerContainerType));
241 : }
242 :
243 1 : ChipLogProgress(AppServer, "UDC TLV parse complete");
244 1 : return CHIP_NO_ERROR;
245 : }
246 :
247 0 : void UserDirectedCommissioningClient::OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msg,
248 : Transport::MessageTransportContext * ctxt)
249 : {
250 : char addrBuffer[chip::Transport::PeerAddress::kMaxToStringSize];
251 0 : source.ToString(addrBuffer);
252 :
253 0 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() from %s", addrBuffer);
254 :
255 0 : PacketHeader packetHeader;
256 :
257 0 : ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
258 :
259 0 : if (packetHeader.IsEncrypted())
260 : {
261 0 : ChipLogError(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() UDC encryption flag set - ignoring");
262 0 : return;
263 : }
264 :
265 0 : PayloadHeader payloadHeader;
266 0 : ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
267 :
268 0 : ChipLogProgress(AppServer,
269 : "UserDirectedCommissioningClient::OnMessageReceived() CommissionerDeclaration DataLength() = %" PRIu32,
270 : static_cast<uint32_t>(msg->DataLength()));
271 :
272 : uint8_t udcPayload[IdentificationDeclaration::kUdcTLVDataMaxBytes];
273 0 : size_t udcPayloadLength = std::min<size_t>(msg->DataLength(), sizeof(udcPayload));
274 0 : msg->Read(udcPayload, udcPayloadLength);
275 :
276 0 : CommissionerDeclaration cd;
277 0 : cd.ReadPayload(udcPayload, sizeof(udcPayload));
278 0 : cd.DebugLog();
279 :
280 : // Call the registered mCommissionerDeclarationHandler, if any.
281 0 : if (mCommissionerDeclarationHandler != nullptr)
282 : {
283 0 : mCommissionerDeclarationHandler->OnCommissionerDeclarationMessage(source, cd);
284 : }
285 : else
286 : {
287 0 : ChipLogProgress(AppServer, "UserDirectedCommissioningClient::OnMessageReceived() No registered handler for UDC messages");
288 : }
289 : }
290 :
291 : } // namespace UserDirectedCommissioning
292 : } // namespace Protocols
293 : } // namespace chip
|