Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2025 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/EndPointBasis.h>
26 : #include <inet/InetError.h>
27 : #include <lib/support/CodeUtils.h>
28 : #include <lib/support/ObjectLifeCycle.h>
29 : #include <lib/support/Pool.h>
30 : #include <lib/support/ReferenceCountedPtr.h>
31 : #include <platform/LockTracker.h>
32 : #include <system/SystemLayer.h>
33 : #include <system/SystemStats.h>
34 :
35 : #include <stdint.h>
36 :
37 : namespace chip {
38 : namespace Inet {
39 :
40 : template <typename EndPointType>
41 : class EndPointDeletor;
42 :
43 : /**
44 : * Template providing traits for EndPoint types used by EndPointManager.
45 : *
46 : * Instances must define:
47 : * static constexpr const char * kName;
48 : * static constexpr int kSystemStatsKey;
49 : */
50 : template <class EndPointType>
51 : struct EndPointProperties;
52 :
53 : template <class EndPointType>
54 : class EndPointHandle : public ReferenceCountedPtr<EndPointType>
55 : {
56 : public:
57 : using ReferenceCountedPtr<EndPointType>::ReferenceCountedPtr;
58 :
59 : // For printing
60 : inline operator const void *() const { return this->mRefCounted; }
61 : };
62 :
63 : /**
64 : * Manage creating, deletion, and iteration of Inet::EndPoint types.
65 : */
66 : template <class EndPointType>
67 : class EndPointManager
68 : {
69 : public:
70 : using EndPoint = EndPointType;
71 : using TypedEndPointHandle = EndPointHandle<EndPoint>;
72 : using EndPointVisitor = Loop (*)(const TypedEndPointHandle &);
73 :
74 187 : EndPointManager() {}
75 187 : virtual ~EndPointManager() { VerifyOrDie(mLayerState.Destroy()); }
76 :
77 222 : CHIP_ERROR Init(System::Layer & systemLayer)
78 : {
79 222 : RegisterLayerErrorFormatter();
80 222 : VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);
81 222 : VerifyOrReturnError(systemLayer.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
82 222 : mSystemLayer = &systemLayer;
83 222 : mLayerState.SetInitialized();
84 222 : return CHIP_NO_ERROR;
85 : }
86 :
87 224 : void Shutdown()
88 : {
89 : // Return to uninitialized state to permit re-initialization.
90 224 : mLayerState.ResetFromInitialized();
91 224 : mSystemLayer = nullptr;
92 224 : }
93 :
94 693 : System::Layer & SystemLayer() const { return *mSystemLayer; }
95 :
96 143 : CHIP_ERROR NewEndPoint(TypedEndPointHandle & retEndPoint)
97 : {
98 143 : assertChipStackLockedByCurrentThread();
99 143 : VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
100 :
101 141 : retEndPoint = std::move(CreateEndPoint());
102 141 : if (retEndPoint.IsNull())
103 : {
104 0 : ChipLogError(Inet, "%s endpoint pool FULL", EndPointProperties<EndPointType>::kName);
105 0 : return CHIP_ERROR_ENDPOINT_POOL_FULL;
106 : }
107 :
108 141 : SYSTEM_STATS_INCREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
109 141 : return CHIP_NO_ERROR;
110 : }
111 :
112 : virtual Loop ForEachEndPoint(const EndPointVisitor visitor) = 0;
113 :
114 : protected:
115 : friend class EndPointDeletor<EndPointType>;
116 : friend class EndPointHandle<EndPointType>;
117 : friend class EndPointBasis<EndPointType>;
118 : friend EndPointType;
119 :
120 : virtual TypedEndPointHandle CreateEndPoint() = 0;
121 :
122 : virtual void ReleaseEndPoint(EndPoint * endPoint) = 0;
123 :
124 141 : void DeleteEndPoint(EndPoint * endPoint)
125 : {
126 141 : SYSTEM_STATS_DECREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
127 141 : ReleaseEndPoint(endPoint);
128 141 : }
129 :
130 : private:
131 : ObjectLifeCycle mLayerState;
132 : System::Layer * mSystemLayer;
133 : };
134 :
135 : template <typename EndPointImpl>
136 : class EndPointManagerImplPool : public EndPointManager<typename EndPointImpl::EndPoint>
137 : {
138 : public:
139 : using Manager = EndPointManager<typename EndPointImpl::EndPoint>;
140 : using EndPoint = typename EndPointImpl::EndPoint;
141 : using TypedEndPointHandle = typename Manager::TypedEndPointHandle;
142 :
143 187 : EndPointManagerImplPool() = default;
144 187 : ~EndPointManagerImplPool() override = default;
145 :
146 141 : TypedEndPointHandle CreateEndPoint() override { return sEndPointPool.CreateObject(*this); }
147 120 : Loop ForEachEndPoint(const typename Manager::EndPointVisitor visitor) override
148 : {
149 240 : return sEndPointPool.ForEachActiveObject([&](EndPoint * endPoint) -> Loop {
150 0 : TypedEndPointHandle handle(endPoint);
151 0 : return visitor(handle);
152 120 : });
153 : }
154 :
155 : private:
156 141 : void ReleaseEndPoint(EndPoint * endPoint) override { sEndPointPool.ReleaseObject(static_cast<EndPointImpl *>(endPoint)); }
157 :
158 : ObjectPool<EndPointImpl, EndPointProperties<EndPoint>::kNumEndPoints> sEndPointPool;
159 : };
160 :
161 : class TCPEndPoint;
162 : class UDPEndPoint;
163 :
164 : } // namespace Inet
165 : } // namespace chip
|