blob: e05c4ae54b4cb2a82d8a25534760e67c10ffae98 [file]
/*
*
* Copyright (c) 2020 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <access/AccessControl.h>
#include <app/CASEClientPool.h>
#include <app/CASESessionManager.h>
#include <app/DefaultAttributePersistenceProvider.h>
#include <app/OperationalDeviceProxyPool.h>
#include <app/server/AppDelegate.h>
#include <app/server/CommissioningWindowManager.h>
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProviderImpl.h>
#include <inet/InetConfig.h>
#include <lib/core/CHIPConfig.h>
#include <lib/support/SafeInt.h>
#include <messaging/ExchangeMgr.h>
#include <platform/KeyValueStoreManager.h>
#include <protocols/secure_channel/CASEServer.h>
#include <protocols/secure_channel/MessageCounterManager.h>
#include <protocols/secure_channel/PASESession.h>
#include <protocols/secure_channel/RendezvousParameters.h>
#include <protocols/user_directed_commissioning/UserDirectedCommissioning.h>
#include <transport/SessionManager.h>
#include <transport/TransportMgr.h>
#include <transport/TransportMgrBase.h>
#include <transport/raw/BLE.h>
#include <transport/raw/UDP.h>
namespace chip {
constexpr size_t kMaxBlePendingPackets = 1;
using ServerTransportMgr = chip::TransportMgr<chip::Transport::UDP
#if INET_CONFIG_ENABLE_IPV4
,
chip::Transport::UDP
#endif
#if CONFIG_NETWORK_LAYER_BLE
,
chip::Transport::BLE<kMaxBlePendingPackets>
#endif
>;
class Server
{
public:
CHIP_ERROR Init(AppDelegate * delegate = nullptr, uint16_t secureServicePort = CHIP_PORT,
uint16_t unsecureServicePort = CHIP_UDC_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null());
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
CHIP_ERROR SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner);
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
/**
* @brief Call this function to rejoin existing groups found in the GroupDataProvider
*/
void RejoinExistingMulticastGroups();
FabricTable & GetFabricTable() { return mFabrics; }
CASESessionManager * GetCASESessionManager() { return &mCASESessionManager; }
Messaging::ExchangeManager & GetExchangeManager() { return mExchangeMgr; }
SessionIDAllocator & GetSessionIDAllocator() { return mSessionIDAllocator; }
SessionManager & GetSecureSessionManager() { return mSessions; }
TransportMgrBase & GetTransportManager() { return mTransports; }
#if CONFIG_NETWORK_LAYER_BLE
Ble::BleLayer * GetBleLayerObject() { return mBleLayer; }
#endif
CommissioningWindowManager & GetCommissioningWindowManager() { return mCommissioningWindowManager; }
PersistentStorageDelegate & GetPersistentStorage() { return mDeviceStorage; }
/**
* This function send the ShutDown event before stopping
* the event loop.
*/
void DispatchShutDownAndStopEventLoop();
void Shutdown();
void ScheduleFactoryReset();
static Server & GetInstance() { return sServer; }
private:
Server();
static Server sServer;
class DeviceStorageDelegate : public PersistentStorageDelegate
{
CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
{
uint8_t emptyPlaceholder = 0;
if (buffer == nullptr)
{
if (size != 0)
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
// When size is zero, let's give a non-nullptr to the KVS backend
buffer = &emptyPlaceholder;
}
size_t bytesRead = 0;
CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead);
// Update size only if it made sense
if ((CHIP_ERROR_BUFFER_TOO_SMALL == err) || (CHIP_NO_ERROR == err))
{
size = CanCastTo<uint16_t>(bytesRead) ? static_cast<uint16_t>(bytesRead) : 0;
}
if (err == CHIP_NO_ERROR)
{
ChipLogProgress(AppServer, "Retrieved from server storage: %s", key);
}
return err;
}
CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
{
uint8_t placeholderForEmpty = 0;
if (value == nullptr)
{
if (size == 0)
{
value = &placeholderForEmpty;
}
else
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
}
return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
}
CHIP_ERROR SyncDeleteKeyValue(const char * key) override
{
return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key);
}
};
class GroupDataProviderListener final : public Credentials::GroupDataProvider::GroupListener
{
public:
GroupDataProviderListener() {}
CHIP_ERROR Init(ServerTransportMgr * transports)
{
VerifyOrReturnError(transports != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mTransports = transports;
return CHIP_NO_ERROR;
};
void OnGroupAdded(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & new_group) override
{
if (mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, new_group.group_id), true) !=
CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Unable to listen to group");
}
};
void OnGroupRemoved(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & old_group) override
{
mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, old_group.group_id), false);
};
private:
ServerTransportMgr * mTransports;
};
class ServerFabricDelegate final : public FabricTableDelegate
{
public:
ServerFabricDelegate() {}
CHIP_ERROR Init(SessionManager * sessionManager)
{
VerifyOrReturnError(sessionManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mSessionManager = sessionManager;
return CHIP_NO_ERROR;
};
void OnFabricDeletedFromStorage(CompressedFabricId compressedId, FabricIndex fabricIndex) override
{
(void) compressedId;
if (mSessionManager != nullptr)
{
mSessionManager->FabricRemoved(fabricIndex);
}
Credentials::GroupDataProvider * groupDataProvider = Credentials::GetGroupDataProvider();
if (groupDataProvider != nullptr)
{
groupDataProvider->RemoveFabric(fabricIndex);
}
};
void OnFabricRetrievedFromStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }
void OnFabricPersistedToStorage(FabricInfo * fabricInfo) override { (void) fabricInfo; }
private:
SessionManager * mSessionManager = nullptr;
};
#if CONFIG_NETWORK_LAYER_BLE
Ble::BleLayer * mBleLayer = nullptr;
#endif
ServerTransportMgr mTransports;
SessionManager mSessions;
CASEServer mCASEServer;
CASESessionManager mCASESessionManager;
CASEClientPool<CHIP_CONFIG_DEVICE_MAX_ACTIVE_CASE_CLIENTS> mCASEClientPool;
OperationalDeviceProxyPool<CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES> mDevicePool;
Messaging::ExchangeManager mExchangeMgr;
FabricTable mFabrics;
SessionIDAllocator mSessionIDAllocator;
secure_channel::MessageCounterManager mMessageCounterManager;
#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
chip::Protocols::UserDirectedCommissioning::UserDirectedCommissioningClient gUDCClient;
#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT
SecurePairingUsingTestSecret mTestPairing;
CommissioningWindowManager mCommissioningWindowManager;
// Both PersistentStorageDelegate, and GroupDataProvider should be injected by the applications
// See: https://github.com/project-chip/connectedhomeip/issues/12276
DeviceStorageDelegate mDeviceStorage;
Credentials::GroupDataProviderImpl mGroupsProvider;
app::DefaultAttributePersistenceProvider mAttributePersister;
GroupDataProviderListener mListener;
ServerFabricDelegate mFabricDelegate;
Access::AccessControl mAccessControl;
// TODO @ceille: Maybe use OperationalServicePort and CommissionableServicePort
uint16_t mSecuredServicePort;
uint16_t mUnsecuredServicePort;
Inet::InterfaceId mInterfaceId;
};
} // namespace chip