blob: 073f633bd8a38cdccd8a6b820cb251193e47a378 [file] [log] [blame]
Jean-Francois Penven1cbec522022-01-11 11:54:40 -05001/*
2 *
3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2018 Google LLC.
5 * Copyright (c) 2013-2018 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
Jean-Francois Penvenfd529192022-03-25 21:43:47 -040020#include <inet/UDPEndPointImplOpenThread.h>
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050021
22#include <lib/support/CodeUtils.h>
23#include <lib/support/SafeInt.h>
24#include <lib/support/logging/CHIPLogging.h>
25
26#include <platform/OpenThread/OpenThreadUtils.h>
27
28#include <system/SystemPacketBuffer.h>
29
30namespace chip {
31namespace Inet {
32
Jean-Francois Penvenfa087ea2022-04-22 14:53:57 -040033otInstance * globalOtInstance;
34
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040035namespace {
36// We want to reserve space for an IPPacketInfo in our buffer, but it needs to
Kevin Schoedel7b3fb842022-06-07 20:30:00 -040037// be 4-byte aligned. We ensure the alignment by masking off the low bits of
38// the pointer that we get by doing `Start() - sizeof(IPPacketInfo)`. That
39// might move it backward by up to kPacketInfoAlignmentBytes, so we need to make
40// sure we allocate enough reserved space that this will still be within our
41// buffer.
42constexpr uint16_t kPacketInfoAlignmentBytes = sizeof(uint32_t) - 1;
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040043constexpr uint16_t kPacketInfoReservedSize = sizeof(IPPacketInfo) + kPacketInfoAlignmentBytes;
44} // namespace
45
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050046void UDPEndPointImplOT::handleUdpReceive(void * aContext, otMessage * aMessage, const otMessageInfo * aMessageInfo)
47{
48 UDPEndPointImplOT * ep = static_cast<UDPEndPointImplOT *>(aContext);
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040049 uint16_t msgLen = otMessageGetLength(aMessage);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050050 System::PacketBufferHandle payload;
51#if CHIP_DETAIL_LOGGING
52 static uint16_t msgReceivedCount = 0;
53 char sourceStr[Inet::IPAddress::kMaxStringLength];
54 char destStr[Inet::IPAddress::kMaxStringLength];
55#endif
56
Zang MingJief5eec6e2022-07-14 21:20:54 +080057 if (ep->mState == State::kClosed)
58 return;
59
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050060 if (msgLen > System::PacketBuffer::kMaxSizeWithoutReserve)
61 {
62 ChipLogError(Inet, "UDP message too long, discarding. Size received %d", msgLen);
63 return;
64 }
65
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040066 payload = System::PacketBufferHandle::New(msgLen, kPacketInfoReservedSize);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050067
68 if (payload.IsNull())
69 {
70 ChipLogError(Inet, "Failed to allocate a System buffer of size %d for UDP Message reception.", msgLen);
71 return;
72 }
73
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040074 IPPacketInfo * pktInfo = GetPacketInfo(payload);
75 if (pktInfo == nullptr)
76 {
77 ChipLogError(Inet, "Failed to pre-allocate reserved space for an IPPacketInfo for UDP Message reception.");
78 return;
79 }
80
81 pktInfo->SrcAddress = IPAddress::FromOtAddr(aMessageInfo->mPeerAddr);
82 pktInfo->DestAddress = IPAddress::FromOtAddr(aMessageInfo->mSockAddr);
83 pktInfo->SrcPort = aMessageInfo->mPeerPort;
84 pktInfo->DestPort = aMessageInfo->mSockPort;
85
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050086#if CHIP_DETAIL_LOGGING
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040087 pktInfo->SrcAddress.ToString(sourceStr, Inet::IPAddress::kMaxStringLength);
88 pktInfo->DestAddress.ToString(destStr, Inet::IPAddress::kMaxStringLength);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050089
90 ChipLogDetail(Inet,
Jean-Francois Penven316e6652022-04-04 14:23:04 -040091 "UDP Message Received packet nb : %d SrcAddr : %s[%d] DestAddr "
92 ": %s[%d] Payload Length %d",
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040093 ++msgReceivedCount, sourceStr, pktInfo->SrcPort, destStr, pktInfo->DestPort, msgLen);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050094
95#endif
96
Boris Zbarsky3956a9d2022-05-26 14:38:43 -040097 if (otMessageRead(aMessage, 0, payload->Start(), msgLen) != msgLen)
Jean-Francois Penven1cbec522022-01-11 11:54:40 -050098 {
99 ChipLogError(Inet, "Failed to copy OpenThread buffer into System Packet buffer");
100 return;
101 }
Boris Zbarsky3956a9d2022-05-26 14:38:43 -0400102 payload->SetDataLength(static_cast<uint16_t>(msgLen));
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500103
Jiacheng Guoad63a632022-07-14 21:20:25 +0800104 // TODO: add thread-safe reference counting for UDP endpoints
105 auto * buf = std::move(payload).UnsafeRelease();
106 CHIP_ERROR err =
107 ep->GetSystemLayer().ScheduleLambda([ep, buf] { ep->HandleDataReceived(System::PacketBufferHandle::Adopt(buf)); });
Boris Zbarskye5922b32022-04-21 12:02:44 -0400108 if (err != CHIP_NO_ERROR)
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500109 {
Boris Zbarskye5922b32022-04-21 12:02:44 -0400110 // Make sure we properly clean up buf and ep, since our lambda will not
111 // run.
112 payload = System::PacketBufferHandle::Adopt(buf);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500113 }
114}
115
116CHIP_ERROR UDPEndPointImplOT::IPv6Bind(otUdpSocket & socket, const IPAddress & address, uint16_t port, InterfaceId interface)
117{
118 (void) interface;
119 otError err = OT_ERROR_NONE;
120 otSockAddr listenSockAddr;
121
122 memset(&socket, 0, sizeof(socket));
123 memset(&listenSockAddr, 0, sizeof(listenSockAddr));
124
125 listenSockAddr.mPort = port;
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400126 listenSockAddr.mAddress = address.ToIPv6();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500127
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400128 LockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500129 otUdpOpen(mOTInstance, &socket, handleUdpReceive, this);
130 otUdpBind(mOTInstance, &socket, &listenSockAddr, OT_NETIF_THREAD);
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400131 UnlockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500132
133 return chip::DeviceLayer::Internal::MapOpenThreadError(err);
134}
135
136CHIP_ERROR UDPEndPointImplOT::BindImpl(IPAddressType addressType, const IPAddress & addr, uint16_t port, InterfaceId interface)
137{
138
139 if (addressType != IPAddressType::kIPv6)
140 {
141 return INET_ERROR_WRONG_ADDRESS_TYPE;
142 }
143
144 ReturnErrorOnFailure(IPv6Bind(mSocket, addr, port, interface));
145 mBoundPort = port;
146 mBoundIntfId = interface;
147
148 return CHIP_NO_ERROR;
149}
150
151InterfaceId UDPEndPointImplOT::GetBoundInterface() const
152{
153 return mBoundIntfId;
154}
155
156uint16_t UDPEndPointImplOT::GetBoundPort() const
157{
158 return mBoundPort;
159}
160
161CHIP_ERROR UDPEndPointImplOT::ListenImpl()
162{
163 // Nothing to do. Callback was set upon Binding call.
164 return CHIP_NO_ERROR;
165}
166
167void UDPEndPointImplOT::HandleDataReceived(System::PacketBufferHandle && msg)
168{
169 if ((mState == State::kListening) && (OnMessageReceived != nullptr))
170 {
171 const IPPacketInfo * pktInfo = GetPacketInfo(msg);
172
173 if (pktInfo != nullptr)
174 {
175 const IPPacketInfo pktInfoCopy = *pktInfo; // copy the address info so that the app can free the
176 // PacketBuffer without affecting access to address info.
177
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500178 OnMessageReceived(this, std::move(msg), &pktInfoCopy);
179 }
180 else
181 {
182 if (OnReceiveError != nullptr)
183 {
184 OnReceiveError(this, CHIP_ERROR_INBOUND_MESSAGE_TOO_BIG, nullptr);
185 }
186 }
187 }
188}
189
Jean-Francois Penvenfa087ea2022-04-22 14:53:57 -0400190void UDPEndPointImplOT::SetNativeParams(void * params)
191{
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400192 if (params == nullptr)
193 {
194 ChipLogError(Inet, "FATAL!! No native parameters provided!!!!!");
195 VerifyOrDie(false);
196 }
197
198 OpenThreadEndpointInitParam * initParams = static_cast<OpenThreadEndpointInitParam *>(params);
199 mOTInstance = initParams->openThreadInstancePtr;
200 globalOtInstance = mOTInstance;
201
202 lockOpenThread = initParams->lockCb;
203 unlockOpenThread = initParams->unlockCb;
Jean-Francois Penvenfa087ea2022-04-22 14:53:57 -0400204}
205
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500206CHIP_ERROR UDPEndPointImplOT::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback)
207{
208 (void) aIPVersion;
209 (void) aLoopback;
210 // TODO
211 return CHIP_ERROR_NOT_IMPLEMENTED;
212}
213
214CHIP_ERROR UDPEndPointImplOT::BindInterfaceImpl(IPAddressType addressType, InterfaceId interfaceId)
215{
216 (void) addressType;
217 (void) interfaceId;
218 return CHIP_NO_ERROR;
219}
220
221CHIP_ERROR UDPEndPointImplOT::SendMsgImpl(const IPPacketInfo * aPktInfo, System::PacketBufferHandle && msg)
222{
223 otError error = OT_ERROR_NONE;
224 otMessage * message;
225 otMessageInfo messageInfo;
226
227 // For now the entire message must fit within a single buffer.
228 VerifyOrReturnError(!msg->HasChainedBuffer(), CHIP_ERROR_MESSAGE_TOO_LONG);
229
230 memset(&messageInfo, 0, sizeof(messageInfo));
231
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400232 messageInfo.mSockAddr = aPktInfo->SrcAddress.ToIPv6();
233 messageInfo.mPeerAddr = aPktInfo->DestAddress.ToIPv6();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500234 messageInfo.mPeerPort = aPktInfo->DestPort;
235
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400236 LockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500237 message = otUdpNewMessage(mOTInstance, NULL);
238 VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
239
240 error = otMessageAppend(message, msg->Start(), msg->DataLength());
241
242 if (error == OT_ERROR_NONE)
243 {
244 error = otUdpSend(mOTInstance, &mSocket, message, &messageInfo);
245 }
246
247exit:
248 if (error != OT_ERROR_NONE && message != NULL)
249 {
250 otMessageFree(message);
251 }
252
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400253 UnlockOpenThread();
254
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500255 return chip::DeviceLayer::Internal::MapOpenThreadError(error);
256}
257
258void UDPEndPointImplOT::CloseImpl()
259{
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400260 LockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500261 if (otUdpIsOpen(mOTInstance, &mSocket))
262 {
263 otUdpClose(mOTInstance, &mSocket);
Zang MingJief5eec6e2022-07-14 21:20:54 +0800264
265 // In case that there is a UDPEndPointImplOT::handleUdpReceive event
266 // pending in the event queue (SystemLayer::ScheduleLambda), we
267 // schedule a release call to the end of the queue, to ensure that the
268 // queued pointer to UDPEndPointImplOT is not dangling.
269 Retain();
270 CHIP_ERROR err = GetSystemLayer().ScheduleLambda([this] { Release(); });
271 if (err != CHIP_NO_ERROR)
272 {
273 ChipLogError(Inet, "Unable scedule lambda: %" CHIP_ERROR_FORMAT, err.Format());
274 // There is nothing we can do here, accept the chance of racing
275 Release();
276 }
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500277 }
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400278 UnlockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500279}
280
281void UDPEndPointImplOT::Free()
282{
283 Close();
284 Release();
285}
286
287CHIP_ERROR UDPEndPointImplOT::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join)
288{
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400289 const otIp6Address otAddress = aAddress.ToIPv6();
290 otError err;
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500291
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400292 LockOpenThread();
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500293 if (join)
294 {
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400295 err = otIp6SubscribeMulticastAddress(mOTInstance, &otAddress);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500296 }
297 else
298 {
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400299 err = otIp6UnsubscribeMulticastAddress(mOTInstance, &otAddress);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500300 }
Jean-Francois Penven9405c202022-05-03 15:37:44 -0400301
302 UnlockOpenThread();
303
304 return chip::DeviceLayer::Internal::MapOpenThreadError(err);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500305}
306
307IPPacketInfo * UDPEndPointImplOT::GetPacketInfo(const System::PacketBufferHandle & aBuffer)
308{
Kevin Schoedel7b3fb842022-06-07 20:30:00 -0400309 if (!aBuffer->EnsureReservedSize(kPacketInfoReservedSize))
310 {
311 return nullptr;
312 }
313
314 uintptr_t lStart = (uintptr_t) aBuffer->Start();
315 uintptr_t lPacketInfoStart = lStart - sizeof(IPPacketInfo);
316
317 // Align to a 4-byte boundary
318 return reinterpret_cast<IPPacketInfo *>(lPacketInfoStart & ~kPacketInfoAlignmentBytes);
Jean-Francois Penven1cbec522022-01-11 11:54:40 -0500319}
320
321} // namespace Inet
322} // namespace chip