Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2023 Project CHIP Authors
4 : * All rights reserved.
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 : * @file
21 : * This file defines the CHIP Active Connection object that maintains TCP connections.
22 : */
23 :
24 : #pragma once
25 :
26 : #include <functional>
27 : #include <inet/IPAddress.h>
28 : #include <inet/InetInterface.h>
29 : #include <inet/TCPEndPoint.h>
30 : #include <lib/core/CHIPCore.h>
31 : #include <lib/core/ReferenceCounted.h>
32 : #include <lib/support/AutoRelease.h>
33 : #include <transport/raw/PeerAddress.h>
34 : #include <transport/raw/TCPConfig.h>
35 :
36 : namespace chip {
37 : namespace Transport {
38 :
39 : // Forward declaration of friend class for test access.
40 : template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
41 : class TCPBaseTestAccess;
42 :
43 : /**
44 : * The State of the TCP connection
45 : */
46 : enum class TCPState : uint8_t
47 : {
48 : kNotReady = 0, /**< State before initialization. */
49 : kInitialized = 1, /**< State after class is listening and ready. */
50 : kConnecting = 3, /**< Connection with peer has been initiated. */
51 : kConnected = 4, /**< Connected with peer and ready for Send/Receive. */
52 : kClosed = 5, /**< Connection is closed. */
53 : };
54 :
55 : struct AppTCPConnectionCallbackCtxt;
56 :
57 : // Templatized to force inlining
58 : template <typename State>
59 : class ActiveTCPConnectionStateDeleter
60 : {
61 : public:
62 27 : inline static void Release(State * entry) { entry->mReleaseConnection(*entry); }
63 : };
64 :
65 : /**
66 : * State for each active TCP connection
67 : */
68 : class ActiveTCPConnectionHolder;
69 : struct ActiveTCPConnectionState
70 : : public ReferenceCounted<ActiveTCPConnectionState, ActiveTCPConnectionStateDeleter<ActiveTCPConnectionState>, 0, uint16_t>
71 : {
72 : using ReleaseFnType = std::function<void(ActiveTCPConnectionState & connection)>;
73 :
74 316 : bool InUse() const { return mEndPoint != nullptr; }
75 :
76 212 : bool IsConnected() const { return (mEndPoint != nullptr && mConnectionState == TCPState::kConnected); }
77 :
78 0 : bool IsConnecting() const { return (mEndPoint != nullptr && mConnectionState == TCPState::kConnecting); }
79 :
80 : inline bool operator==(const ActiveTCPConnectionHolder & other) const;
81 : inline bool operator!=(const ActiveTCPConnectionHolder & other) const;
82 :
83 : // Peer Node Address
84 : PeerAddress mPeerAddr;
85 :
86 : // Buffers received but not yet consumed.
87 : System::PacketBufferHandle mReceived;
88 :
89 : // Current state of the connection
90 : TCPState mConnectionState;
91 :
92 : // A pointer to an application-specific state object. It should
93 : // represent an object that is at a layer above the SessionManager. The
94 : // SessionManager would accept this object at the time of connecting to
95 : // the peer, and percolate it down to the TransportManager that then,
96 : // should store this state in the corresponding connection object that
97 : // is created.
98 : // At various connection events, this state is passed back to the
99 : // corresponding application.
100 : AppTCPConnectionCallbackCtxt * mAppState = nullptr;
101 :
102 : // KeepAlive interval in seconds
103 : uint16_t mTCPKeepAliveIntervalSecs = CHIP_CONFIG_TCP_KEEPALIVE_INTERVAL_SECS;
104 : uint16_t mTCPMaxNumKeepAliveProbes = CHIP_CONFIG_MAX_TCP_KEEPALIVE_PROBES;
105 :
106 : // This is bad and should not normally be done; we are explicitly closing the TCP connection
107 : // instead of gracefully releasing our reference, which will theoretically cause anyone
108 : // holding a reference (who should have a listener for connection closing) to release their reference
109 : void ForceDisconnect() { mReleaseConnection(*this); }
110 :
111 : private:
112 : template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
113 : friend class TCP;
114 : friend class TCPBase;
115 : friend class ActiveTCPConnectionStateDeleter<ActiveTCPConnectionState>;
116 : // Allow tests to access private members.
117 : template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
118 : friend class TCPBaseTestAccess;
119 :
120 : // Associated endpoint.
121 : Inet::TCPEndPoint * mEndPoint;
122 : ReleaseFnType mReleaseConnection;
123 :
124 216 : void Init(Inet::TCPEndPoint * endPoint, const PeerAddress & peerAddr, ReleaseFnType releaseConnection)
125 : {
126 216 : if (endPoint)
127 : {
128 28 : endPoint->Retain();
129 : }
130 216 : mEndPoint = endPoint;
131 216 : mPeerAddr = peerAddr;
132 216 : mReceived = nullptr;
133 216 : mAppState = nullptr;
134 216 : mReleaseConnection = releaseConnection;
135 216 : }
136 :
137 28 : void Free()
138 : {
139 28 : if (mEndPoint)
140 : {
141 28 : mEndPoint->Release();
142 : }
143 28 : mPeerAddr = PeerAddress::Uninitialized();
144 28 : mEndPoint = nullptr;
145 28 : mReceived = nullptr;
146 28 : mAppState = nullptr;
147 28 : mReleaseConnection = [](auto &) {};
148 28 : }
149 : };
150 :
151 : /**
152 : * A holder for ActiveTCPConnectionState which properly ref-counts on ctor/copy/dtor.
153 : */
154 : class ActiveTCPConnectionHolder : private AutoRelease<ActiveTCPConnectionState>
155 : {
156 : friend class TCPBase;
157 : friend struct ActiveTCPConnectionState;
158 :
159 : public:
160 : using AutoRelease<ActiveTCPConnectionState>::operator->;
161 : using AutoRelease<ActiveTCPConnectionState>::IsNull;
162 : using AutoRelease<ActiveTCPConnectionState>::Release;
163 :
164 135939 : ActiveTCPConnectionHolder() : AutoRelease<ActiveTCPConnectionState>(nullptr) {}
165 85 : ActiveTCPConnectionHolder(ActiveTCPConnectionState * releasable) :
166 85 : AutoRelease<ActiveTCPConnectionState>(releasable ? releasable->Retain() : nullptr)
167 85 : {}
168 :
169 0 : ActiveTCPConnectionHolder(const ActiveTCPConnectionHolder & src) : ActiveTCPConnectionHolder(src.mReleasable) {}
170 :
171 111 : inline AutoRelease & operator=(const ActiveTCPConnectionHolder & src)
172 : {
173 111 : if (mReleasable != src.mReleasable)
174 : {
175 101 : Set(src.IsNull() ? nullptr : src.mReleasable->Retain());
176 : }
177 111 : return *this;
178 : }
179 :
180 36 : inline bool operator==(const ActiveTCPConnectionHolder & other) const { return mReleasable == other.mReleasable; }
181 0 : inline bool operator!=(const ActiveTCPConnectionHolder & other) const { return mReleasable != other.mReleasable; }
182 0 : inline bool operator==(const ActiveTCPConnectionState & other) const { return mReleasable == &other; }
183 : inline bool operator!=(const ActiveTCPConnectionState & other) const { return mReleasable != &other; }
184 :
185 : // For printing
186 0 : inline operator const void *() const { return mReleasable; }
187 : };
188 :
189 0 : inline bool ActiveTCPConnectionState::operator==(const ActiveTCPConnectionHolder & other) const
190 : {
191 0 : return this == other.mReleasable;
192 : }
193 : inline bool ActiveTCPConnectionState::operator!=(const ActiveTCPConnectionHolder & other) const
194 : {
195 : return this != other.mReleasable;
196 : }
197 :
198 : // Functors for callbacks into higher layers
199 : using OnTCPConnectionReceivedCallback = void (*)(ActiveTCPConnectionState & conn);
200 :
201 : using OnTCPConnectionCompleteCallback = void (*)(ActiveTCPConnectionHolder & conn, CHIP_ERROR conErr);
202 :
203 : using OnTCPConnectionClosedCallback = void (*)(ActiveTCPConnectionState & conn, CHIP_ERROR conErr);
204 :
205 : /*
206 : * Application callback state that is passed down at connection establishment
207 : * stage.
208 : * */
209 : struct AppTCPConnectionCallbackCtxt
210 : {
211 : void * appContext = nullptr; // A pointer to an application context object.
212 : OnTCPConnectionReceivedCallback connReceivedCb = nullptr;
213 : OnTCPConnectionCompleteCallback connCompleteCb = nullptr;
214 : OnTCPConnectionClosedCallback connClosedCb = nullptr;
215 : };
216 :
217 : } // namespace Transport
218 : } // namespace chip
|