Coverage Report

Created: 2025-05-04 06:22

/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