blob: 771d1df8b78121b11a0f4ab68016df1baf03dd05 [file] [log] [blame]
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* Copyright (c) 2013-2017 Nest Labs, Inc.
*
* 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.
*/
/**
* Provides access to UDP (and optionally TCP) EndPointManager.
*/
#pragma once
#include <inet/InetError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ObjectLifeCycle.h>
#include <lib/support/Pool.h>
#include <platform/LockTracker.h>
#include <system/SystemLayer.h>
#include <system/SystemStats.h>
#include <stdint.h>
namespace chip {
namespace Inet {
/**
* Template providing traits for EndPoint types used by EndPointManager.
*
* Instances must define:
* static constexpr const char * kName;
* static constexpr int kSystemStatsKey;
*/
template <class EndPointType>
struct EndPointProperties;
/**
* Manage creating, deletion, and iteration of Inet::EndPoint types.
*/
template <class EndPointType>
class EndPointManager
{
public:
using EndPoint = EndPointType;
using EndPointVisitor = Loop (*)(EndPoint *);
EndPointManager() {}
virtual ~EndPointManager() { VerifyOrDie(mLayerState.Destroy()); }
CHIP_ERROR Init(System::Layer & systemLayer)
{
RegisterLayerErrorFormatter();
VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(systemLayer.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
mSystemLayer = &systemLayer;
mLayerState.SetInitialized();
return CHIP_NO_ERROR;
}
void Shutdown()
{
// Return to uninitialized state to permit re-initialization.
mLayerState.ResetFromInitialized();
mSystemLayer = nullptr;
}
System::Layer & SystemLayer() const { return *mSystemLayer; }
CHIP_ERROR NewEndPoint(EndPoint ** retEndPoint)
{
assertChipStackLockedByCurrentThread();
VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
*retEndPoint = CreateEndPoint();
if (*retEndPoint == nullptr)
{
ChipLogError(Inet, "%s endpoint pool FULL", EndPointProperties<EndPointType>::kName);
return CHIP_ERROR_ENDPOINT_POOL_FULL;
}
SYSTEM_STATS_INCREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
return CHIP_NO_ERROR;
}
void DeleteEndPoint(EndPoint * endPoint)
{
SYSTEM_STATS_DECREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
ReleaseEndPoint(endPoint);
}
virtual EndPoint * CreateEndPoint() = 0;
virtual void ReleaseEndPoint(EndPoint * endPoint) = 0;
virtual Loop ForEachEndPoint(const EndPointVisitor visitor) = 0;
private:
ObjectLifeCycle mLayerState;
System::Layer * mSystemLayer;
};
template <typename EndPointImpl>
class EndPointManagerImplPool : public EndPointManager<typename EndPointImpl::EndPoint>
{
public:
using Manager = EndPointManager<typename EndPointImpl::EndPoint>;
using EndPoint = typename EndPointImpl::EndPoint;
EndPointManagerImplPool() = default;
~EndPointManagerImplPool() override = default;
EndPoint * CreateEndPoint() override { return sEndPointPool.CreateObject(*this); }
void ReleaseEndPoint(EndPoint * endPoint) override { sEndPointPool.ReleaseObject(static_cast<EndPointImpl *>(endPoint)); }
Loop ForEachEndPoint(const typename Manager::EndPointVisitor visitor) override
{
return sEndPointPool.ForEachActiveObject([&](EndPoint * endPoint) -> Loop { return visitor(endPoint); });
}
private:
ObjectPool<EndPointImpl, EndPointProperties<EndPoint>::kNumEndPoints> sEndPointPool;
};
class TCPEndPoint;
class UDPEndPoint;
} // namespace Inet
} // namespace chip