Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020-2021 Project CHIP Authors 4 : * Copyright (c) 2013-2017 Nest Labs, Inc. 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 : * Provides access to UDP (and optionally TCP) EndPointManager. 21 : */ 22 : 23 : #pragma once 24 : 25 : #include <inet/InetError.h> 26 : #include <lib/support/CodeUtils.h> 27 : #include <lib/support/ObjectLifeCycle.h> 28 : #include <lib/support/Pool.h> 29 : #include <platform/LockTracker.h> 30 : #include <system/SystemLayer.h> 31 : #include <system/SystemStats.h> 32 : 33 : #include <stdint.h> 34 : 35 : namespace chip { 36 : namespace Inet { 37 : 38 : /** 39 : * Template providing traits for EndPoint types used by EndPointManager. 40 : * 41 : * Instances must define: 42 : * static constexpr const char * kName; 43 : * static constexpr int kSystemStatsKey; 44 : */ 45 : template <class EndPointType> 46 : struct EndPointProperties; 47 : 48 : /** 49 : * Manage creating, deletion, and iteration of Inet::EndPoint types. 50 : */ 51 : template <class EndPointType> 52 : class EndPointManager 53 : { 54 : public: 55 : using EndPoint = EndPointType; 56 : using EndPointVisitor = Loop (*)(EndPoint *); 57 : 58 : EndPointManager() {} 59 : virtual ~EndPointManager() { VerifyOrDie(mLayerState.Destroy()); } 60 : 61 : CHIP_ERROR Init(System::Layer & systemLayer) 62 : { 63 : RegisterLayerErrorFormatter(); 64 : VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE); 65 : VerifyOrReturnError(systemLayer.IsInitialized(), CHIP_ERROR_INCORRECT_STATE); 66 : mSystemLayer = &systemLayer; 67 : mLayerState.SetInitialized(); 68 : return CHIP_NO_ERROR; 69 : } 70 : 71 : void Shutdown() 72 : { 73 : // Return to uninitialized state to permit re-initialization. 74 : mLayerState.ResetFromInitialized(); 75 : mSystemLayer = nullptr; 76 : } 77 : 78 327 : System::Layer & SystemLayer() const { return *mSystemLayer; } 79 : 80 86 : CHIP_ERROR NewEndPoint(EndPoint ** retEndPoint) 81 : { 82 86 : assertChipStackLockedByCurrentThread(); 83 86 : VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE); 84 : 85 86 : *retEndPoint = CreateEndPoint(); 86 86 : if (*retEndPoint == nullptr) 87 : { 88 0 : ChipLogError(Inet, "%s endpoint pool FULL", EndPointProperties<EndPointType>::kName); 89 0 : return CHIP_ERROR_ENDPOINT_POOL_FULL; 90 : } 91 : 92 86 : SYSTEM_STATS_INCREMENT(EndPointProperties<EndPointType>::kSystemStatsKey); 93 86 : return CHIP_NO_ERROR; 94 : } 95 : 96 89 : void DeleteEndPoint(EndPoint * endPoint) 97 : { 98 89 : SYSTEM_STATS_DECREMENT(EndPointProperties<EndPointType>::kSystemStatsKey); 99 89 : ReleaseEndPoint(endPoint); 100 89 : } 101 : 102 : virtual EndPoint * CreateEndPoint() = 0; 103 : virtual void ReleaseEndPoint(EndPoint * endPoint) = 0; 104 : virtual Loop ForEachEndPoint(const EndPointVisitor visitor) = 0; 105 : 106 : private: 107 : ObjectLifeCycle mLayerState; 108 : System::Layer * mSystemLayer; 109 : }; 110 : 111 : template <typename EndPointImpl> 112 : class EndPointManagerImplPool : public EndPointManager<typename EndPointImpl::EndPoint> 113 : { 114 : public: 115 : using Manager = EndPointManager<typename EndPointImpl::EndPoint>; 116 : using EndPoint = typename EndPointImpl::EndPoint; 117 : 118 : EndPointManagerImplPool() = default; 119 : ~EndPointManagerImplPool() override = default; 120 : 121 : EndPoint * CreateEndPoint() override { return sEndPointPool.CreateObject(*this); } 122 : void ReleaseEndPoint(EndPoint * endPoint) override { sEndPointPool.ReleaseObject(static_cast<EndPointImpl *>(endPoint)); } 123 : Loop ForEachEndPoint(const typename Manager::EndPointVisitor visitor) override 124 : { 125 : return sEndPointPool.ForEachActiveObject([&](EndPoint * endPoint) -> Loop { return visitor(endPoint); }); 126 : } 127 : 128 : private: 129 : ObjectPool<EndPointImpl, EndPointProperties<EndPoint>::kNumEndPoints> sEndPointPool; 130 : }; 131 : 132 : class TCPEndPoint; 133 : class UDPEndPoint; 134 : 135 : } // namespace Inet 136 : } // namespace chip