/src/openweave-core/src/inet/InetLayer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2013-2017 Nest Labs, Inc. |
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 classes for abstracting access to and |
22 | | * interactions with a platform- and system-specific Internet |
23 | | * Protocol stack which, as of this implementation, may be either |
24 | | * BSD/POSIX Sockets or LwIP. |
25 | | * |
26 | | * Major abstractions provided are: |
27 | | * |
28 | | * * Timers |
29 | | * * Domain Name System (DNS) resolution |
30 | | * * TCP network transport |
31 | | * * UDP network transport |
32 | | * * Raw network transport |
33 | | * |
34 | | * For BSD/POSIX Sockets, event readiness notification is handled |
35 | | * via file descriptors and a traditional poll / select |
36 | | * implementation on the platform adaptation. |
37 | | * |
38 | | * For LwIP, event readiness notification is handle via events / |
39 | | * messages and platform- and system-specific hooks for the event |
40 | | * / message system. |
41 | | * |
42 | | */ |
43 | | |
44 | | #ifndef __STDC_LIMIT_MACROS |
45 | | #define __STDC_LIMIT_MACROS |
46 | | #endif |
47 | | |
48 | | #include <InetLayer/InetLayer.h> |
49 | | #include <InetLayer/InetFaultInjection.h> |
50 | | |
51 | | #include <SystemLayer/SystemTimer.h> |
52 | | |
53 | | #include <Weave/Support/CodeUtils.h> |
54 | | #include <Weave/Support/logging/WeaveLogging.h> |
55 | | |
56 | | #include <errno.h> |
57 | | #include <stddef.h> |
58 | | #include <stdint.h> |
59 | | #include <string.h> |
60 | | |
61 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
62 | | #include <lwip/sys.h> |
63 | | #include <lwip/netif.h> |
64 | | #else // !WEAVE_SYSTEM_CONFIG_USE_LWIP |
65 | | #include <unistd.h> |
66 | | #include <fcntl.h> |
67 | | #include <net/if.h> |
68 | | #ifdef __ANDROID__ |
69 | | #include <ifaddrs-android.h> |
70 | | #else |
71 | | #include <ifaddrs.h> |
72 | | #endif // __ANDROID__ |
73 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
74 | | |
75 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
76 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS |
77 | | |
78 | | // MARK: InetLayer platform- and system-specific functions for LwIP-native eventing. |
79 | | |
80 | | struct LwIPInetEvent |
81 | | { |
82 | | nl::Inet::InetEventType Type; |
83 | | nl::Inet::InetLayerBasis* Target; |
84 | | uintptr_t Arg; |
85 | | }; |
86 | | |
87 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS |
88 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
89 | | |
90 | | namespace nl { |
91 | | namespace Inet { |
92 | | |
93 | | void InetLayer::UpdateSnapshot(nl::Weave::System::Stats::Snapshot &aSnapshot) |
94 | 0 | { |
95 | 0 | #if INET_CONFIG_ENABLE_DNS_RESOLVER |
96 | 0 | DNSResolver::sPool.GetStatistics(aSnapshot.mResourcesInUse[nl::Weave::System::Stats::kInetLayer_NumDNSResolvers], |
97 | 0 | aSnapshot.mHighWatermarks[nl::Weave::System::Stats::kInetLayer_NumDNSResolvers]); |
98 | 0 | #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
99 | 0 | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
100 | 0 | TCPEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[nl::Weave::System::Stats::kInetLayer_NumTCPEps], |
101 | 0 | aSnapshot.mHighWatermarks[nl::Weave::System::Stats::kInetLayer_NumTCPEps]); |
102 | 0 | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
103 | 0 | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
104 | 0 | UDPEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[nl::Weave::System::Stats::kInetLayer_NumUDPEps], |
105 | 0 | aSnapshot.mHighWatermarks[nl::Weave::System::Stats::kInetLayer_NumUDPEps]); |
106 | 0 | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
107 | 0 | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
108 | 0 | RawEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[nl::Weave::System::Stats::kInetLayer_NumRawEps], |
109 | 0 | aSnapshot.mHighWatermarks[nl::Weave::System::Stats::kInetLayer_NumRawEps]); |
110 | 0 | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
111 | 0 | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
112 | 0 | TunEndPoint::sPool.GetStatistics(aSnapshot.mResourcesInUse[nl::Weave::System::Stats::kInetLayer_NumTunEps], |
113 | 0 | aSnapshot.mHighWatermarks[nl::Weave::System::Stats::kInetLayer_NumTunEps]); |
114 | 0 | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
115 | 0 | } |
116 | | |
117 | | /** |
118 | | * This is the InetLayer default constructor. |
119 | | * |
120 | | * It performs some basic data member initialization; however, since |
121 | | * InetLayer follows an explicit initializer design pattern, the InetLayer::Init |
122 | | * method must be called successfully prior to using the object. |
123 | | * |
124 | | */ |
125 | | InetLayer::InetLayer(void) |
126 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
127 | | : mImplicitSystemLayer() |
128 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
129 | 10 | { |
130 | 10 | State = kState_NotInitialized; |
131 | | |
132 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
133 | | if (!sInetEventHandlerDelegate.IsInitialized()) |
134 | | sInetEventHandlerDelegate.Init(HandleInetLayerEvent); |
135 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
136 | 10 | } |
137 | | |
138 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
139 | | Weave::System::LwIPEventHandlerDelegate InetLayer::sInetEventHandlerDelegate; |
140 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
141 | | |
142 | | #if INET_CONFIG_MAX_DROPPABLE_EVENTS && WEAVE_SYSTEM_CONFIG_USE_LWIP |
143 | | |
144 | | #if WEAVE_SYSTEM_CONFIG_NO_LOCKING |
145 | | |
146 | | INET_ERROR InetLayer::InitQueueLimiter(void) |
147 | | { |
148 | | mDroppableEvents = 0; |
149 | | return INET_NO_ERROR; |
150 | | } |
151 | | |
152 | | bool InetLayer::CanEnqueueDroppableEvent(void) |
153 | | { |
154 | | if (__sync_add_and_fetch(&mDroppableEvents, 1) <= INET_CONFIG_MAX_DROPPABLE_EVENTS) |
155 | | { |
156 | | return true; |
157 | | } |
158 | | else |
159 | | { |
160 | | __sync_add_and_fetch(&mDroppableEvents, -1); |
161 | | return false; |
162 | | } |
163 | | } |
164 | | |
165 | | void InetLayer::DroppableEventDequeued(void) |
166 | | { |
167 | | __sync_add_and_fetch(&mDroppableEvents, -1); |
168 | | } |
169 | | |
170 | | #elif WEAVE_SYSTEM_CONFIG_FREERTOS_LOCKING |
171 | | |
172 | | INET_ERROR InetLayer::InitQueueLimiter(void) |
173 | | { |
174 | | const unsigned portBASE_TYPE maximum = INET_CONFIG_MAX_DROPPABLE_EVENTS; |
175 | | const unsigned portBASE_TYPE initial = INET_CONFIG_MAX_DROPPABLE_EVENTS; |
176 | | |
177 | | #if (configSUPPORT_STATIC_ALLOCATION == 1) |
178 | | mDroppableEvents = xSemaphoreCreateCountingStatic(maximum, initial, &mDroppableEventsObj); |
179 | | #else |
180 | | mDroppableEvents = xSemaphoreCreateCounting(maximum, initial); |
181 | | #endif |
182 | | |
183 | | if (mDroppableEvents != NULL) |
184 | | return INET_NO_ERROR; |
185 | | else |
186 | | return INET_ERROR_NO_MEMORY; |
187 | | } |
188 | | |
189 | | bool InetLayer::CanEnqueueDroppableEvent(void) |
190 | | { |
191 | | if (xSemaphoreTake(mDroppableEvents, 0) != pdTRUE) |
192 | | { |
193 | | return false; |
194 | | } |
195 | | return true; |
196 | | } |
197 | | |
198 | | void InetLayer::DroppableEventDequeued(void) |
199 | | { |
200 | | xSemaphoreGive(mDroppableEvents); |
201 | | } |
202 | | |
203 | | #else // !WEAVE_SYSTEM_CONFIG_FREERTOS_LOCKING |
204 | | |
205 | | INET_ERROR InetLayer::InitQueueLimiter(void) |
206 | | { |
207 | | if (sem_init(&mDroppableEvents, 0, INET_CONFIG_MAX_DROPPABLE_EVENTS) != 0) |
208 | | { |
209 | | return Weave::System::MapErrorPOSIX(errno); |
210 | | } |
211 | | return INET_NO_ERROR; |
212 | | } |
213 | | |
214 | | bool InetLayer::CanEnqueueDroppableEvent(void) |
215 | | { |
216 | | // Striclty speaking, we should check for EAGAIN. But, other |
217 | | // errno values probably should signal that that we should drop |
218 | | // the packet: EINVAL means that the semaphore is not valid (we |
219 | | // failed initialization), and EINTR should probably also lead to |
220 | | // dropping a packet. |
221 | | |
222 | | if (sem_trywait(&mDroppableEvents) != 0) |
223 | | { |
224 | | return false; |
225 | | } |
226 | | return true; |
227 | | } |
228 | | |
229 | | void InetLayer::DroppableEventDequeued(void) |
230 | | { |
231 | | sem_post(&mDroppableEvents); |
232 | | } |
233 | | |
234 | | #endif // !WEAVE_SYSTEM_CONFIG_FREERTOS_LOCKING |
235 | | #endif // INET_CONFIG_MAX_DROPPABLE_EVENTS && WEAVE_SYSTEM_CONFIG_USE_LWIP |
236 | | |
237 | | /** |
238 | | * This is the InetLayer explicit initializer. This must be called |
239 | | * and complete successfully before the InetLayer may be used. |
240 | | * |
241 | | * The caller may provide an optional context argument which will be |
242 | | * passed back via any platform-specific hook functions. For |
243 | | * LwIP-based adaptations, this will typically be a pointer to the |
244 | | * event queue associated with the InetLayer instance. |
245 | | * |
246 | | * Platforms may choose to assert |
247 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS in their |
248 | | * platform-specific configuration header and enable the |
249 | | * Platform::InetLayer::WillInit and Platform::InetLayer::DidInit |
250 | | * hooks to effect platform-specific customizations or data extensions |
251 | | * to InetLayer. |
252 | | * |
253 | | * @param[in] aSystemLayer A required instance of the Weave System Layer |
254 | | * already successfully initialized. |
255 | | * |
256 | | * @param[in] aContext An optional context argument which will be passed |
257 | | * back to the caller via any platform-specific hook |
258 | | * functions. |
259 | | * |
260 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer is in an |
261 | | * incorrect state. |
262 | | * @retval #INET_ERROR_NO_MEMORY If the InetLayer runs out |
263 | | * of resource for this |
264 | | * request for a new timer. |
265 | | * @retval other Platform-specific errors indicating the reason for |
266 | | * initialization failure. |
267 | | * @retval #INET_NO_ERROR On success. |
268 | | * |
269 | | */ |
270 | | INET_ERROR InetLayer::Init(Weave::System::Layer& aSystemLayer, void *aContext) |
271 | 0 | { |
272 | 0 | INET_ERROR err = INET_NO_ERROR; |
273 | |
|
274 | 0 | RegisterInetLayerErrorFormatter(); |
275 | |
|
276 | 0 | if (State != kState_NotInitialized) |
277 | 0 | return INET_ERROR_INCORRECT_STATE; |
278 | | |
279 | | // Platform-specific initialization may elect to set this data |
280 | | // member. Ensure it is set to a sane default value before |
281 | | // invoking platform-specific initialization. |
282 | | |
283 | 0 | mPlatformData = NULL; |
284 | |
|
285 | 0 | Platform::InetLayer::WillInit(this, aContext); |
286 | 0 | SuccessOrExit(err); |
287 | | |
288 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
289 | | if (&aSystemLayer == &mImplicitSystemLayer) |
290 | | { |
291 | | err = mImplicitSystemLayer.Init(aContext); |
292 | | SuccessOrExit(err); |
293 | | } |
294 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
295 | | |
296 | 0 | mSystemLayer = &aSystemLayer; |
297 | 0 | mContext = aContext; |
298 | |
|
299 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
300 | | err = InitQueueLimiter(); |
301 | | SuccessOrExit(err); |
302 | | |
303 | | mSystemLayer->AddEventHandlerDelegate(sInetEventHandlerDelegate); |
304 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
305 | |
|
306 | 0 | State = kState_Initialized; |
307 | |
|
308 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
309 | 0 | #if INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
310 | |
|
311 | 0 | err = mAsyncDNSResolver.Init(this); |
312 | 0 | SuccessOrExit(err); |
313 | | |
314 | 0 | #endif // INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
315 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
316 | | |
317 | 0 | exit: |
318 | 0 | Platform::InetLayer::DidInit(this, mContext, err); |
319 | 0 | return err; |
320 | 0 | } |
321 | | |
322 | | /** |
323 | | * This is the InetLayer explicit deinitializer and should be called |
324 | | * prior to disposing of an instantiated InetLayer instance. |
325 | | * |
326 | | * Platforms may choose to assert |
327 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS in their |
328 | | * platform-specific configuration header and enable the |
329 | | * Platform::InetLayer::WillShutdown and |
330 | | * Platform::InetLayer::DidShutdown hooks to effect clean-up of |
331 | | * platform-specific customizations or data extensions to InetLayer. |
332 | | * |
333 | | * @return #INET_NO_ERROR on success; otherwise, a specific error indicating |
334 | | * the reason for shutdown failure. |
335 | | * |
336 | | */ |
337 | | INET_ERROR InetLayer::Shutdown(void) |
338 | 0 | { |
339 | 0 | INET_ERROR err; |
340 | |
|
341 | 0 | err = Platform::InetLayer::WillShutdown(this, mContext); |
342 | 0 | SuccessOrExit(err); |
343 | | |
344 | 0 | if (State == kState_Initialized) |
345 | 0 | { |
346 | 0 | #if INET_CONFIG_ENABLE_DNS_RESOLVER |
347 | | // Cancel all DNS resolution requests owned by this instance. |
348 | 0 | for (size_t i = 0; i < DNSResolver::sPool.Size(); i++) |
349 | 0 | { |
350 | 0 | DNSResolver* lResolver = DNSResolver::sPool.Get(*mSystemLayer, i); |
351 | 0 | if ((lResolver != NULL) && lResolver->IsCreatedByInetLayer(*this)) |
352 | 0 | { |
353 | 0 | lResolver->Cancel(); |
354 | 0 | } |
355 | 0 | } |
356 | |
|
357 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
358 | |
|
359 | 0 | err = mAsyncDNSResolver.Shutdown(); |
360 | |
|
361 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
362 | 0 | #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
363 | |
|
364 | 0 | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
365 | | // Close all raw endpoints owned by this Inet layer instance. |
366 | 0 | for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) |
367 | 0 | { |
368 | 0 | RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); |
369 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
370 | 0 | { |
371 | 0 | lEndPoint->Close(); |
372 | 0 | } |
373 | 0 | } |
374 | 0 | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
375 | |
|
376 | 0 | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
377 | | // Abort all TCP endpoints owned by this instance. |
378 | 0 | for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) |
379 | 0 | { |
380 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); |
381 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
382 | 0 | { |
383 | 0 | lEndPoint->Abort(); |
384 | 0 | } |
385 | 0 | } |
386 | 0 | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
387 | |
|
388 | 0 | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
389 | | // Close all UDP endpoints owned by this instance. |
390 | 0 | for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) |
391 | 0 | { |
392 | 0 | UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); |
393 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
394 | 0 | { |
395 | 0 | lEndPoint->Close(); |
396 | 0 | } |
397 | 0 | } |
398 | 0 | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
399 | |
|
400 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
401 | | if (mSystemLayer == &mImplicitSystemLayer) |
402 | | { |
403 | | err = mImplicitSystemLayer.Shutdown(); |
404 | | SuccessOrExit(err); |
405 | | } |
406 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
407 | |
|
408 | 0 | } |
409 | |
|
410 | 0 | State = kState_NotInitialized; |
411 | |
|
412 | 0 | exit: |
413 | 0 | Platform::InetLayer::DidShutdown(this, mContext, err); |
414 | |
|
415 | 0 | return err; |
416 | 0 | } |
417 | | |
418 | | /** |
419 | | * This returns any client-specific platform data assigned to the |
420 | | * instance, if it has been previously set. |
421 | | * |
422 | | * @return Client-specific platform data, if is has been previously set; |
423 | | * otherwise, NULL. |
424 | | * |
425 | | */ |
426 | | void *InetLayer::GetPlatformData(void) |
427 | 0 | { |
428 | 0 | return mPlatformData; |
429 | 0 | } |
430 | | |
431 | | /** |
432 | | * This sets the specified client-specific platform data to the |
433 | | * instance for later retrieval by the client platform. |
434 | | * |
435 | | * @param[in] aPlatformData The client-specific platform data to set. |
436 | | * |
437 | | */ |
438 | | void InetLayer::SetPlatformData(void *aPlatformData) |
439 | 0 | { |
440 | 0 | mPlatformData = aPlatformData; |
441 | 0 | } |
442 | | |
443 | | #if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
444 | | bool InetLayer::IsIdleTimerRunning(void) |
445 | 0 | { |
446 | 0 | bool timerRunning = false; |
447 | | |
448 | | // see if there are any TCP connections with the idle timer check in use. |
449 | 0 | for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) |
450 | 0 | { |
451 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); |
452 | |
|
453 | 0 | if ((lEndPoint != NULL) && (lEndPoint->mIdleTimeout != 0)) |
454 | 0 | { |
455 | 0 | timerRunning = true; |
456 | 0 | break; |
457 | 0 | } |
458 | 0 | } |
459 | |
|
460 | 0 | return timerRunning; |
461 | 0 | } |
462 | | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
463 | | |
464 | | /** |
465 | | * Get the link local IPv6 address for a specified link or interface. |
466 | | * |
467 | | * @param[in] link The interface for which the link local IPv6 |
468 | | * address is being sought. |
469 | | * |
470 | | * @param[out] llAddr The link local IPv6 address for the link. |
471 | | * |
472 | | * @retval #INET_ERROR_NOT_IMPLEMENTED If IPv6 is not supported. |
473 | | * @retval #INET_ERROR_BAD_ARGS If the link local address |
474 | | * is NULL. |
475 | | * @retval #INET_ERROR_ADDRESS_NOT_FOUND If the link does not have |
476 | | * any address configured. |
477 | | * @retval #INET_NO_ERROR On success. |
478 | | * |
479 | | */ |
480 | | INET_ERROR InetLayer::GetLinkLocalAddr(InterfaceId link, IPAddress *llAddr) |
481 | 0 | { |
482 | 0 | INET_ERROR err = INET_NO_ERROR; |
483 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
484 | | #if !LWIP_IPV6 |
485 | | err = INET_ERROR_NOT_IMPLEMENTED; |
486 | | goto out; |
487 | | #endif //!LWIP_IPV6 |
488 | | #endif //WEAVE_SYSTEM_CONFIG_USE_LWIP |
489 | |
|
490 | 0 | if ( llAddr == NULL ) |
491 | 0 | { |
492 | 0 | err = INET_ERROR_BAD_ARGS; |
493 | 0 | goto out; |
494 | 0 | } |
495 | | |
496 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
497 | | for (struct netif *intf = netif_list; intf != NULL; intf = intf->next) |
498 | | { |
499 | | if ( (link != NULL) && (link != intf) ) continue; |
500 | | int j; for (j = 0; j < LWIP_IPV6_NUM_ADDRESSES; ++j) |
501 | | { |
502 | | if (ip6_addr_isvalid(netif_ip6_addr_state(intf, j)) && ip6_addr_islinklocal(netif_ip6_addr(intf, j))) |
503 | | { |
504 | | (*llAddr) = IPAddress::FromIPv6(*netif_ip6_addr(intf, j)); |
505 | | goto out; |
506 | | } |
507 | | } |
508 | | if (link != NULL) { |
509 | | err = INET_ERROR_ADDRESS_NOT_FOUND; |
510 | | break; |
511 | | } |
512 | | } |
513 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
514 | | |
515 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
516 | 0 | struct ifaddrs *ifaddr; |
517 | 0 | int rv; |
518 | 0 | rv = getifaddrs(&ifaddr); |
519 | 0 | if (rv != -1) |
520 | 0 | { |
521 | 0 | struct ifaddrs*ifaddr_iter = ifaddr; |
522 | 0 | while (ifaddr_iter != NULL) |
523 | 0 | { |
524 | |
|
525 | 0 | if (ifaddr_iter->ifa_addr != NULL) |
526 | 0 | { |
527 | 0 | if ((ifaddr_iter->ifa_addr->sa_family == AF_INET6) && |
528 | 0 | ((link == INET_NULL_INTERFACEID) || (if_nametoindex(ifaddr_iter->ifa_name) == link))) |
529 | 0 | { |
530 | 0 | struct in6_addr *sin6_addr = &((struct sockaddr_in6*)ifaddr_iter->ifa_addr)->sin6_addr; |
531 | 0 | if (sin6_addr->s6_addr[0] == 0xfe && (sin6_addr->s6_addr[1] & 0xc0) == 0x80)//Link Local Address |
532 | 0 | { |
533 | 0 | (*llAddr) = IPAddress::FromIPv6(((struct sockaddr_in6*)ifaddr_iter->ifa_addr)->sin6_addr); |
534 | 0 | break; |
535 | 0 | } |
536 | 0 | } |
537 | 0 | } |
538 | 0 | ifaddr_iter = ifaddr_iter->ifa_next; |
539 | 0 | } |
540 | 0 | freeifaddrs(ifaddr); |
541 | 0 | } |
542 | 0 | else |
543 | 0 | { |
544 | 0 | err = INET_ERROR_ADDRESS_NOT_FOUND; |
545 | 0 | } |
546 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
547 | |
|
548 | 0 | out: |
549 | 0 | return err; |
550 | 0 | } |
551 | | |
552 | | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
553 | | /** |
554 | | * Creates a new RawEndPoint object for a specific IP version and protocol. |
555 | | * |
556 | | * @note |
557 | | * This function gets a free RawEndPoint object from a pre-allocated pool |
558 | | * and also calls the explicit initializer on the new object. |
559 | | * |
560 | | * @param[in] ipVer IPv4 or IPv6. |
561 | | * |
562 | | * @param[in] ipProto A protocol within the IP family (e.g., ICMPv4 or ICMPv6). |
563 | | * |
564 | | * @param[inout] retEndPoint A pointer to a pointer of the RawEndPoint object that is |
565 | | * a return parameter upon completion of the object creation. |
566 | | * *retEndPoint is NULL if creation fails. |
567 | | * |
568 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. |
569 | | * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer RawEndPoint pool is full and no new |
570 | | * endpoints can be created. |
571 | | * @retval #INET_NO_ERROR On success. |
572 | | * |
573 | | */ |
574 | | INET_ERROR InetLayer::NewRawEndPoint(IPVersion ipVer, IPProtocol ipProto, RawEndPoint **retEndPoint) |
575 | 0 | { |
576 | 0 | INET_ERROR err = INET_NO_ERROR; |
577 | 0 | *retEndPoint = NULL; |
578 | |
|
579 | 0 | VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); |
580 | | |
581 | 0 | *retEndPoint = RawEndPoint::sPool.TryCreate(*mSystemLayer); |
582 | 0 | if (*retEndPoint != NULL) |
583 | 0 | { |
584 | 0 | (*retEndPoint)->nl::Inet::RawEndPoint::Init(this, ipVer, ipProto); |
585 | 0 | SYSTEM_STATS_INCREMENT(nl::Weave::System::Stats::kInetLayer_NumRawEps); |
586 | 0 | } |
587 | 0 | else |
588 | 0 | { |
589 | 0 | WeaveLogError(Inet, "%s endpoint pool FULL", "Raw"); |
590 | 0 | err = INET_ERROR_NO_ENDPOINTS; |
591 | 0 | } |
592 | |
|
593 | 0 | exit: |
594 | 0 | return err; |
595 | 0 | } |
596 | | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
597 | | |
598 | | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
599 | | /** |
600 | | * Creates a new TCPEndPoint object. |
601 | | * |
602 | | * @note |
603 | | * This function gets a free TCPEndPoint object from a pre-allocated pool |
604 | | * and also calls the explicit initializer on the new object. |
605 | | * |
606 | | * @param[inout] retEndPoint A pointer to a pointer of the TCPEndPoint object that is |
607 | | * a return parameter upon completion of the object creation. |
608 | | * *retEndPoint is NULL if creation fails. |
609 | | * |
610 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. |
611 | | * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer TCPEndPoint pool is full and no new |
612 | | * endpoints can be created. |
613 | | * @retval #INET_NO_ERROR On success. |
614 | | * |
615 | | */ |
616 | | INET_ERROR InetLayer::NewTCPEndPoint(TCPEndPoint **retEndPoint) |
617 | 0 | { |
618 | 0 | INET_ERROR err = INET_NO_ERROR; |
619 | 0 | *retEndPoint = NULL; |
620 | |
|
621 | 0 | VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); |
622 | | |
623 | 0 | *retEndPoint = TCPEndPoint::sPool.TryCreate(*mSystemLayer); |
624 | 0 | if (*retEndPoint != NULL) |
625 | 0 | { |
626 | 0 | (*retEndPoint)->Init(this); |
627 | 0 | SYSTEM_STATS_INCREMENT(nl::Weave::System::Stats::kInetLayer_NumTCPEps); |
628 | 0 | } |
629 | 0 | else |
630 | 0 | { |
631 | 0 | WeaveLogError(Inet, "%s endpoint pool FULL", "TCP"); |
632 | 0 | err = INET_ERROR_NO_ENDPOINTS; |
633 | 0 | } |
634 | |
|
635 | 0 | exit: |
636 | 0 | return err; |
637 | 0 | } |
638 | | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
639 | | |
640 | | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
641 | | /** |
642 | | * Creates a new UDPEndPoint object. |
643 | | * |
644 | | * @note |
645 | | * This function gets a free UDPEndPoint object from a pre-allocated pool |
646 | | * and also calls the explicit initializer on the new object. |
647 | | * |
648 | | * @param[inout] retEndPoint A pointer to a pointer of the UDPEndPoint object that is |
649 | | * a return parameter upon completion of the object creation. |
650 | | * *retEndPoint is NULL if creation fails. |
651 | | * |
652 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. |
653 | | * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer UDPEndPoint pool is full and no new |
654 | | * endpoints can be created. |
655 | | * @retval #INET_NO_ERROR On success. |
656 | | * |
657 | | */ |
658 | | INET_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint **retEndPoint) |
659 | 0 | { |
660 | 0 | INET_ERROR err = INET_NO_ERROR; |
661 | 0 | *retEndPoint = NULL; |
662 | |
|
663 | 0 | VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); |
664 | | |
665 | 0 | *retEndPoint = UDPEndPoint::sPool.TryCreate(*mSystemLayer); |
666 | 0 | if (*retEndPoint != NULL) |
667 | 0 | { |
668 | 0 | (*retEndPoint)->Init(this); |
669 | 0 | SYSTEM_STATS_INCREMENT(nl::Weave::System::Stats::kInetLayer_NumUDPEps); |
670 | 0 | } |
671 | 0 | else |
672 | 0 | { |
673 | 0 | WeaveLogError(Inet, "%s endpoint pool FULL", "UDP"); |
674 | 0 | err = INET_ERROR_NO_ENDPOINTS; |
675 | 0 | } |
676 | |
|
677 | 0 | exit: |
678 | 0 | return err; |
679 | 0 | } |
680 | | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
681 | | |
682 | | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
683 | | /** |
684 | | * Creates a new TunEndPoint object. |
685 | | * |
686 | | * @note |
687 | | * This function gets a free TunEndPoint object from a pre-allocated pool |
688 | | * and also calls the explicit initializer on the new object. |
689 | | * |
690 | | * @param[inout] retEndPoint A pointer to a pointer of the TunEndPoint object that is |
691 | | * a return parameter upon completion of the object creation. |
692 | | * *retEndPoint is NULL if creation fails. |
693 | | * |
694 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. |
695 | | * @retval #INET_ERROR_NO_ENDPOINTS If the InetLayer TunEndPoint pool is full and no new |
696 | | * ones can be created. |
697 | | * @retval #INET_NO_ERROR On success. |
698 | | * |
699 | | */ |
700 | | INET_ERROR InetLayer::NewTunEndPoint(TunEndPoint **retEndPoint) |
701 | 0 | { |
702 | 0 | INET_ERROR err = INET_NO_ERROR; |
703 | 0 | *retEndPoint = NULL; |
704 | |
|
705 | 0 | VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); |
706 | | |
707 | 0 | *retEndPoint = TunEndPoint::sPool.TryCreate(*mSystemLayer); |
708 | 0 | if (*retEndPoint != NULL) |
709 | 0 | { |
710 | 0 | (*retEndPoint)->Init(this); |
711 | 0 | SYSTEM_STATS_INCREMENT(nl::Weave::System::Stats::kInetLayer_NumTunEps); |
712 | 0 | } |
713 | 0 | else |
714 | 0 | { |
715 | 0 | WeaveLogError(Inet, "%s endpoint pool FULL", "Tun"); |
716 | 0 | err = INET_ERROR_NO_ENDPOINTS; |
717 | 0 | } |
718 | |
|
719 | 0 | exit: |
720 | 0 | return err; |
721 | 0 | } |
722 | | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
723 | | |
724 | | #if INET_CONFIG_ENABLE_DNS_RESOLVER |
725 | | /** |
726 | | * Perform an IP address resolution of a specified hostname. |
727 | | * |
728 | | * @note |
729 | | * This is an asynchronous operation and the result will be communicated back |
730 | | * via the OnComplete() callback. |
731 | | * |
732 | | * @param[in] hostName A pointer to a NULL-terminated C string representing |
733 | | * the host name to be queried. |
734 | | * |
735 | | * @param[in] maxAddrs The maximum number of addresses to store in the DNS |
736 | | * table. |
737 | | * |
738 | | * @param[in] addrArray A pointer to the DNS table. |
739 | | * |
740 | | * @param[in] onComplete A pointer to the callback function when a DNS |
741 | | * request is complete. |
742 | | * |
743 | | * @param[in] appState A pointer to the application state to be passed to |
744 | | * onComplete when a DNS request is complete. |
745 | | * |
746 | | * @retval #INET_NO_ERROR if a DNS request is handled |
747 | | * successfully. |
748 | | * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool |
749 | | * is full. |
750 | | * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too |
751 | | * long. |
752 | | * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be |
753 | | * resolved to an address. |
754 | | * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a |
755 | | * temporary failure indication; |
756 | | * try again later. |
757 | | * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an |
758 | | * unrecoverable error. |
759 | | * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on |
760 | | * the underlying platform. |
761 | | * @retval other POSIX network or OS error returned by the underlying DNS |
762 | | * resolver implementation. |
763 | | * |
764 | | */ |
765 | | INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint8_t maxAddrs, |
766 | | IPAddress *addrArray, |
767 | | DNSResolveCompleteFunct onComplete, void *appState) |
768 | 0 | { |
769 | 0 | return ResolveHostAddress(hostName, strlen(hostName), maxAddrs, addrArray, onComplete, appState); |
770 | 0 | } |
771 | | |
772 | | /** |
773 | | * Perform an IP address resolution of a specified hostname. |
774 | | * |
775 | | * @param[in] hostName A pointer to a non NULL-terminated C string representing the host name |
776 | | * to be queried. |
777 | | * |
778 | | * @param[in] hostNameLen The string length of host name. |
779 | | * |
780 | | * @param[in] maxAddrs The maximum number of addresses to store in the DNS |
781 | | * table. |
782 | | * |
783 | | * @param[in] addrArray A pointer to the DNS table. |
784 | | * |
785 | | * @param[in] onComplete A pointer to the callback function when a DNS |
786 | | * request is complete. |
787 | | * |
788 | | * @param[in] appState A pointer to the application state to be passed to |
789 | | * onComplete when a DNS request is complete. |
790 | | * |
791 | | * @retval #INET_NO_ERROR if a DNS request is handled |
792 | | * successfully. |
793 | | * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool |
794 | | * is full. |
795 | | * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too |
796 | | * long. |
797 | | * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be |
798 | | * resolved to an address. |
799 | | * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a |
800 | | * temporary failure indication; |
801 | | * try again later. |
802 | | * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an |
803 | | * unrecoverable error. |
804 | | * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on |
805 | | * the underlying platform. |
806 | | * @retval other POSIX network or OS error returned by the underlying DNS |
807 | | * resolver implementation. |
808 | | * |
809 | | */ |
810 | | INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint16_t hostNameLen, |
811 | | uint8_t maxAddrs, IPAddress *addrArray, |
812 | | DNSResolveCompleteFunct onComplete, void *appState) |
813 | 0 | { |
814 | 0 | return ResolveHostAddress(hostName, hostNameLen, kDNSOption_Default, maxAddrs, addrArray, onComplete, appState); |
815 | 0 | } |
816 | | |
817 | | /** |
818 | | * Perform an IP address resolution of a specified hostname. |
819 | | * |
820 | | * @param[in] hostName A pointer to a non NULL-terminated C string representing the host name |
821 | | * to be queried. |
822 | | * |
823 | | * @param[in] hostNameLen The string length of host name. |
824 | | * |
825 | | * @param[in] options An integer value controlling how host name resolution is performed. |
826 | | * |
827 | | * Value should be one of the address family values from the |
828 | | * #DNSOptions enumeration: |
829 | | * |
830 | | * #kDNSOption_AddrFamily_Any |
831 | | * #kDNSOption_AddrFamily_IPv4Only |
832 | | * #kDNSOption_AddrFamily_IPv6Only |
833 | | * #kDNSOption_AddrFamily_IPv4Preferred |
834 | | * #kDNSOption_AddrFamily_IPv6Preferred |
835 | | * |
836 | | * @param[in] maxAddrs The maximum number of addresses to store in the DNS |
837 | | * table. |
838 | | * |
839 | | * @param[in] addrArray A pointer to the DNS table. |
840 | | * |
841 | | * @param[in] onComplete A pointer to the callback function when a DNS |
842 | | * request is complete. |
843 | | * |
844 | | * @param[in] appState A pointer to the application state to be passed to |
845 | | * onComplete when a DNS request is complete. |
846 | | * |
847 | | * @retval #INET_NO_ERROR if a DNS request is handled |
848 | | * successfully. |
849 | | * @retval #INET_ERROR_NO_MEMORY if the Inet layer resolver pool |
850 | | * is full. |
851 | | * @retval #INET_ERROR_HOST_NAME_TOO_LONG if a requested host name is too |
852 | | * long. |
853 | | * @retval #INET_ERROR_HOST_NOT_FOUND if a request host name could not be |
854 | | * resolved to an address. |
855 | | * @retval #INET_ERROR_DNS_TRY_AGAIN if a name server returned a |
856 | | * temporary failure indication; |
857 | | * try again later. |
858 | | * @retval #INET_ERROR_DNS_NO_RECOVERY if a name server returned an |
859 | | * unrecoverable error. |
860 | | * @retval #INET_ERROR_NOT_IMPLEMENTED if DNS resolution is not enabled on |
861 | | * the underlying platform. |
862 | | * @retval other POSIX network or OS error returned by the underlying DNS |
863 | | * resolver implementation. |
864 | | * |
865 | | */ |
866 | | INET_ERROR InetLayer::ResolveHostAddress(const char *hostName, uint16_t hostNameLen, |
867 | | uint8_t options, |
868 | | uint8_t maxAddrs, IPAddress *addrArray, |
869 | | DNSResolveCompleteFunct onComplete, void *appState) |
870 | 0 | { |
871 | 0 | INET_ERROR err = INET_NO_ERROR; |
872 | 0 | DNSResolver *resolver = NULL; |
873 | |
|
874 | 0 | VerifyOrExit(State == kState_Initialized, err = INET_ERROR_INCORRECT_STATE); |
875 | | |
876 | 0 | INET_FAULT_INJECT(FaultInjection::kFault_DNSResolverNew, return INET_ERROR_NO_MEMORY); |
877 | | |
878 | | // Store context information and set the resolver state. |
879 | 0 | VerifyOrExit(hostNameLen <= NL_DNS_HOSTNAME_MAX_LEN, err = INET_ERROR_HOST_NAME_TOO_LONG); |
880 | 0 | VerifyOrExit(maxAddrs > 0, err = INET_ERROR_NO_MEMORY); |
881 | | |
882 | 0 | resolver = DNSResolver::sPool.TryCreate(*mSystemLayer); |
883 | 0 | if (resolver != NULL) |
884 | 0 | { |
885 | 0 | resolver->InitInetLayerBasis(*this); |
886 | 0 | } |
887 | 0 | else |
888 | 0 | { |
889 | 0 | WeaveLogError(Inet, "%s resolver pool FULL", "DNS"); |
890 | 0 | ExitNow(err = INET_ERROR_NO_MEMORY); |
891 | 0 | } |
892 | | |
893 | | // Short-circuit full address resolution if the supplied host name is a text-form |
894 | | // IP address... |
895 | 0 | if (IPAddress::FromString(hostName, hostNameLen, *addrArray)) |
896 | 0 | { |
897 | 0 | uint8_t addrTypeOption = (options & kDNSOption_AddrFamily_Mask); |
898 | 0 | IPAddressType addrType = addrArray->Type(); |
899 | |
|
900 | 0 | if ((addrTypeOption == kDNSOption_AddrFamily_IPv6Only && addrType != kIPAddressType_IPv6) |
901 | 0 | #if INET_CONFIG_ENABLE_IPV4 |
902 | 0 | || (addrTypeOption == kDNSOption_AddrFamily_IPv4Only && addrType != kIPAddressType_IPv4) |
903 | 0 | #endif |
904 | 0 | ) |
905 | 0 | { |
906 | 0 | err = INET_ERROR_INCOMPATIBLE_IP_ADDRESS_TYPE; |
907 | 0 | } |
908 | |
|
909 | 0 | if (onComplete) |
910 | 0 | { |
911 | 0 | onComplete(appState, err, (err == INET_NO_ERROR) ? 1 : 0, addrArray); |
912 | 0 | } |
913 | |
|
914 | 0 | resolver->Release(); |
915 | 0 | resolver = NULL; |
916 | |
|
917 | 0 | ExitNow(err = INET_NO_ERROR); |
918 | 0 | } |
919 | | |
920 | | // After this point, the resolver will be released by: |
921 | | // - mAsyncDNSResolver (in case of ASYNC_DNS_SOCKETS) |
922 | | // - resolver->Resolve() (in case of synchronous resolving) |
923 | | // - the event handlers (in case of LwIP) |
924 | | |
925 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
926 | | |
927 | 0 | err = mAsyncDNSResolver.PrepareDNSResolver(*resolver, hostName, hostNameLen, options, |
928 | 0 | maxAddrs, addrArray, onComplete, appState); |
929 | 0 | SuccessOrExit(err); |
930 | | |
931 | 0 | mAsyncDNSResolver.EnqueueRequest(*resolver); |
932 | |
|
933 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
934 | |
|
935 | | #if !INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
936 | | err = resolver->Resolve(hostName, hostNameLen, options, maxAddrs, addrArray, onComplete, appState); |
937 | | #endif // !INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
938 | 0 | exit: |
939 | |
|
940 | 0 | return err; |
941 | 0 | } |
942 | | |
943 | | /** |
944 | | * Cancel any outstanding DNS query (for a matching completion callback and |
945 | | * application state) that may still be active. |
946 | | * |
947 | | * @note |
948 | | * This situation can arise if the application initiates a connection |
949 | | * to a peer using a hostname and then aborts/closes the connection |
950 | | * before the hostname resolution completes. |
951 | | * |
952 | | * @param[in] onComplete A pointer to the callback function when a DNS |
953 | | * request is complete. |
954 | | * |
955 | | * @param[in] appState A pointer to an application state object to be passed |
956 | | * to the callback function as argument. |
957 | | * |
958 | | */ |
959 | | void InetLayer::CancelResolveHostAddress(DNSResolveCompleteFunct onComplete, void *appState) |
960 | 0 | { |
961 | 0 | if (State != kState_Initialized) |
962 | 0 | return; |
963 | | |
964 | 0 | for (size_t i = 0; i < DNSResolver::sPool.Size(); i++) |
965 | 0 | { |
966 | 0 | DNSResolver* lResolver = DNSResolver::sPool.Get(*mSystemLayer, i); |
967 | |
|
968 | 0 | if (lResolver == NULL) |
969 | 0 | { |
970 | 0 | continue; |
971 | 0 | } |
972 | | |
973 | 0 | if (!lResolver->IsCreatedByInetLayer(*this)) |
974 | 0 | { |
975 | 0 | continue; |
976 | 0 | } |
977 | | |
978 | 0 | if (lResolver->OnComplete != onComplete) |
979 | 0 | { |
980 | 0 | continue; |
981 | 0 | } |
982 | | |
983 | 0 | if (lResolver->AppState != appState) |
984 | 0 | { |
985 | 0 | continue; |
986 | 0 | } |
987 | | |
988 | 0 | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
989 | 0 | if (lResolver->mState == DNSResolver::kState_Canceled) |
990 | 0 | { |
991 | 0 | continue; |
992 | 0 | } |
993 | 0 | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS |
994 | | |
995 | 0 | lResolver->Cancel(); |
996 | 0 | break; |
997 | 0 | } |
998 | 0 | } |
999 | | |
1000 | | #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
1001 | | |
1002 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1003 | | static void SystemTimerComplete(Weave::System::Layer* aLayer, void* aAppState, Weave::System::Error aError) |
1004 | | { |
1005 | | Weave::System::Timer& lTimer = *reinterpret_cast<Weave::System::Timer*>(aAppState); |
1006 | | InetLayer& lInetLayer = *lTimer.InetLayer(); |
1007 | | InetLayer::TimerCompleteFunct lComplete = reinterpret_cast<InetLayer::TimerCompleteFunct>(lTimer.OnCompleteInetLayer()); |
1008 | | void* lAppState = lTimer.AppStateInetLayer(); |
1009 | | |
1010 | | lComplete(&lInetLayer, lAppState, static_cast<INET_ERROR>(aError)); |
1011 | | } |
1012 | | |
1013 | | /** |
1014 | | * @brief |
1015 | | * This method registers a one-shot timer(to fire at a specified offset relative to the time |
1016 | | * of registration) with the underlying timer mechanism, through this InetLayer instance. |
1017 | | * |
1018 | | * @note |
1019 | | * Each InetLayer instance could have its own set of timers. This might not be |
1020 | | * significant to applications, as each application usually works with one singleton |
1021 | | * InetLayer instance. |
1022 | | * |
1023 | | * @param[in] aMilliseconds Number of milliseconds before this timer should fire. |
1024 | | * |
1025 | | * @param[in] aComplete A pointer to a callback function to be called when this |
1026 | | * timer fires. |
1027 | | * |
1028 | | * @param[in] aAppState A pointer to an application state object to be passed |
1029 | | * to the callback function as argument. |
1030 | | * |
1031 | | * @retval #INET_ERROR_INCORRECT_STATE If the InetLayer instance is not initialized. |
1032 | | * @retval #INET_ERROR_NO_MEMORY If the InetLayer runs out of resource for this |
1033 | | * request for a new timer. |
1034 | | * @retval #INET_NO_ERROR On success. |
1035 | | * |
1036 | | */ |
1037 | | INET_ERROR InetLayer::StartTimer(uint32_t aMilliseconds, TimerCompleteFunct aComplete, void* aAppState) |
1038 | | { |
1039 | | INET_ERROR lReturn; |
1040 | | |
1041 | | if (State != kState_Initialized) |
1042 | | { |
1043 | | return INET_ERROR_INCORRECT_STATE; |
1044 | | } |
1045 | | |
1046 | | Weave::System::Timer* lTimer; |
1047 | | |
1048 | | lReturn = mSystemLayer->NewTimer(lTimer); |
1049 | | SuccessOrExit(lReturn); |
1050 | | |
1051 | | lTimer->AttachInetLayer(*this, reinterpret_cast<void*>(aComplete), aAppState); |
1052 | | |
1053 | | lReturn = lTimer->Start(aMilliseconds, SystemTimerComplete, lTimer); |
1054 | | |
1055 | | if (lReturn != WEAVE_SYSTEM_NO_ERROR) |
1056 | | { |
1057 | | lTimer->Cancel(); |
1058 | | } |
1059 | | |
1060 | | exit: |
1061 | | switch (lReturn) |
1062 | | { |
1063 | | case WEAVE_SYSTEM_ERROR_NO_MEMORY: lReturn = INET_ERROR_NO_MEMORY; break; |
1064 | | case WEAVE_SYSTEM_NO_ERROR: lReturn = INET_NO_ERROR; break; |
1065 | | } |
1066 | | |
1067 | | return lReturn; |
1068 | | } |
1069 | | |
1070 | | /** |
1071 | | * @brief |
1072 | | * This method cancels an one-shot timer, started earlier through @p StartTimer(). |
1073 | | * |
1074 | | * @note |
1075 | | * The cancellation could fail silently in two different ways. If the timer |
1076 | | * specified by the combination of the callback function and application state object |
1077 | | * couldn't be found, cancellation could fail. If the timer has fired, but not yet |
1078 | | * removed from memory, cancellation could also fail. |
1079 | | * |
1080 | | * @param[in] aComplete A pointer to the callback function used in calling @p StartTimer(). |
1081 | | * @param[in] aAppState A pointer to the application state object used in calling |
1082 | | * @p StartTimer(). |
1083 | | * |
1084 | | */ |
1085 | | void InetLayer::CancelTimer(TimerCompleteFunct aComplete, void* aAppState) |
1086 | | { |
1087 | | if (State == kState_Initialized) |
1088 | | { |
1089 | | mSystemLayer->CancelAllMatchingInetTimers(*this, reinterpret_cast<void*>(aComplete), aAppState); |
1090 | | } |
1091 | | } |
1092 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1093 | | |
1094 | | /** |
1095 | | * Get the interface identifier for the specified IP address. If the |
1096 | | * interface identifier cannot be derived it is set to the |
1097 | | * #INET_NULL_INTERFACEID. |
1098 | | * |
1099 | | * @note |
1100 | | * This function fetches the first interface (from the configured list |
1101 | | * of interfaces) that matches the specified IP address. |
1102 | | * |
1103 | | * @param[in] addr A reference to the IPAddress object. |
1104 | | * |
1105 | | * @param[out] intfId A reference to the InterfaceId object. |
1106 | | * |
1107 | | * @return #INET_NO_ERROR unconditionally. |
1108 | | * |
1109 | | */ |
1110 | | INET_ERROR InetLayer::GetInterfaceFromAddr(const IPAddress& addr, InterfaceId& intfId) |
1111 | 0 | { |
1112 | 0 | InterfaceAddressIterator addrIter; |
1113 | |
|
1114 | 0 | for (; addrIter.HasCurrent(); addrIter.Next()) |
1115 | 0 | { |
1116 | 0 | IPAddress curAddr = addrIter.GetAddress(); |
1117 | 0 | if (addr == curAddr) |
1118 | 0 | { |
1119 | 0 | intfId = addrIter.GetInterface(); |
1120 | 0 | return INET_NO_ERROR; |
1121 | 0 | } |
1122 | 0 | } |
1123 | | |
1124 | 0 | intfId = INET_NULL_INTERFACEID; |
1125 | |
|
1126 | 0 | return INET_NO_ERROR; |
1127 | 0 | } |
1128 | | |
1129 | | /** |
1130 | | * Check if there is a prefix match between the specified IPv6 address and any of |
1131 | | * the locally configured IPv6 addresses. |
1132 | | * |
1133 | | * @param[in] addr The IPv6 address to check for the prefix-match. |
1134 | | * |
1135 | | * @return true if a successful match is found, otherwise false. |
1136 | | * |
1137 | | */ |
1138 | | bool InetLayer::MatchLocalIPv6Subnet(const IPAddress& addr) |
1139 | 0 | { |
1140 | 0 | if (addr.IsIPv6LinkLocal()) |
1141 | 0 | return true; |
1142 | | |
1143 | 0 | InterfaceAddressIterator ifAddrIter; |
1144 | 0 | for ( ; ifAddrIter.HasCurrent(); ifAddrIter.Next()) |
1145 | 0 | { |
1146 | 0 | IPPrefix addrPrefix; |
1147 | 0 | addrPrefix.IPAddr = ifAddrIter.GetAddress(); |
1148 | 0 | #if INET_CONFIG_ENABLE_IPV4 |
1149 | 0 | if (addrPrefix.IPAddr.IsIPv4()) |
1150 | 0 | continue; |
1151 | 0 | #endif // INET_CONFIG_ENABLE_IPV4 |
1152 | 0 | if (addrPrefix.IPAddr.IsIPv6LinkLocal()) |
1153 | 0 | continue; |
1154 | 0 | addrPrefix.Length = ifAddrIter.GetIPv6PrefixLength(); |
1155 | 0 | if (addrPrefix.MatchAddress(addr)) |
1156 | 0 | return true; |
1157 | 0 | } |
1158 | | |
1159 | 0 | return false; |
1160 | 0 | } |
1161 | | |
1162 | | #if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
1163 | | void InetLayer::HandleTCPInactivityTimer(Weave::System::Layer* aSystemLayer, void* aAppState, Weave::System::Error aError) |
1164 | 0 | { |
1165 | 0 | InetLayer& lInetLayer = *reinterpret_cast<InetLayer*>(aAppState); |
1166 | 0 | bool lTimerRequired = lInetLayer.IsIdleTimerRunning(); |
1167 | |
|
1168 | 0 | for (size_t i = 0; i < INET_CONFIG_NUM_TCP_ENDPOINTS; i++) |
1169 | 0 | { |
1170 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*aSystemLayer, i); |
1171 | |
|
1172 | 0 | if (lEndPoint == NULL) continue; |
1173 | 0 | if (!lEndPoint->IsCreatedByInetLayer(lInetLayer)) continue; |
1174 | 0 | if (!lEndPoint->IsConnected()) continue; |
1175 | 0 | if (lEndPoint->mIdleTimeout == 0) continue; |
1176 | | |
1177 | 0 | if (lEndPoint->mRemainingIdleTime == 0) |
1178 | 0 | { |
1179 | 0 | lEndPoint->DoClose(INET_ERROR_IDLE_TIMEOUT, false); |
1180 | 0 | } |
1181 | 0 | else |
1182 | 0 | { |
1183 | 0 | --lEndPoint->mRemainingIdleTime; |
1184 | 0 | } |
1185 | 0 | } |
1186 | |
|
1187 | 0 | if (lTimerRequired) |
1188 | 0 | { |
1189 | 0 | aSystemLayer->StartTimer(INET_TCP_IDLE_CHECK_INTERVAL, HandleTCPInactivityTimer, &lInetLayer); |
1190 | 0 | } |
1191 | 0 | } |
1192 | | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 |
1193 | | |
1194 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
1195 | | Weave::System::Error InetLayer::HandleInetLayerEvent(Weave::System::Object& aTarget, Weave::System::EventType aEventType, |
1196 | | uintptr_t aArgument) |
1197 | | { |
1198 | | Weave::System::Error lReturn = WEAVE_SYSTEM_NO_ERROR; |
1199 | | InetLayerBasis& lBasis = static_cast<InetLayerBasis&>(aTarget); |
1200 | | |
1201 | | VerifyOrExit(INET_IsInetEvent(aEventType), lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT); |
1202 | | |
1203 | | // Dispatch the event according to its type. |
1204 | | switch (aEventType) |
1205 | | { |
1206 | | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
1207 | | case kInetEvent_TCPConnectComplete: |
1208 | | static_cast<TCPEndPoint &>(aTarget).HandleConnectComplete(static_cast<INET_ERROR>(aArgument)); |
1209 | | break; |
1210 | | |
1211 | | case kInetEvent_TCPConnectionReceived: |
1212 | | static_cast<TCPEndPoint &>(aTarget).HandleIncomingConnection(reinterpret_cast<TCPEndPoint*>(aArgument)); |
1213 | | break; |
1214 | | |
1215 | | case kInetEvent_TCPDataReceived: |
1216 | | static_cast<TCPEndPoint &>(aTarget).HandleDataReceived(reinterpret_cast<Weave::System::PacketBuffer*>(aArgument)); |
1217 | | break; |
1218 | | |
1219 | | case kInetEvent_TCPDataSent: |
1220 | | static_cast<TCPEndPoint &>(aTarget).HandleDataSent(static_cast<uint16_t>(aArgument)); |
1221 | | break; |
1222 | | |
1223 | | case kInetEvent_TCPError: |
1224 | | static_cast<TCPEndPoint &>(aTarget).HandleError(static_cast<INET_ERROR>(aArgument)); |
1225 | | break; |
1226 | | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
1227 | | |
1228 | | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
1229 | | case kInetEvent_RawDataReceived: |
1230 | | static_cast<RawEndPoint &>(aTarget).HandleDataReceived(reinterpret_cast<Weave::System::PacketBuffer*>(aArgument)); |
1231 | | break; |
1232 | | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
1233 | | |
1234 | | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
1235 | | case kInetEvent_UDPDataReceived: |
1236 | | static_cast<UDPEndPoint &>(aTarget).HandleDataReceived(reinterpret_cast<Weave::System::PacketBuffer*>(aArgument)); |
1237 | | break; |
1238 | | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
1239 | | |
1240 | | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
1241 | | case kInetEvent_TunDataReceived: |
1242 | | static_cast<TunEndPoint &>(aTarget).HandleDataReceived(reinterpret_cast<Weave::System::PacketBuffer*>(aArgument)); |
1243 | | break; |
1244 | | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
1245 | | |
1246 | | #if INET_CONFIG_ENABLE_DNS_RESOLVER |
1247 | | case kInetEvent_DNSResolveComplete: |
1248 | | static_cast<DNSResolver &>(aTarget).HandleResolveComplete(); |
1249 | | break; |
1250 | | #endif // INET_CONFIG_ENABLE_DNS_RESOLVER |
1251 | | |
1252 | | default: |
1253 | | lReturn = WEAVE_SYSTEM_ERROR_UNEXPECTED_EVENT; |
1254 | | ExitNow(); |
1255 | | } |
1256 | | |
1257 | | // If the event was droppable, record the fact that it has been dequeued. |
1258 | | if (IsDroppableEvent(aEventType)) |
1259 | | { |
1260 | | InetLayer& lInetLayer = lBasis.Layer(); |
1261 | | |
1262 | | lInetLayer.DroppableEventDequeued(); |
1263 | | } |
1264 | | |
1265 | | exit: |
1266 | | return lReturn; |
1267 | | } |
1268 | | |
1269 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1270 | | |
1271 | | /** |
1272 | | * This posts an event / message of the specified type with the |
1273 | | * provided argument to this instance's platform-specific event / |
1274 | | * message queue. |
1275 | | * |
1276 | | * @param[inout] target A pointer to the InetLayer object making the |
1277 | | * post request. |
1278 | | * |
1279 | | * @param[in] type The type of event to post. |
1280 | | * |
1281 | | * @param[inout] arg The argument associated with the event to post. |
1282 | | * |
1283 | | * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer |
1284 | | * object is incorrect. |
1285 | | * @retval #INET_ERROR_BAD_ARGS If #target is NULL. |
1286 | | * @retval #INET_ERROR_NO_MEMORY If the EventQueue is already |
1287 | | * full. |
1288 | | * @retval other platform-specific errors generated indicating the reason |
1289 | | * for failure. |
1290 | | * @retval #INET_NO_ERROR On success. |
1291 | | * |
1292 | | */ |
1293 | | INET_ERROR InetLayer::PostEvent(InetLayerBasis *target, InetEventType type, uintptr_t arg) |
1294 | | { |
1295 | | Weave::System::Layer& lSystemLayer = *mSystemLayer; |
1296 | | INET_ERROR retval = INET_NO_ERROR; |
1297 | | |
1298 | | VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); |
1299 | | VerifyOrExit(target != NULL, retval = INET_ERROR_BAD_ARGS); |
1300 | | |
1301 | | { |
1302 | | Weave::System::Layer& lTargetSystemLayer = target->SystemLayer(); |
1303 | | |
1304 | | VerifyOrDieWithMsg(target->IsRetained(lSystemLayer), Inet, "wrong system layer! [target %p != instance %p]", |
1305 | | &lTargetSystemLayer, &lSystemLayer); |
1306 | | } |
1307 | | |
1308 | | // Sanity check that this instance and the target layer haven't |
1309 | | // been "crossed". |
1310 | | |
1311 | | { |
1312 | | InetLayer& lTargetInetLayer = target->Layer(); |
1313 | | |
1314 | | VerifyOrDieWithMsg(this == &lTargetInetLayer, Inet, "target layer %p != instance layer %p", &lTargetInetLayer, this); |
1315 | | } |
1316 | | |
1317 | | if (IsDroppableEvent(type) && !CanEnqueueDroppableEvent()) |
1318 | | { |
1319 | | WeaveLogProgress(Inet, "Dropping incoming packet (type %d)", (int)type); |
1320 | | ExitNow(retval = INET_ERROR_NO_MEMORY); |
1321 | | } |
1322 | | |
1323 | | retval = Platform::InetLayer::PostEvent(this, mContext, target, type, arg); |
1324 | | if (retval != INET_NO_ERROR) |
1325 | | { |
1326 | | WeaveLogError(Inet, "Failed to queue InetLayer event (type %d): %s", (int)type, ErrorStr(retval)); |
1327 | | } |
1328 | | SuccessOrExit(retval); |
1329 | | |
1330 | | exit: |
1331 | | return retval; |
1332 | | } |
1333 | | |
1334 | | /** |
1335 | | * This is a syntactic wrapper around a platform-specific hook that |
1336 | | * effects an event loop, waiting on a queue that services this |
1337 | | * instance, pulling events off of that queue, and then dispatching |
1338 | | * them for handling. |
1339 | | * |
1340 | | * @return #INET_NO_ERROR on success; otherwise, a specific error |
1341 | | * indicating the reason for initialization failure. |
1342 | | * |
1343 | | */ |
1344 | | INET_ERROR InetLayer::DispatchEvents(void) |
1345 | | { |
1346 | | INET_ERROR retval = INET_NO_ERROR; |
1347 | | |
1348 | | VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); |
1349 | | |
1350 | | retval = Platform::InetLayer::DispatchEvents(this, mContext); |
1351 | | SuccessOrExit(retval); |
1352 | | |
1353 | | exit: |
1354 | | return retval; |
1355 | | } |
1356 | | |
1357 | | /** |
1358 | | * Start the platform timer with specified msec duration. |
1359 | | * |
1360 | | * @brief |
1361 | | * Calls the Platform specific API to start a platform timer. |
1362 | | * This API is called by the Weave::System::Timer class when one or more |
1363 | | * system timers are active and require deferred execution. |
1364 | | * |
1365 | | * @param[in] inDurMS The timer duration in milliseconds. |
1366 | | * |
1367 | | * @return INET_NO_ERROR on success, error code otherwise. |
1368 | | * |
1369 | | */ |
1370 | | INET_ERROR InetLayer::StartPlatformTimer(uint32_t inDurMS) |
1371 | | { |
1372 | | INET_ERROR retval; |
1373 | | |
1374 | | VerifyOrExit(State == kState_Initialized, retval = INET_ERROR_INCORRECT_STATE); |
1375 | | |
1376 | | retval = Platform::InetLayer::StartTimer(this, mContext, inDurMS); |
1377 | | |
1378 | | exit: |
1379 | | return retval; |
1380 | | } |
1381 | | |
1382 | | /** |
1383 | | * Handle the platform timer expiration event. |
1384 | | * |
1385 | | * @brief |
1386 | | * Calls Weave::System::Timer::HandleExpiredTimers to handle any expired |
1387 | | * system timers. It is assumed that this API is called only while |
1388 | | * on the thread which owns the InetLayer object. |
1389 | | * |
1390 | | * @return INET_NO_ERROR on success, error code otherwise. |
1391 | | * |
1392 | | */ |
1393 | | INET_ERROR InetLayer::HandlePlatformTimer(void) |
1394 | | { |
1395 | | INET_ERROR lReturn; |
1396 | | Weave::System::Error lSystemError; |
1397 | | |
1398 | | VerifyOrExit(State == kState_Initialized, lReturn = INET_ERROR_INCORRECT_STATE); |
1399 | | |
1400 | | lSystemError = mSystemLayer->HandlePlatformTimer(); |
1401 | | lReturn = static_cast<INET_ERROR>(lSystemError); |
1402 | | |
1403 | | exit: |
1404 | | return lReturn; |
1405 | | } |
1406 | | |
1407 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1408 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
1409 | | |
1410 | | #if WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
1411 | | /** |
1412 | | * Prepare the sets of file descriptors for @p select() to work with. |
1413 | | * |
1414 | | * @param[in,out] pollFDs The fd set which is going to be polled |
1415 | | * @param[in,out] numPollFDs The number of fds in the fd set |
1416 | | * @param[in] timeoutMS A reference to the maximum sleep time. |
1417 | | * |
1418 | | */ |
1419 | | void InetLayer::PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS) |
1420 | 0 | { |
1421 | 0 | if (State != kState_Initialized) |
1422 | 0 | return; |
1423 | | |
1424 | 0 | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
1425 | 0 | for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) |
1426 | 0 | { |
1427 | 0 | RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); |
1428 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1429 | 0 | lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1430 | 0 | } |
1431 | 0 | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
1432 | |
|
1433 | 0 | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
1434 | 0 | for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) |
1435 | 0 | { |
1436 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); |
1437 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1438 | 0 | lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1439 | 0 | } |
1440 | 0 | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
1441 | |
|
1442 | 0 | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
1443 | 0 | for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) |
1444 | 0 | { |
1445 | 0 | UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); |
1446 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1447 | 0 | lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1448 | 0 | } |
1449 | 0 | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
1450 | |
|
1451 | 0 | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
1452 | 0 | for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) |
1453 | 0 | { |
1454 | 0 | TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); |
1455 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1456 | 0 | lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1457 | 0 | } |
1458 | 0 | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
1459 | |
|
1460 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1461 | | if (mSystemLayer == &mImplicitSystemLayer) |
1462 | | { |
1463 | | mSystemLayer->PrepareSelect(pollFDs, numPollFDs, timeoutMS); |
1464 | | } |
1465 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1466 | 0 | } |
1467 | | |
1468 | | /** |
1469 | | * Handle I/O from a select call. This method registers the pending I/O |
1470 | | * event in each active endpoint and then invokes the respective I/O |
1471 | | * handling functions for those endpoints. |
1472 | | * |
1473 | | * @note |
1474 | | * It is important to set the pending I/O fields for all endpoints |
1475 | | * *before* making any callbacks. This avoids the case where an |
1476 | | * endpoint is closed and then re-opened within the callback for |
1477 | | * another endpoint. When this happens the new endpoint is likely |
1478 | | * to be assigned the same file descriptor as the old endpoint. |
1479 | | * However, any pending I/O for that file descriptor number represents |
1480 | | * I/O related to the old incarnation of the endpoint, not the current |
1481 | | * one. Saving the pending I/O state in each endpoint before acting |
1482 | | * on it allows the endpoint code to clear the I/O flags in the event |
1483 | | * of a close, thus avoiding any confusion. |
1484 | | * |
1485 | | * @param[in] pollFDs The result of polled FDs |
1486 | | * @param[in] numPollFDs The number of fds in the fd set |
1487 | | */ |
1488 | | void InetLayer::HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs) |
1489 | 0 | { |
1490 | 0 | if (State != kState_Initialized) |
1491 | 0 | return; |
1492 | | |
1493 | | // Set the pending I/O field for each active endpoint based on the value returned by select. |
1494 | 0 | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
1495 | 0 | for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) |
1496 | 0 | { |
1497 | 0 | RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); |
1498 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1499 | 0 | { |
1500 | 0 | lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1501 | 0 | } |
1502 | 0 | } |
1503 | 0 | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
1504 | |
|
1505 | 0 | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
1506 | 0 | for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) |
1507 | 0 | { |
1508 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); |
1509 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1510 | 0 | { |
1511 | 0 | lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1512 | 0 | } |
1513 | 0 | } |
1514 | 0 | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
1515 | |
|
1516 | 0 | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
1517 | 0 | for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) |
1518 | 0 | { |
1519 | 0 | UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); |
1520 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1521 | 0 | { |
1522 | 0 | lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1523 | 0 | } |
1524 | 0 | } |
1525 | 0 | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
1526 | |
|
1527 | 0 | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
1528 | 0 | for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) |
1529 | 0 | { |
1530 | 0 | TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); |
1531 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1532 | 0 | { |
1533 | 0 | lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs); |
1534 | 0 | } |
1535 | 0 | } |
1536 | 0 | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
1537 | | |
1538 | | // Now call each active endpoint to handle its pending I/O. |
1539 | 0 | #if INET_CONFIG_ENABLE_RAW_ENDPOINT |
1540 | 0 | for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++) |
1541 | 0 | { |
1542 | 0 | RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i); |
1543 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1544 | 0 | { |
1545 | 0 | lEndPoint->HandlePendingIO(); |
1546 | 0 | } |
1547 | 0 | } |
1548 | 0 | #endif // INET_CONFIG_ENABLE_RAW_ENDPOINT |
1549 | |
|
1550 | 0 | #if INET_CONFIG_ENABLE_TCP_ENDPOINT |
1551 | 0 | for (size_t i = 0; i < TCPEndPoint::sPool.Size(); i++) |
1552 | 0 | { |
1553 | 0 | TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i); |
1554 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1555 | 0 | { |
1556 | 0 | lEndPoint->HandlePendingIO(); |
1557 | 0 | } |
1558 | 0 | } |
1559 | 0 | #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT |
1560 | |
|
1561 | 0 | #if INET_CONFIG_ENABLE_UDP_ENDPOINT |
1562 | 0 | for (size_t i = 0; i < UDPEndPoint::sPool.Size(); i++) |
1563 | 0 | { |
1564 | 0 | UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i); |
1565 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1566 | 0 | { |
1567 | 0 | lEndPoint->HandlePendingIO(); |
1568 | 0 | } |
1569 | 0 | } |
1570 | 0 | #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT |
1571 | |
|
1572 | 0 | #if INET_CONFIG_ENABLE_TUN_ENDPOINT |
1573 | 0 | for (size_t i = 0; i < TunEndPoint::sPool.Size(); i++) |
1574 | 0 | { |
1575 | 0 | TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i); |
1576 | 0 | if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this)) |
1577 | 0 | { |
1578 | 0 | lEndPoint->HandlePendingIO(); |
1579 | 0 | } |
1580 | 0 | } |
1581 | 0 | #endif // INET_CONFIG_ENABLE_TUN_ENDPOINT |
1582 | |
|
1583 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1584 | | if (mSystemLayer == &mImplicitSystemLayer) |
1585 | | { |
1586 | | mSystemLayer->HandleSelectResult(pollFDs, numPollFDs); |
1587 | | } |
1588 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1589 | 0 | } |
1590 | | |
1591 | | #endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS |
1592 | | |
1593 | | /** |
1594 | | * Reset the members of the IPPacketInfo object. |
1595 | | * |
1596 | | */ |
1597 | | void IPPacketInfo::Clear() |
1598 | 0 | { |
1599 | 0 | SrcAddress = IPAddress::Any; |
1600 | 0 | DestAddress = IPAddress::Any; |
1601 | 0 | Interface = INET_NULL_INTERFACEID; |
1602 | 0 | SrcPort = 0; |
1603 | 0 | DestPort = 0; |
1604 | 0 | } |
1605 | | |
1606 | | |
1607 | | #if !INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS |
1608 | | |
1609 | | // MARK: InetLayer platform- and system-specific functions for InetLayer |
1610 | | // construction and destruction. |
1611 | | |
1612 | | namespace Platform { |
1613 | | namespace InetLayer { |
1614 | | |
1615 | | /** |
1616 | | * This is a platform-specific InetLayer pre-initialization hook. This |
1617 | | * may be overridden by assserting the preprocessor definition, |
1618 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. |
1619 | | * |
1620 | | * @param[inout] aLayer A pointer to the InetLayer instance being |
1621 | | * initialized. |
1622 | | * |
1623 | | * @param[inout] aContext Platform-specific context data passed to |
1624 | | * the layer initialization method, ::Init. |
1625 | | * |
1626 | | * @return #INET_NO_ERROR on success; otherwise, a specific error indicating |
1627 | | * the reason for initialization failure. Returning non-successful |
1628 | | * status will abort initialization. |
1629 | | * |
1630 | | */ |
1631 | | NL_DLL_EXPORT INET_ERROR WillInit(Inet::InetLayer *aLayer, void *aContext) |
1632 | 0 | { |
1633 | 0 | (void)aLayer; |
1634 | 0 | (void)aContext; |
1635 | |
|
1636 | 0 | return INET_NO_ERROR; |
1637 | 0 | } |
1638 | | |
1639 | | /** |
1640 | | * This is a platform-specific InetLayer post-initialization hook. This |
1641 | | * may be overridden by assserting the preprocessor definition, |
1642 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. |
1643 | | * |
1644 | | * @param[inout] aLayer A pointer to the InetLayer instance being |
1645 | | * initialized. |
1646 | | * |
1647 | | * @param[inout] aContext Platform-specific context data passed to |
1648 | | * the layer initialization method, ::Init. |
1649 | | * |
1650 | | * @param[in] anError The overall status being returned via the |
1651 | | * InetLayer ::Init method. |
1652 | | * |
1653 | | */ |
1654 | | NL_DLL_EXPORT void DidInit(Inet::InetLayer *aLayer, void *aContext, INET_ERROR anError) |
1655 | 0 | { |
1656 | 0 | (void)aLayer; |
1657 | 0 | (void)aContext; |
1658 | 0 | (void)anError; |
1659 | |
|
1660 | 0 | return; |
1661 | 0 | } |
1662 | | |
1663 | | /** |
1664 | | * This is a platform-specific InetLayer pre-shutdown hook. This |
1665 | | * may be overridden by assserting the preprocessor definition, |
1666 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. |
1667 | | * |
1668 | | * @param[inout] aLayer A pointer to the InetLayer instance being |
1669 | | * shutdown. |
1670 | | * |
1671 | | * @param[inout] aContext Platform-specific context data passed to |
1672 | | * the layer initialization method, ::Init. |
1673 | | * |
1674 | | * @return #INET_NO_ERROR on success; otherwise, a specific error indicating |
1675 | | * the reason for shutdown failure. Returning non-successful |
1676 | | * status will abort shutdown. |
1677 | | * |
1678 | | */ |
1679 | | NL_DLL_EXPORT INET_ERROR WillShutdown(Inet::InetLayer *aLayer, void *aContext) |
1680 | 0 | { |
1681 | 0 | (void)aLayer; |
1682 | 0 | (void)aContext; |
1683 | |
|
1684 | 0 | return INET_NO_ERROR; |
1685 | 0 | } |
1686 | | |
1687 | | /** |
1688 | | * This is a platform-specific InetLayer post-shutdown hook. This |
1689 | | * may be overridden by assserting the preprocessor definition, |
1690 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS. |
1691 | | * |
1692 | | * @param[inout] aLayer A pointer to the InetLayer instance being |
1693 | | * shutdown. |
1694 | | * |
1695 | | * @param[inout] aContext Platform-specific context data passed to |
1696 | | * the layer initialization method, ::Init. |
1697 | | * |
1698 | | * @param[in] anError The overall status being returned via the |
1699 | | * InetLayer ::Shutdown method. |
1700 | | * |
1701 | | */ |
1702 | | NL_DLL_EXPORT void DidShutdown(Inet::InetLayer *aLayer, void *aContext, INET_ERROR anError) |
1703 | 0 | { |
1704 | 0 | (void)aLayer; |
1705 | 0 | (void)aContext; |
1706 | 0 | (void)anError; |
1707 | |
|
1708 | 0 | return; |
1709 | 0 | } |
1710 | | |
1711 | | #if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1712 | | #if WEAVE_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS |
1713 | | /** |
1714 | | * This is a platform-specific event / message post hook. This may be |
1715 | | * overridden by assserting the preprocessor definition, |
1716 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. |
1717 | | * |
1718 | | * This posts an event / message of the specified type with the |
1719 | | * provided argument to this instance's platform-specific event / |
1720 | | * message queue. |
1721 | | * |
1722 | | * @note |
1723 | | * This is an implementation for LwIP. |
1724 | | * |
1725 | | * @param[inout] aLayer A pointer to the layer instance to which the |
1726 | | * event / message is being posted. |
1727 | | * |
1728 | | * @param[inout] aContext Platform-specific context data passed to |
1729 | | * the layer initialization method, ::Init. |
1730 | | * |
1731 | | * @param[inout] aTarget A pointer to the InetLayer object making the |
1732 | | * post request. |
1733 | | * |
1734 | | * @param[in] aType The type of event to post. |
1735 | | * |
1736 | | * @param[inout] anArg The argument associated with the event to post. |
1737 | | * |
1738 | | * @return #INET_NO_ERROR on success; otherwise, a specific error indicating |
1739 | | * the reason for initialization failure. |
1740 | | * |
1741 | | */ |
1742 | | INET_ERROR PostEvent(Inet::InetLayer* aInetLayer, void* aContext, InetLayerBasis* aTarget, InetEventType aEventType, |
1743 | | uintptr_t aArgument) |
1744 | | { |
1745 | | Weave::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; |
1746 | | Weave::System::Object& lObject = *aTarget; |
1747 | | Weave::System::Error lReturn = Weave::System::Platform::Layer::PostEvent(lSystemLayer, aContext, lObject, aEventType, |
1748 | | aArgument); |
1749 | | |
1750 | | return static_cast<INET_ERROR>(lReturn); |
1751 | | } |
1752 | | |
1753 | | /** |
1754 | | * This is a platform-specific event / message dispatch hook. This may |
1755 | | * be overridden by assserting the preprocessor definition, |
1756 | | * INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. |
1757 | | * |
1758 | | * This effects an event loop, waiting on a queue that services this |
1759 | | * instance, pulling events off of that queue, and then dispatching |
1760 | | * them for handling. |
1761 | | * |
1762 | | * @note |
1763 | | * This is an implementation for LwIP. |
1764 | | * |
1765 | | * @param[inout] aInetLayer A pointer to the layer instance for which |
1766 | | * events / messages are being dispatched. |
1767 | | * |
1768 | | * @param[inout] aContext Platform-specific context data passed to |
1769 | | * the layer initialization method, ::Init. |
1770 | | * |
1771 | | * @retval #INET_ERROR_BAD_ARGS If #aLayer or #aContext is NULL. |
1772 | | * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer |
1773 | | * object is incorrect. |
1774 | | * @retval #INET_ERROR_UNEXPECTED_EVENT If an event type is unrecognized. |
1775 | | * @retval #INET_NO_ERROR On success. |
1776 | | * |
1777 | | */ |
1778 | | INET_ERROR DispatchEvents(Inet::InetLayer* aInetLayer, void* aContext) |
1779 | | { |
1780 | | Weave::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; |
1781 | | Weave::System::Error lReturn = Weave::System::Platform::Layer::DispatchEvents(lSystemLayer, aContext); |
1782 | | |
1783 | | return static_cast<INET_ERROR>(lReturn); |
1784 | | } |
1785 | | |
1786 | | /** |
1787 | | * This is a platform-specific event / message dispatch hook. This may |
1788 | | * be overridden by assserting the preprocessor definition, |
1789 | | * INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. |
1790 | | * |
1791 | | * This dispatches the specified event for handling, unmarshalling the |
1792 | | * type and arguments from the event for hand off to |
1793 | | * InetLayer::HandleEvent for the actual dispatch. |
1794 | | * |
1795 | | * @note |
1796 | | * This is an implementation for LwIP. |
1797 | | * |
1798 | | * @param[inout] aInetLayer A pointer to the layer instance for which |
1799 | | * events / messages are being dispatched. |
1800 | | * |
1801 | | * @param[inout] aContext Platform-specific context data passed to |
1802 | | * the layer initialization method, ::Init. |
1803 | | * |
1804 | | * @param[in] aEvent The platform-specific event object to |
1805 | | * dispatch for handling. |
1806 | | * |
1807 | | * @retval #INET_ERROR_BAD_ARGS If #aLayer or the event target is |
1808 | | * NULL. |
1809 | | * @retval #INET_ERROR_UNEXPECTED_EVENT If the event type is unrecognized. |
1810 | | * @retval #INET_ERROR_INCORRECT_STATE If the state of the InetLayer |
1811 | | * object is incorrect. |
1812 | | * @retval #INET_NO_ERROR On success. |
1813 | | * |
1814 | | */ |
1815 | | INET_ERROR DispatchEvent(Inet::InetLayer* aInetLayer, void* aContext, InetEvent aEvent) |
1816 | | { |
1817 | | Weave::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; |
1818 | | Weave::System::Error lReturn = Weave::System::Platform::Layer::DispatchEvent(lSystemLayer, aContext, aEvent); |
1819 | | |
1820 | | return static_cast<INET_ERROR>(lReturn); |
1821 | | } |
1822 | | |
1823 | | /** |
1824 | | * This is a platform-specific event / message dispatch hook. This may be overridden by assserting the preprocessor definition, |
1825 | | * #INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS. |
1826 | | * |
1827 | | * @note |
1828 | | * This is an implementation for LwIP. |
1829 | | * |
1830 | | * @param[inout] aInetLayer A reference to the layer instance for which events / messages are being dispatched. |
1831 | | * @param[inout] aContext Platform-specific context data passed to the layer initialization method, ::Init. |
1832 | | * @param[in] aMilliseconds The number of milliseconds to set for the timer. |
1833 | | * |
1834 | | * @retval #INET_NO_ERROR Always succeeds unless overridden. |
1835 | | */ |
1836 | | INET_ERROR StartTimer(Inet::InetLayer* aInetLayer, void* aContext, uint32_t aMilliseconds) |
1837 | | { |
1838 | | Weave::System::Layer& lSystemLayer = *aInetLayer->mSystemLayer; |
1839 | | Weave::System::Error lReturn = Weave::System::Platform::Layer::StartTimer(lSystemLayer, aContext, aMilliseconds); |
1840 | | |
1841 | | return static_cast<INET_ERROR>(lReturn); |
1842 | | } |
1843 | | |
1844 | | #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP && !INET_CONFIG_WILL_OVERRIDE_PLATFORM_EVENT_FUNCS |
1845 | | #endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES |
1846 | | |
1847 | | } // namespace InetLayer |
1848 | | } // namespace Platform |
1849 | | |
1850 | | #endif // !INET_CONFIG_WILL_OVERRIDE_PLATFORM_XTOR_FUNCS |
1851 | | |
1852 | | } // namespace Inet |
1853 | | } // namespace nl |