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.
20 #include <app/server/Server.h>
22 #include <app/InteractionModelEngine.h>
23 #include <app/server/DataModelHandler.h>
24 #include <app/server/EchoHandler.h>
25 #include <app/server/RendezvousServer.h>
26 #include <app/server/SessionManager.h>
28 #include <ble/BLEEndPoint.h>
29 #include <core/CHIPPersistentStorageDelegate.h>
30 #include <inet/IPAddress.h>
31 #include <inet/InetError.h>
32 #include <inet/InetLayer.h>
33 #include <messaging/ExchangeMgr.h>
34 #include <platform/CHIPDeviceLayer.h>
35 #include <platform/KeyValueStoreManager.h>
36 #include <setup_payload/SetupPayload.h>
37 #include <support/CodeUtils.h>
38 #include <support/ErrorStr.h>
39 #include <support/logging/CHIPLogging.h>
40 #include <sys/param.h>
41 #include <system/SystemPacketBuffer.h>
42 #include <system/TLVPacketBufferBackingStore.h>
43 #include <transport/SecureSessionMgr.h>
44 #include <transport/StorablePeerConnection.h>
48 using namespace ::chip;
49 using namespace ::chip::Inet;
50 using namespace ::chip::Transport;
51 using namespace ::chip::DeviceLayer;
52 using namespace ::chip::Messaging;
56 constexpr bool isRendezvousBypassed()
58 #if defined(CHIP_BYPASS_RENDEZVOUS) && CHIP_BYPASS_RENDEZVOUS
60 #elif defined(CONFIG_RENDEZVOUS_MODE)
61 return static_cast<RendezvousInformationFlags>(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kNone;
67 constexpr bool useTestPairing()
69 // Use the test pairing whenever rendezvous is bypassed. Otherwise, there wouldn't be
70 // any way to communicate with the device using CHIP protocol.
71 // This is used to bypass BLE in the cirque test.
72 // Only in the cirque test this is enabled with --args='bypass_rendezvous=true'.
73 return isRendezvousBypassed();
76 class ServerStorageDelegate : public PersistentStorageDelegate
78 void SetStorageDelegate(PersistentStorageResultDelegate * delegate) override
80 ChipLogError(AppServer, "ServerStorageDelegate does not support async operations");
84 void AsyncSetKeyValue(const char * key, const char * value) override
86 ChipLogError(AppServer, "ServerStorageDelegate does not support async operations");
90 CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
92 return PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size);
95 CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
97 return PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
100 void AsyncDeleteKeyValue(const char * key) override { PersistedStorage::KeyValueStoreMgr().Delete(key); }
103 ServerStorageDelegate gServerStorage;
105 CHIP_ERROR PersistAdminPairingToKVS(AdminPairingInfo * admin, AdminId nextAvailableId)
107 ReturnErrorCodeIf(admin == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
108 ChipLogProgress(AppServer, "Persisting admin ID %d, next available %d", admin->GetAdminId(), nextAvailableId);
110 ReturnErrorOnFailure(admin->StoreIntoKVS(gServerStorage));
111 ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kAdminTableCountKey, &nextAvailableId, sizeof(nextAvailableId)));
113 ChipLogProgress(AppServer, "Persisting admin ID successfully");
114 return CHIP_NO_ERROR;
117 CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, AdminId & nextAvailableId)
119 // It's not an error if the key doesn't exist. Just return right away.
120 VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kAdminTableCountKey, &nextAvailableId) == CHIP_NO_ERROR,
122 ChipLogProgress(AppServer, "Next available admin ID is %d", nextAvailableId);
124 // TODO: The admin ID space allocation should be re-evaluated. With the current approach, the space could be
125 // exhausted while IDs are still available (e.g. if the admin IDs are allocated and freed over a period of time).
126 // Also, the current approach can make ID lookup slower as more IDs are allocated and freed.
127 for (AdminId id = 0; id < nextAvailableId; id++)
129 AdminPairingInfo * admin = adminPairings.AssignAdminId(id);
130 // Recreate the binding if one exists in persistent storage. Else skip to the next ID
131 if (admin->FetchFromKVS(gServerStorage) != CHIP_NO_ERROR)
133 adminPairings.ReleaseAdminId(id);
137 ChipLogProgress(AppServer, "Found admin pairing for %d, node ID 0x%08" PRIx32 "%08" PRIx32, admin->GetAdminId(),
138 static_cast<uint32_t>(admin->GetNodeId() >> 32), static_cast<uint32_t>(admin->GetNodeId()));
142 return CHIP_NO_ERROR;
145 void EraseAllAdminPairingsUpTo(AdminId nextAvailableId)
147 PersistedStorage::KeyValueStoreMgr().Delete(kAdminTableCountKey);
149 for (AdminId id = 0; id < nextAvailableId; id++)
151 AdminPairingInfo::DeleteFromKVS(gServerStorage, id);
155 static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousServer & server)
157 uint16_t nextSessionKeyId = 0;
158 // It's not an error if the key doesn't exist. Just return right away.
159 VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kStorablePeerConnectionCountKey, &nextSessionKeyId) ==
162 ChipLogProgress(AppServer, "Found %d stored connections", nextSessionKeyId);
164 PASESession * session = chip::Platform::New<PASESession>();
165 VerifyOrReturnError(session != nullptr, CHIP_ERROR_NO_MEMORY);
167 for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++)
169 StorablePeerConnection connection;
170 if (CHIP_NO_ERROR == connection.FetchFromKVS(gServerStorage, keyId))
172 connection.GetPASESession(session);
174 ChipLogProgress(AppServer, "Fetched the session information: from 0x%08" PRIx32 "%08" PRIx32,
175 static_cast<uint32_t>(session->PeerConnection().GetPeerNodeId() >> 32),
176 static_cast<uint32_t>(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 char src_addr[PeerAddress::kMaxToStringSize];
328 // as soon as a client connects, assume it is connected
329 VerifyOrExit(!buffer.IsNull(), ChipLogProgress(AppServer, "Received data but couldn't process it..."));
330 VerifyOrExit(header.GetSourceNodeId().HasValue(), ChipLogProgress(AppServer, "Unknown source for received message"));
332 VerifyOrExit(state->GetPeerNodeId() != kUndefinedNodeId, ChipLogProgress(AppServer, "Unknown source for received message"));
334 state->GetPeerAddress().ToString(src_addr);
336 ChipLogProgress(AppServer, "Packet received from %s: %u bytes", src_addr, buffer->DataLength());
338 // TODO: This code is temporary, and must be updated to use the Cluster API.
339 // Issue: https://github.com/project-chip/connectedhomeip/issues/4725
340 if (payloadHeader.HasProtocol(chip::Protocols::ServiceProvisioning::Id))
342 CHIP_ERROR err = CHIP_NO_ERROR;
344 uint16_t discriminator;
345 PASEVerifier verifier;
347 ChipLogProgress(AppServer, "Received service provisioning message. Treating it as OpenPairingWindow request");
348 chip::System::PacketBufferTLVReader reader;
349 reader.Init(std::move(buffer));
350 reader.ImplicitProfileId = chip::Protocols::ServiceProvisioning::Id.ToTLVProfileId();
352 SuccessOrExit(reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 1)));
353 SuccessOrExit(reader.Get(timeout));
355 err = reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 2));
356 if (err == CHIP_NO_ERROR)
358 SuccessOrExit(reader.Get(discriminator));
360 err = reader.Next(kTLVType_ByteString, TLV::ProfileTag(reader.ImplicitProfileId, 3));
361 if (err == CHIP_NO_ERROR)
363 SuccessOrExit(reader.GetBytes(reinterpret_cast<uint8_t *>(verifier), sizeof(verifier)));
367 ChipLogProgress(AppServer, "Pairing Window timeout %d seconds", timeout);
369 if (err != CHIP_NO_ERROR)
371 SuccessOrExit(err = OpenDefaultPairingWindow(ResetAdmins::kNo));
375 ChipLogProgress(AppServer, "Pairing Window discriminator %d", discriminator);
376 err = OpenPairingWindowUsingVerifier(discriminator, verifier);
379 ChipLogProgress(AppServer, "Opened the pairing window");
383 HandleDataModelMessage(header.GetSourceNodeId().Value(), std::move(buffer));
389 void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override
391 ChipLogProgress(AppServer, "Packet received error: %s", ErrorStr(error));
392 if (mDelegate != nullptr)
394 mDelegate->OnReceiveError();
398 void OnNewConnection(SecureSessionHandle session, SecureSessionMgr * mgr) override
400 ChipLogProgress(AppServer, "Received a new connection.");
403 void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }
406 AppDelegate * mDelegate = nullptr;
409 #if CHIP_ENABLE_INTERACTION_MODEL || defined(CHIP_APP_USE_ECHO)
410 Messaging::ExchangeManager gExchangeMgr;
412 ServerCallback gCallbacks;
413 SecurePairingUsingTestSecret gTestPairing;
417 SecureSessionMgr & chip::SessionManager()
422 CHIP_ERROR OpenDefaultPairingWindow(ResetAdmins resetAdmins)
424 gDeviceDiscriminatorCache.RestoreDiscriminator();
427 ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSetupPinCode(pinCode));
429 RendezvousParameters params;
431 #if CONFIG_NETWORK_LAYER_BLE
432 params.SetSetupPINCode(pinCode)
433 .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer())
434 .SetPeerAddress(Transport::PeerAddress::BLE())
435 .SetAdvertisementDelegate(&gAdvDelegate);
437 params.SetSetupPINCode(pinCode);
438 #endif // CONFIG_NETWORK_LAYER_BLE
440 if (resetAdmins == ResetAdmins::kYes)
442 uint16_t nextKeyId = gRendezvousServer.GetRendezvousSession()->GetNextKeyId();
443 EraseAllAdminPairingsUpTo(gNextAvailableAdminId);
444 EraseAllSessionsUpTo(nextKeyId);
445 gNextAvailableAdminId = 0;
446 gAdminPairings.Reset();
449 AdminId admin = gNextAvailableAdminId;
450 AdminPairingInfo * adminInfo = gAdminPairings.AssignAdminId(admin);
451 VerifyOrReturnError(adminInfo != nullptr, CHIP_ERROR_NO_MEMORY);
452 gNextAvailableAdminId++;
454 return gRendezvousServer.WaitForPairing(std::move(params), &gTransports, &gSessions, adminInfo);
457 // The function will initialize datamodel handler and then start the server
458 // The server assumes the platform's networking has been setup already
459 void InitServer(AppDelegate * delegate)
461 CHIP_ERROR err = CHIP_NO_ERROR;
463 chip::Platform::MemoryInit();
465 InitDataModelHandler();
466 gCallbacks.SetDelegate(delegate);
468 err = gRendezvousServer.Init(delegate, &gServerStorage);
471 gAdvDelegate.SetDelegate(delegate);
473 // Init transport before operations with secure session mgr.
474 #if INET_CONFIG_ENABLE_IPV4
475 err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6),
476 UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4));
478 err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6));
482 err = gSessions.Init(chip::kTestDeviceNodeId, &DeviceLayer::SystemLayer, &gTransports, &gAdminPairings);
485 #if CHIP_ENABLE_INTERACTION_MODEL || defined(CHIP_APP_USE_ECHO)
486 err = gExchangeMgr.Init(&gSessions);
489 gSessions.SetDelegate(&gCallbacks);
492 #if CHIP_ENABLE_INTERACTION_MODEL
493 err = chip::app::InteractionModelEngine::GetInstance()->Init(&gExchangeMgr, nullptr);
497 #if defined(CHIP_APP_USE_ECHO)
498 err = InitEchoHandler(&gExchangeMgr);
502 if (useTestPairing())
504 ChipLogProgress(AppServer, "Rendezvous and secure pairing skipped");
505 SuccessOrExit(err = AddTestPairing());
507 else if (DeviceLayer::ConnectivityMgr().IsWiFiStationProvisioned() || DeviceLayer::ConnectivityMgr().IsThreadProvisioned())
509 // If the network is already provisioned, proactively disable BLE advertisement.
510 ChipLogProgress(AppServer, "Network already provisioned. Disabling BLE advertisement");
511 chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false);
513 // Restore any previous admin pairings
514 VerifyOrExit(CHIP_NO_ERROR == RestoreAllAdminPairingsFromKVS(gAdminPairings, gNextAvailableAdminId),
515 ChipLogError(AppServer, "Could not restore admin table"));
517 VerifyOrExit(CHIP_NO_ERROR == RestoreAllSessionsFromKVS(gSessions, gRendezvousServer),
518 ChipLogError(AppServer, "Could not restore previous sessions"));
522 #if CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART
523 SuccessOrExit(err = OpenDefaultPairingWindow(ResetAdmins::kYes));
527 // Starting mDNS server only for Thread devices due to problem reported in issue #5076.
528 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
529 app::Mdns::StartServer();
533 if (err != CHIP_NO_ERROR)
535 ChipLogError(AppServer, "ERROR setting up transport: %s", ErrorStr(err));
539 ChipLogProgress(AppServer, "Server Listening...");
543 CHIP_ERROR AddTestPairing()
545 CHIP_ERROR err = CHIP_NO_ERROR;
546 AdminPairingInfo * adminInfo = nullptr;
548 for (const AdminPairingInfo & admin : gAdminPairings)
549 if (admin.IsInitialized() && admin.GetNodeId() == chip::kTestDeviceNodeId)
552 adminInfo = gAdminPairings.AssignAdminId(gNextAvailableAdminId);
553 VerifyOrExit(adminInfo != nullptr, err = CHIP_ERROR_NO_MEMORY);
555 adminInfo->SetNodeId(chip::kTestDeviceNodeId);
556 SuccessOrExit(err = gSessions.NewPairing(Optional<PeerAddress>{ PeerAddress::Uninitialized() }, chip::kTestControllerNodeId,
557 &gTestPairing, SecureSessionMgr::PairingDirection::kResponder, gNextAvailableAdminId));
558 ++gNextAvailableAdminId;
561 if (err != CHIP_NO_ERROR && adminInfo != nullptr)
562 gAdminPairings.ReleaseAdminId(gNextAvailableAdminId);
567 AdminPairingTable & GetGlobalAdminPairingTable()
569 return gAdminPairings;