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