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 467 : System::Layer & SystemLayer() const { return *mSystemLayer; }
79 :
80 96 : CHIP_ERROR NewEndPoint(EndPoint ** retEndPoint)
81 : {
82 96 : assertChipStackLockedByCurrentThread();
83 96 : VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
84 :
85 96 : *retEndPoint = CreateEndPoint();
86 96 : 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 96 : SYSTEM_STATS_INCREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
93 96 : return CHIP_NO_ERROR;
94 : }
95 :
96 99 : void DeleteEndPoint(EndPoint * endPoint)
97 : {
98 99 : SYSTEM_STATS_DECREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
99 99 : ReleaseEndPoint(endPoint);
100 99 : }
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
|