Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2025 Project CHIP Authors
4 : * Copyright (c) 2018 Google LLC
5 : * Copyright (c) 2013-2017 Nest Labs, Inc.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * This header file defines the <tt>Inet::UDPEndPoint</tt>
23 : * class, where the CHIP Inet Layer encapsulates methods for
24 : * interacting with UDP transport endpoints (SOCK_DGRAM sockets
25 : * on Linux and BSD-derived systems) or LwIP UDP protocol
26 : * control blocks, as the system is configured accordingly.
27 : */
28 :
29 : #pragma once
30 :
31 : #include <inet/InetConfig.h>
32 :
33 : #include <inet/EndPointBasis.h>
34 : #include <inet/IPAddress.h>
35 : #include <inet/IPPacketInfo.h>
36 : #include <inet/InetInterface.h>
37 : #include <inet/InetLayer.h>
38 : #include <system/SystemPacketBuffer.h>
39 :
40 : struct otInstance;
41 :
42 : namespace chip {
43 : namespace Inet {
44 :
45 : class UDPEndPoint;
46 : using UDPEndPointHandle = EndPointHandle<UDPEndPoint>;
47 :
48 : /**
49 : * @brief Objects of this class represent UDP transport endpoints.
50 : *
51 : * @details
52 : * CHIP Inet Layer encapsulates methods for interacting with UDP transport
53 : * endpoints (SOCK_DGRAM sockets on Linux and BSD-derived systems) or LwIP
54 : * UDP protocol control blocks, as the system is configured accordingly.
55 : */
56 : class DLL_EXPORT UDPEndPoint : public EndPointBasis<UDPEndPoint>
57 : {
58 : public:
59 : UDPEndPoint(const UDPEndPoint &) = delete;
60 : UDPEndPoint(UDPEndPoint &&) = delete;
61 : UDPEndPoint & operator=(const UDPEndPoint &) = delete;
62 : UDPEndPoint & operator=(UDPEndPoint &&) = delete;
63 :
64 : /**
65 : * Type of message text reception event handling function.
66 : *
67 : * @param[in] endPoint The endpoint associated with the event.
68 : * @param[in] msg The message text received.
69 : * @param[in] pktInfo The packet's IP information.
70 : *
71 : * Provide a function of this type to the \c OnMessageReceived delegate
72 : * member to process message text reception events on \c endPoint where
73 : * \c msg is the message text received from the sender at \c senderAddr.
74 : */
75 : using OnMessageReceivedFunct = void (*)(UDPEndPoint * endPoint, chip::System::PacketBufferHandle && msg,
76 : const IPPacketInfo * pktInfo);
77 :
78 : /**
79 : * Type of reception error event handling function.
80 : *
81 : * @param[in] endPoint The endpoint associated with the event.
82 : * @param[in] err The reason for the error.
83 : * @param[in] pktInfo The packet's IP information.
84 : *
85 : * Provide a function of this type to the \c OnReceiveError delegate
86 : * member to process reception error events on \c endPoint. The \c err
87 : * argument provides specific detail about the type of the error.
88 : */
89 : using OnReceiveErrorFunct = void (*)(UDPEndPoint * endPoint, CHIP_ERROR err, const IPPacketInfo * pktInfo);
90 :
91 : /**
92 : * Set whether IP multicast traffic should be looped back.
93 : */
94 : virtual CHIP_ERROR SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) = 0;
95 :
96 : /**
97 : * Join an IP multicast group.
98 : *
99 : * @param[in] aInterfaceId The indicator of the network interface to add to the multicast group.
100 : * @param[in] aAddress The multicast group to add the interface to.
101 : *
102 : * @retval CHIP_NO_ERROR Success: multicast group removed.
103 : * @retval INET_ERROR_UNKNOWN_INTERFACE Unknown network interface, \c aInterfaceId.
104 : * @retval INET_ERROR_WRONG_ADDRESS_TYPE \c aAddress is not \c kIPv4 or \c kIPv6 or is not multicast.
105 : * @retval other Another system or platform error.
106 : */
107 : CHIP_ERROR JoinMulticastGroup(InterfaceId aInterfaceId, const IPAddress & aAddress);
108 :
109 : /**
110 : * Leave an IP multicast group.
111 : *
112 : * @param[in] aInterfaceId The indicator of the network interface to remove from the multicast group.
113 : * @param[in] aAddress The multicast group to remove the interface from.
114 : *
115 : * @retval CHIP_NO_ERROR Success: multicast group removed
116 : * @retval INET_ERROR_UNKNOWN_INTERFACE Unknown network interface, \c aInterfaceId
117 : * @retval INET_ERROR_WRONG_ADDRESS_TYPE \c aAddress is not \c kIPv4 or \c kIPv6 or is not multicast.
118 : * @retval other Another system or platform error
119 : */
120 : CHIP_ERROR LeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress & aAddress);
121 :
122 : /**
123 : * Bind the endpoint to an interface IP address.
124 : *
125 : * Binds the endpoint to the specified network interface IP address.
126 : *
127 : * On LwIP, this method must not be called with the LwIP stack lock already acquired.
128 : *
129 : * @param[in] addrType Protocol version of the IP address.
130 : * @param[in] addr IP address (must be an interface address).
131 : * @param[in] port UDP port.
132 : * @param[in] intfId An optional network interface indicator.
133 : *
134 : * @retval CHIP_NO_ERROR Success: endpoint bound to address.
135 : * @retval CHIP_ERROR_INCORRECT_STATE Endpoint has been bound previously.
136 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory for endpoint.
137 : * @retval INET_ERROR_UNKNOWN_INTERFACE The optionally specified interface is not present.
138 : * @retval INET_ERROR_WRONG_PROTOCOL_TYPE \c addrType does not match \c IPVer.
139 : * @retval INET_ERROR_WRONG_ADDRESS_TYPE \c addrType is \c IPAddressType::kAny, or not equal to the type of \c addr.
140 : * @retval other Another system or platform error
141 : */
142 : CHIP_ERROR Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, InterfaceId intfId = InterfaceId::Null());
143 :
144 : /**
145 : * Bind the endpoint to a network interface.
146 : *
147 : * Binds the endpoint to the specified network interface IP address.
148 : *
149 : * On LwIP, this method must not be called with the LwIP stack lock already acquired.
150 : *
151 : * @param[in] addrType Protocol version of the IP address.
152 : * @param[in] intfId Network interface.
153 : *
154 : * @retval CHIP_NO_ERROR Success: endpoint bound to address.
155 : * @retval CHIP_ERROR_NO_MEMORY Insufficient memory for endpoint.
156 : * @retval CHIP_ERROR_NOT_IMPLEMENTED System implementation not complete.
157 : * @retval INET_ERROR_UNKNOWN_INTERFACE The interface is not present.
158 : * @retval other Another system or platform error.
159 : */
160 : CHIP_ERROR BindInterface(IPAddressType addrType, InterfaceId intfId);
161 :
162 : /**
163 : * Get the bound interface on this endpoint.
164 : */
165 : virtual InterfaceId GetBoundInterface() const = 0;
166 :
167 : /**
168 : * Get the bound port on this endpoint.
169 : */
170 : virtual uint16_t GetBoundPort() const = 0;
171 :
172 : /**
173 : * Prepare the endpoint to receive UDP messages.
174 : *
175 : * If \c mState is already \c State::kListening, then no operation is
176 : * performed, otherwise the \c mState is set to \c State::kListening and
177 : * the endpoint is prepared to received UDP messages, according to the
178 : * semantics of the platform.
179 : *
180 : * On LwIP, this method must not be called with the LwIP stack lock already acquired.
181 : *
182 : * @param[in] onMessageReceived The endpoint's message reception event handling function delegate.
183 : * @param[in] onReceiveError The endpoint's receive error event handling function delegate.
184 : * @param[in] appState Application state pointer.
185 : *
186 : * @retval CHIP_NO_ERROR Success: endpoint ready to receive messages.
187 : * @retval CHIP_ERROR_INCORRECT_STATE Endpoint is already listening.
188 : */
189 : CHIP_ERROR Listen(OnMessageReceivedFunct onMessageReceived, OnReceiveErrorFunct onReceiveError, void * appState = nullptr);
190 :
191 : /**
192 : * Send a UDP message to the specified destination address.
193 : *
194 : * If possible, then this method sends the UDP message \c msg to the destination \c addr
195 : * (with \c intfId used as the scope identifier for IPv6 link-local destinations) and \c port.
196 : *
197 : * @param[in] addr Destination IP address.
198 : * @param[in] port Destination UDP port.
199 : * @param[in] msg Packet buffer containing the UDP message.
200 : * @param[in] intfId Optional network interface indicator.
201 : *
202 : * @retval CHIP_NO_ERROR Success: \c msg is queued for transmit.
203 : * @retval CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE The system does not support the requested operation.
204 : * @retval INET_ERROR_WRONG_ADDRESS_TYPE The destination address and the bound interface address do not have
205 : * matching protocol versions or address type.
206 : * @retval CHIP_ERROR_MESSAGE_TOO_LONG \c msg does not contain the whole UDP message.
207 : * @retval CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG Only a truncated portion of \c msg was queued for transmit.
208 : * @retval other Another system or platform error.
209 : */
210 : CHIP_ERROR SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle && msg,
211 : InterfaceId intfId = InterfaceId::Null());
212 :
213 : /**
214 : * Send a UDP message to a specified destination.
215 : *
216 : * Send the UDP message in \c msg to the destination address and port given in \c pktInfo.
217 : * If \c pktInfo contains an interface id, the message will be sent over the specified interface.
218 : * If \c pktInfo contains a source address, the given address will be used as the source of the UDP message.
219 : *
220 : * @param[in] pktInfo Source and destination information for the UDP message.
221 : * @param[in] msg Packet buffer containing the UDP message.
222 : *
223 : * @retval CHIP_NO_ERROR Success: \c msg is queued for transmit.
224 : * @retval CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE The system does not support the requested operation.
225 : * @retval INET_ERROR_WRONG_ADDRESS_TYPE The destination address and the bound interface address do not have
226 : * matching protocol versions or address type.
227 : * @retval CHIP_ERROR_MESSAGE_TOO_LONG \c msg does not contain the whole UDP message.
228 : * @retval CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG Only a truncated portion of \c msg was queued for transmit.
229 : * @retval other Another system or platform error.
230 : */
231 : CHIP_ERROR SendMsg(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle && msg);
232 :
233 : /**
234 : * Close the endpoint.
235 : *
236 : * If <tt>mState != State::kClosed</tt>, then closes the endpoint, removing
237 : * it from the set of endpoints eligible for communication events.
238 : *
239 : * On LwIP systems, this method must not be called with the LwIP stack lock already acquired.
240 : */
241 : void Close();
242 :
243 : /**
244 : * Set Network Native Parameters (optional)
245 : *
246 : * Some networking stack requires additionnal parameters
247 : */
248 7 : virtual inline void SetNativeParams(void * params) { (void) params; }
249 :
250 : inline bool operator==(const UDPEndPointHandle & other) const { return other == *this; }
251 : inline bool operator!=(const UDPEndPointHandle & other) const { return other != *this; }
252 :
253 : protected:
254 : friend class EndPointDeletor<UDPEndPoint>;
255 : friend class EndPointHandle<UDPEndPoint>;
256 :
257 81 : UDPEndPoint(EndPointManager<UDPEndPoint> & endPointManager) :
258 81 : EndPointBasis(endPointManager), mState(State::kReady), OnMessageReceived(nullptr), OnReceiveError(nullptr)
259 81 : {}
260 :
261 81 : virtual ~UDPEndPoint() = default;
262 :
263 : /**
264 : * Basic dynamic state of the underlying endpoint.
265 : *
266 : * Objects are initialized in the "ready" state, proceed to the "bound"
267 : * state after binding to a local interface address, then proceed to the
268 : * "listening" state when they have continuations registered for handling
269 : * events for reception of ICMP messages.
270 : */
271 : enum class State : uint8_t
272 : {
273 : kReady = 0, /**< Endpoint initialized, but not open. */
274 : kBound = 1, /**< Endpoint bound, but not listening. */
275 : kListening = 2, /**< Endpoint receiving datagrams. */
276 : kClosed = 3 /**< Endpoint closed, ready for release. */
277 : } mState;
278 :
279 : /** The endpoint's message reception event handling function delegate. */
280 : OnMessageReceivedFunct OnMessageReceived;
281 :
282 : /** The endpoint's receive error event handling function delegate. */
283 : OnReceiveErrorFunct OnReceiveError;
284 :
285 : /*
286 : * Implementation helpers for shared methods.
287 : */
288 : #if INET_CONFIG_ENABLE_IPV4
289 : virtual CHIP_ERROR IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) = 0;
290 : #endif // INET_CONFIG_ENABLE_IPV4
291 : virtual CHIP_ERROR IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) = 0;
292 :
293 : virtual CHIP_ERROR BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, InterfaceId interfaceId) = 0;
294 : virtual CHIP_ERROR BindInterfaceImpl(IPAddressType addressType, InterfaceId interfaceId) = 0;
295 : virtual CHIP_ERROR ListenImpl() = 0;
296 : virtual CHIP_ERROR SendMsgImpl(const IPPacketInfo * pktInfo, chip::System::PacketBufferHandle && msg) = 0;
297 : virtual void CloseImpl() = 0;
298 :
299 : /**
300 : * Close the endpoint and recycle its memory.
301 : *
302 : * Invokes the \c Close method, then invokes the <tt>EndPointBasis::Delete</tt> method to return the object to its
303 : * memory pool.
304 : *
305 : * On LwIP systems, this method must not be called with the LwIP stack lock already acquired.
306 : */
307 : virtual void Free();
308 : };
309 :
310 : template <>
311 : struct EndPointProperties<UDPEndPoint>
312 : {
313 : static constexpr char kName[] = "UDP";
314 : static constexpr size_t kNumEndPoints = INET_CONFIG_NUM_UDP_ENDPOINTS;
315 : static constexpr int kSystemStatsKey = System::Stats::kInetLayer_NumUDPEps;
316 : };
317 :
318 : } // namespace Inet
319 : } // namespace chip
|