3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <app/server/Server.h>
20 #include <app/InteractionModelEngine.h>
21 #include <app/server/DataModelHandler.h>
22 #include <app/server/EchoHandler.h>
23 #include <app/server/RendezvousServer.h>
24 #include <app/server/SessionManager.h>
26 #include <ble/BLEEndPoint.h>
27 #include <core/CHIPPersistentStorageDelegate.h>
28 #include <inet/IPAddress.h>
29 #include <inet/InetError.h>
30 #include <inet/InetLayer.h>
31 #include <messaging/ExchangeMgr.h>
32 #include <platform/CHIPDeviceLayer.h>
33 #include <platform/KeyValueStoreManager.h>
34 #include <setup_payload/SetupPayload.h>
35 #include <support/CodeUtils.h>
36 #include <support/ErrorStr.h>
37 #include <support/ReturnMacros.h>
38 #include <support/logging/CHIPLogging.h>
39 #include <sys/param.h>
40 #include <system/SystemPacketBuffer.h>
41 #include <system/TLVPacketBufferBackingStore.h>
42 #include <transport/SecureSessionMgr.h>
43 #include <transport/StorablePeerConnection.h>
47 using namespace ::chip;
48 using namespace ::chip::Inet;
49 using namespace ::chip::Transport;
50 using namespace ::chip::DeviceLayer;
51 using namespace ::chip::Messaging;
55 constexpr bool isRendezvousBypassed()
57 #if defined(CHIP_BYPASS_RENDEZVOUS) && CHIP_BYPASS_RENDEZVOUS
59 #elif defined(CONFIG_RENDEZVOUS_MODE)
60 return static_cast<RendezvousInformationFlags>(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kNone;
66 constexpr bool useTestPairing()
68 // Use the test pairing whenever rendezvous is bypassed. Otherwise, there wouldn't be
69 // any way to communicate with the device using CHIP protocol.
70 return isRendezvousBypassed();
73 class ServerStorageDelegate : public PersistentStorageDelegate
75 void SetDelegate(PersistentStorageResultDelegate * delegate) override
77 ChipLogError(AppServer, "ServerStorageDelegate does not support async operations");
81 void GetKeyValue(const char * key) override
83 ChipLogError(AppServer, "ServerStorageDelegate does not support async operations");
87 void SetKeyValue(const char * key, const char * value) override
89 ChipLogError(AppServer, "ServerStorageDelegate does not support async operations");
93 CHIP_ERROR GetKeyValue(const char * key, void * buffer, uint16_t & size) override
95 return PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size);
98 CHIP_ERROR SetKeyValue(const char * key, const void * value, uint16_t size) override
100 return PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
103 void DeleteKeyValue(const char * key) override { PersistedStorage::KeyValueStoreMgr().Delete(key); }
106 ServerStorageDelegate gServerStorage;
108 CHIP_ERROR PersistAdminPairingToKVS(AdminPairingInfo * admin, AdminId nextAvailableId)
110 ReturnErrorCodeIf(admin == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
111 ChipLogProgress(AppServer, "Persisting admin ID %d, next available %d", admin->GetAdminId(), nextAvailableId);
113 ReturnErrorOnFailure(admin->StoreIntoKVS(gServerStorage));
114 ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kAdminTableCountKey, &nextAvailableId, sizeof(nextAvailableId)));
116 ChipLogProgress(AppServer, "Persisting admin ID successfully");
117 return CHIP_NO_ERROR;
120 CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, AdminId & nextAvailableId)
122 // It's not an error if the key doesn't exist. Just return right away.
123 VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kAdminTableCountKey, &nextAvailableId) == CHIP_NO_ERROR,
125 ChipLogProgress(AppServer, "Next available admin ID is %d", nextAvailableId);
127 // TODO: The admin ID space allocation should be re-evaluated. With the current approach, the space could be
128 // exhausted while IDs are still available (e.g. if the admin IDs are allocated and freed over a period of time).
129 // Also, the current approach can make ID lookup slower as more IDs are allocated and freed.
130 for (AdminId id = 0; id < nextAvailableId; id++)
132 AdminPairingInfo * admin = adminPairings.AssignAdminId(id);
133 // Recreate the binding if one exists in persistent storage. Else skip to the next ID
134 if (admin->FetchFromKVS(gServerStorage) != CHIP_NO_ERROR)
136 adminPairings.ReleaseAdminId(id);
140 ChipLogProgress(AppServer, "Found admin pairing for %d, node ID %llu", admin->GetAdminId(), admin->GetNodeId());
144 return CHIP_NO_ERROR;
147 void EraseAllAdminPairingsUpTo(AdminId nextAvailableId)
149 PersistedStorage::KeyValueStoreMgr().Delete(kAdminTableCountKey);
151 for (AdminId id = 0; id < nextAvailableId; id++)
153 AdminPairingInfo::DeleteFromKVS(gServerStorage, id);
157 static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousServer & server)
159 uint16_t nextSessionKeyId = 0;
160 // It's not an error if the key doesn't exist. Just return right away.
161 VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kStorablePeerConnectionCountKey, &nextSessionKeyId) ==
164 ChipLogProgress(AppServer, "Found %d stored connections", nextSessionKeyId);
166 PASESession * session = chip::Platform::New<PASESession>();
167 VerifyOrReturnError(session != nullptr, CHIP_ERROR_NO_MEMORY);
169 for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++)
171 StorablePeerConnection connection;
172 if (CHIP_NO_ERROR == connection.FetchFromKVS(gServerStorage, keyId))
174 connection.GetPASESession(session);
176 ChipLogProgress(AppServer, "Fetched the session information: from %llu", session->PeerConnection().GetPeerNodeId());
177 sessionMgr.NewPairing(Optional<Transport::PeerAddress>::Value(session->PeerConnection().GetPeerAddress()),
178 session->PeerConnection().GetPeerNodeId(), session,
179 SecureSessionMgr::PairingDirection::kResponder, connection.GetAdminId(), nullptr);
184 chip::Platform::Delete(session);
186 server.GetRendezvousSession()->SetNextKeyId(nextSessionKeyId);
187 return CHIP_NO_ERROR;
190 void EraseAllSessionsUpTo(uint16_t nextSessionKeyId)
192 PersistedStorage::KeyValueStoreMgr().Delete(kStorablePeerConnectionCountKey);
194 for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++)
196 StorablePeerConnection::DeleteFromKVS(gServerStorage, keyId);
200 // TODO: The following class is setting the discriminator in Persistent Storage. This is
201 // is needed since BLE reads the discriminator using ConfigurationMgr APIs. The
202 // better solution will be to pass the discriminator to BLE without changing it
203 // in the persistent storage.
204 // https://github.com/project-chip/connectedhomeip/issues/4767
205 class DeviceDiscriminatorCache
208 CHIP_ERROR UpdateDiscriminator(uint16_t discriminator)
210 if (!mOriginalDiscriminatorCached)
212 // Cache the original discriminator
213 ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(mOriginalDiscriminator));
214 mOriginalDiscriminatorCached = true;
217 return DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(discriminator);
220 CHIP_ERROR RestoreDiscriminator()
222 if (mOriginalDiscriminatorCached)
224 // Restore the original discriminator
225 ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(mOriginalDiscriminator));
226 mOriginalDiscriminatorCached = false;
229 return CHIP_NO_ERROR;
233 bool mOriginalDiscriminatorCached = false;
234 uint16_t mOriginalDiscriminator = 0;
237 DeviceDiscriminatorCache gDeviceDiscriminatorCache;
238 AdminPairingTable gAdminPairings;
239 AdminId gNextAvailableAdminId = 0;
241 class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDelegate
244 CHIP_ERROR StartAdvertisement() const override
246 ReturnErrorOnFailure(chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true));
247 if (mDelegate != nullptr)
249 mDelegate->OnPairingWindowOpened();
251 return CHIP_NO_ERROR;
253 CHIP_ERROR StopAdvertisement() const override
255 gDeviceDiscriminatorCache.RestoreDiscriminator();
257 ReturnErrorOnFailure(chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false));
259 if (mDelegate != nullptr)
260 mDelegate->OnPairingWindowClosed();
263 AdminPairingInfo * admin = gAdminPairings.FindAdmin(mAdmin);
264 if (admin != nullptr)
266 ReturnErrorOnFailure(PersistAdminPairingToKVS(admin, gNextAvailableAdminId));
269 return CHIP_NO_ERROR;
272 void RendezvousComplete() const override
274 // Once rendezvous completed, assume we are operational
275 if (app::Mdns::AdvertiseOperational() != CHIP_NO_ERROR)
277 ChipLogError(Discovery, "Failed to start advertising operational state at rendezvous completion time.");
281 void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }
283 void SetAdminId(AdminId id) { mAdmin = id; }
286 AppDelegate * mDelegate = nullptr;
290 DemoTransportMgr gTransports;
291 SecureSessionMgr gSessions;
292 RendezvousServer gRendezvousServer;
294 ServerRendezvousAdvertisementDelegate gAdvDelegate;
296 static CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t discriminator, PASEVerifier & verifier)
298 RendezvousParameters params;
300 ReturnErrorOnFailure(gDeviceDiscriminatorCache.UpdateDiscriminator(discriminator));
302 #if CONFIG_NETWORK_LAYER_BLE
303 params.SetPASEVerifier(verifier)
304 .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer())
305 .SetPeerAddress(Transport::PeerAddress::BLE())
306 .SetAdvertisementDelegate(&gAdvDelegate);
308 params.SetPASEVerifier(verifier);
309 #endif // CONFIG_NETWORK_LAYER_BLE
311 AdminId admin = gNextAvailableAdminId;
312 AdminPairingInfo * adminInfo = gAdminPairings.AssignAdminId(admin);
313 VerifyOrReturnError(adminInfo != nullptr, CHIP_ERROR_NO_MEMORY);
314 gNextAvailableAdminId++;
316 return gRendezvousServer.WaitForPairing(std::move(params), &gTransports, &gSessions, adminInfo);
319 class ServerCallback : public SecureSessionMgrDelegate
322 void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, SecureSessionHandle session,
323 System::PacketBufferHandle buffer, SecureSessionMgr * mgr) override
325 auto state = mgr->GetPeerConnectionState(session);
326 const size_t data_len = buffer->DataLength();
327 char src_addr[PeerAddress::kMaxToStringSize];
329 // as soon as a client connects, assume it is connected
330 VerifyOrExit(!buffer.IsNull(), ChipLogProgress(AppServer, "Received data but couldn't process it..."));
331 VerifyOrExit(header.GetSourceNodeId().HasValue(), ChipLogProgress(AppServer, "Unknown source for received message"));
333 VerifyOrExit(state->GetPeerNodeId() != kUndefinedNodeId, ChipLogProgress(AppServer, "Unknown source for received message"));
335 state->GetPeerAddress().ToString(src_addr);
337 ChipLogProgress(AppServer, "Packet received from %s: %zu bytes", src_addr, static_cast<size_t>(data_len));
339 // TODO: This code is temporary, and must be updated to use the Cluster API.
340 // Issue: https://github.com/project-chip/connectedhomeip/issues/4725
341 if (payloadHeader.GetProtocolID() == chip::Protocols::kProtocol_ServiceProvisioning)
343 CHIP_ERROR err = CHIP_NO_ERROR;
345 uint16_t discriminator;
346 PASEVerifier verifier;
348 ChipLogProgress(AppServer, "Received service provisioning message. Treating it as OpenPairingWindow request");
349 chip::System::PacketBufferTLVReader reader;
350 reader.Init(std::move(buffer));
351 reader.ImplicitProfileId = chip::Protocols::kProtocol_ServiceProvisioning;
353 SuccessOrExit(reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 1)));
354 SuccessOrExit(reader.Get(timeout));
356 err = reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 2));
357 if (err == CHIP_NO_ERROR)
359 SuccessOrExit(reader.Get(discriminator));
361 err = reader.Next(kTLVType_ByteString, TLV::ProfileTag(reader.ImplicitProfileId, 3));
362 if (err == CHIP_NO_ERROR)
364 SuccessOrExit(reader.GetBytes(reinterpret_cast<uint8_t *>(verifier), sizeof(verifier)));
368 ChipLogProgress(AppServer, "Pairing Window timeout %d seconds", timeout);
370 if (err != CHIP_NO_ERROR)
372 SuccessOrExit(err = OpenDefaultPairingWindow(ResetAdmins::kNo));
376 ChipLogProgress(AppServer, "Pairing Window discriminator %d", discriminator);
377 err = OpenPairingWindowUsingVerifier(discriminator, verifier);
380 ChipLogProgress(AppServer, "Opened the pairing window");
384 HandleDataModelMessage(header.GetSourceNodeId().Value(), std::move(buffer));
390 void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override
392 ChipLogProgress(AppServer, "Packet received error: %s", ErrorStr(error));
393 if (mDelegate != nullptr)
395 mDelegate->OnReceiveError();
399 void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override
401 ChipLogProgress(AppServer, "Received a new connection.");
404 void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }
407 AppDelegate * mDelegate = nullptr;
410 #if defined(CHIP_APP_USE_INTERACTION_MODEL) || defined(CHIP_APP_USE_ECHO)
411 Messaging::ExchangeManager gExchangeMgr;
413 ServerCallback gCallbacks;
414 SecurePairingUsingTestSecret gTestPairing;
418 SecureSessionMgr & chip::SessionManager()
423 CHIP_ERROR OpenDefaultPairingWindow(ResetAdmins resetAdmins)
425 gDeviceDiscriminatorCache.RestoreDiscriminator();
428 ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSetupPinCode(pinCode));
430 RendezvousParameters params;
432 #if CONFIG_NETWORK_LAYER_BLE
433 params.SetSetupPINCode(pinCode)
434 .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer())
435 .SetPeerAddress(Transport::PeerAddress::BLE())
436 .SetAdvertisementDelegate(&gAdvDelegate);
438 params.SetSetupPINCode(pinCode);
439 #endif // CONFIG_NETWORK_LAYER_BLE
441 if (resetAdmins == ResetAdmins::kYes)
443 uint16_t nextKeyId = gRendezvousServer.GetRendezvousSession()->GetNextKeyId();
444 EraseAllAdminPairingsUpTo(gNextAvailableAdminId);
445 EraseAllSessionsUpTo(nextKeyId);
446 gNextAvailableAdminId = 0;
447 gAdminPairings.Reset();
450 AdminId admin = gNextAvailableAdminId;
451 AdminPairingInfo * adminInfo = gAdminPairings.AssignAdminId(admin);
452 VerifyOrReturnError(adminInfo != nullptr, CHIP_ERROR_NO_MEMORY);
453 gNextAvailableAdminId++;
455 return gRendezvousServer.WaitForPairing(std::move(params), &gTransports, &gSessions, adminInfo);
458 // The function will initialize datamodel handler and then start the server
459 // The server assumes the platform's networking has been setup already
460 void InitServer(AppDelegate * delegate)
462 CHIP_ERROR err = CHIP_NO_ERROR;
464 chip::Platform::MemoryInit();
466 InitDataModelHandler();
467 gCallbacks.SetDelegate(delegate);
469 err = gRendezvousServer.Init(delegate, &gServerStorage);
472 gAdvDelegate.SetDelegate(delegate);
474 // Init transport before operations with secure session mgr.
475 #if INET_CONFIG_ENABLE_IPV4
476 err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6),
477 UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4));
479 err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6));
483 err = gSessions.Init(chip::kTestDeviceNodeId, &DeviceLayer::SystemLayer, &gTransports, &gAdminPairings);
486 #if defined(CHIP_APP_USE_INTERACTION_MODEL) || defined(CHIP_APP_USE_ECHO)
487 err = gExchangeMgr.Init(&gSessions);
490 gSessions.SetDelegate(&gCallbacks);
493 #if defined(CHIP_APP_USE_INTERACTION_MODEL)
494 err = chip::app::InteractionModelEngine::GetInstance()->Init(&gExchangeMgr);
498 #if defined(CHIP_APP_USE_ECHO)
499 err = InitEchoHandler(&gExchangeMgr);
503 if (useTestPairing())
505 SuccessOrExit(err = AddTestPairing());
508 // This flag is used to bypass BLE in the cirque test
509 // Only in the cirque test this is enabled with --args='bypass_rendezvous=true'
510 if (isRendezvousBypassed())
512 ChipLogProgress(AppServer, "Rendezvous and secure pairing skipped");
514 else if (DeviceLayer::ConnectivityMgr().IsWiFiStationProvisioned() || DeviceLayer::ConnectivityMgr().IsThreadProvisioned())
516 // If the network is already provisioned, proactively disable BLE advertisement.
517 ChipLogProgress(AppServer, "Network already provisioned. Disabling BLE advertisement");
518 chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false);
520 // Restore any previous admin pairings
521 VerifyOrExit(CHIP_NO_ERROR == RestoreAllAdminPairingsFromKVS(gAdminPairings, gNextAvailableAdminId),
522 ChipLogError(AppServer, "Could not restore admin table"));
524 VerifyOrExit(CHIP_NO_ERROR == RestoreAllSessionsFromKVS(gSessions, gRendezvousServer),
525 ChipLogError(AppServer, "Could not restore previous sessions"));
529 #if CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART
530 SuccessOrExit(err = OpenDefaultPairingWindow(ResetAdmins::kYes));
534 // Starting mDNS server only for Thread devices due to problem reported in issue #5076.
535 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
536 app::Mdns::StartServer();
540 if (err != CHIP_NO_ERROR)
542 ChipLogError(AppServer, "ERROR setting up transport: %s", ErrorStr(err));
546 ChipLogProgress(AppServer, "Server Listening...");
550 CHIP_ERROR AddTestPairing()
552 CHIP_ERROR err = CHIP_NO_ERROR;
553 AdminPairingInfo * adminInfo = nullptr;
555 for (const AdminPairingInfo & admin : gAdminPairings)
556 if (admin.IsInitialized() && admin.GetNodeId() == chip::kTestDeviceNodeId)
559 adminInfo = gAdminPairings.AssignAdminId(gNextAvailableAdminId);
560 VerifyOrExit(adminInfo != nullptr, err = CHIP_ERROR_NO_MEMORY);
562 adminInfo->SetNodeId(chip::kTestDeviceNodeId);
563 SuccessOrExit(err = gSessions.NewPairing(Optional<PeerAddress>{ PeerAddress::Uninitialized() }, chip::kTestControllerNodeId,
564 &gTestPairing, SecureSessionMgr::PairingDirection::kResponder, gNextAvailableAdminId));
565 ++gNextAvailableAdminId;
568 if (err != CHIP_NO_ERROR && adminInfo != nullptr)
569 gAdminPairings.ReleaseAdminId(gNextAvailableAdminId);
574 AdminPairingTable & GetGlobalAdminPairingTable()
576 return gAdminPairings;