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