Coverage Report

Created: 2026-02-12 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/examples/platform/linux/AppMain.cpp
Line
Count
Source
1
/*
2
 *
3
 *    Copyright (c) 2021-2022 Project CHIP Authors
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
#include <string>
20
21
#include <platform/CHIPDeviceLayer.h>
22
#include <platform/PlatformManager.h>
23
24
#include <app/InteractionModelEngine.h>
25
#include <app/clusters/network-commissioning/network-commissioning.h>
26
#include <app/server/Dnssd.h>
27
#include <app/server/Server.h>
28
#include <app/util/endpoint-config-api.h>
29
#include <crypto/CHIPCryptoPAL.h>
30
#include <data-model-providers/codegen/Instance.h>
31
#include <lib/core/CHIPError.h>
32
#include <lib/core/NodeId.h>
33
#include <lib/core/Optional.h>
34
#include <lib/support/logging/CHIPLogging.h>
35
#include <setup_payload/OnboardingCodesUtil.h>
36
37
#include <credentials/DeviceAttestationCredsProvider.h>
38
39
#include <lib/support/CHIPMem.h>
40
#include <lib/support/CHIPMemString.h>
41
#include <lib/support/CodeUtils.h>
42
#include <lib/support/ScopedBuffer.h>
43
#include <lib/support/TestGroupData.h>
44
#include <platform/CHIPDeviceEvent.h>
45
#include <platform/ConnectivityManager.h>
46
#include <platform/OpenThread/GenericNetworkCommissioningThreadDriver.h>
47
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
48
#include <setup_payload/SetupPayload.h>
49
50
#include <platform/CommissionableDataProvider.h>
51
#include <platform/DiagnosticDataProvider.h>
52
#include <platform/RuntimeOptionsProvider.h>
53
54
#include <AllClustersExampleDeviceInfoProviderImpl.h>
55
#include <DeviceInfoProviderImpl.h>
56
57
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
58
#include "CommissionerMain.h"
59
#include <ControllerShellCommands.h>
60
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
61
62
#if defined(ENABLE_CHIP_SHELL)
63
#include <CommissioneeShellCommands.h>
64
#include <lib/shell/Engine.h> // nogncheck
65
#include <thread>
66
#endif
67
68
#if defined(PW_RPC_ENABLED)
69
#include <Rpc.h>
70
#endif
71
72
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
73
#include "TraceDecoder.h"
74
#include "TraceHandlers.h"
75
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
76
77
#if ENABLE_TRACING
78
#include <TracingCommandLineArgument.h> // nogncheck
79
#endif
80
81
#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_DIAGNOSTIC_TRIGGER
82
#include <app/clusters/software-diagnostics-server/SoftwareDiagnosticsTestEventTriggerHandler.h>
83
#endif
84
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_DIAGNOSTIC_TRIGGER
85
#include <app/clusters/wifi-network-diagnostics-server/WiFiDiagnosticsTestEventTriggerHandler.h>
86
#endif
87
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
88
#include <app/clusters/ota-requestor/OTATestEventTriggerHandler.h>
89
#endif
90
#if CHIP_DEVICE_CONFIG_ENABLE_SMOKE_CO_TRIGGER
91
#include <app/clusters/smoke-co-alarm-server/SmokeCOTestEventTriggerHandler.h>
92
#endif
93
#if CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER
94
#include <app/clusters/boolean-state-configuration-server/BooleanStateConfigurationTestEventTriggerHandler.h>
95
#endif
96
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_PRICE_TRIGGER
97
#include <app/clusters/commodity-price-server/CommodityPriceTestEventTriggerHandler.h>
98
#endif
99
#if CHIP_DEVICE_CONFIG_ENABLE_ELECTRICAL_GRID_CONDITIONS_TRIGGER
100
#include <app/clusters/electrical-grid-conditions-server/ElectricalGridConditionsTestEventTriggerHandler.h>
101
#endif
102
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_TARIFF_TRIGGER
103
#include <app/clusters/commodity-tariff-server/CommodityTariffTestEventTriggerHandler.h>
104
#endif
105
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
106
#include <app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h>
107
#endif
108
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
109
#include <app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h>
110
#endif
111
#if CHIP_DEVICE_CONFIG_ENABLE_METER_IDENTIFICATION_TRIGGER
112
#include <app/clusters/meter-identification-server/MeterIdentificationTestEventTriggerHandler.h>
113
#endif
114
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
115
#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
116
#endif
117
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
118
#include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
119
#endif
120
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_METERING_TRIGGER
121
#include <app/clusters/commodity-metering-server/CommodityMeteringTestEventTriggerHandler.h>
122
#endif
123
#if CHIP_CONFIG_ENABLE_ICD_SERVER
124
#include <app/icd/server/ICDManager.h> // nogncheck
125
#endif
126
#include <app/TestEventTriggerDelegate.h>
127
128
#include <signal.h>
129
130
#include "AppMain.h"
131
#include "CommissionableInit.h"
132
133
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
134
#include "ExampleAccessRestrictionProvider.h"
135
#endif
136
137
#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
138
#include <app/server/TermsAndConditionsManager.h> // nogncheck
139
#endif
140
141
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
142
#include <platform/Darwin/NetworkCommissioningDriver.h>
143
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
144
#include <platform/Darwin/WiFi/NetworkCommissioningWiFiDriver.h>
145
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
146
#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN
147
148
#if CHIP_DEVICE_LAYER_TARGET_LINUX
149
#include <platform/Linux/NetworkCommissioningDriver.h>
150
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
151
152
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
153
#include <inet/EndPointStateOpenThread.h>
154
#include <openthread-system.h>
155
#include <openthread/instance.h>
156
#endif
157
158
using namespace chip;
159
using namespace chip::ArgParser;
160
using namespace chip::Credentials;
161
using namespace chip::DeviceLayer;
162
using namespace chip::Inet;
163
using namespace chip::Transport;
164
using namespace chip::app::Clusters;
165
using namespace chip::Access;
166
using namespace chip::Platform;
167
168
// Network comissioning implementation
169
namespace {
170
// If secondaryNetworkCommissioningEndpoint has a value and both Thread and WiFi
171
// are enabled, we put the WiFi network commissioning cluster on
172
// secondaryNetworkCommissioningEndpoint.
173
Optional<EndpointId> sSecondaryNetworkCommissioningEndpoint;
174
175
#if CHIP_DEVICE_LAYER_TARGET_LINUX
176
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
177
#define CHIP_APP_MAIN_HAS_THREAD_DRIVER 1
178
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
179
DeviceLayer::NetworkCommissioning::GenericThreadDriver sThreadDriver;
180
#else
181
DeviceLayer::NetworkCommissioning::LinuxThreadDriver sThreadDriver;
182
#endif
183
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
184
185
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
186
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 1
187
DeviceLayer::NetworkCommissioning::LinuxWiFiDriver sWiFiDriver;
188
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
189
190
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 1
191
DeviceLayer::NetworkCommissioning::LinuxEthernetDriver sEthernetDriver;
192
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
193
194
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
195
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
196
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 1
197
DeviceLayer::NetworkCommissioning::DarwinWiFiDriver sWiFiDriver;
198
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
199
200
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 1
201
DeviceLayer::NetworkCommissioning::DarwinEthernetDriver sEthernetDriver;
202
#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN
203
204
#ifndef CHIP_APP_MAIN_HAS_THREAD_DRIVER
205
#define CHIP_APP_MAIN_HAS_THREAD_DRIVER 0
206
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
207
208
#ifndef CHIP_APP_MAIN_HAS_WIFI_DRIVER
209
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 0
210
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
211
212
#ifndef CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
213
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 0
214
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
215
216
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
217
app::Clusters::NetworkCommissioning::Instance sThreadNetworkCommissioningInstance(kRootEndpointId, &sThreadDriver);
218
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
219
220
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
221
// The WiFi network commissioning instance cannot be constructed until we know
222
// whether we have an sSecondaryNetworkCommissioningEndpoint.
223
Optional<app::Clusters::NetworkCommissioning::Instance> sWiFiNetworkCommissioningInstance;
224
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
225
226
#if CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
227
app::Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(kRootEndpointId, &sEthernetDriver);
228
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
229
230
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
231
auto exampleAccessRestrictionProvider = std::make_unique<ExampleAccessRestrictionProvider>();
232
#endif
233
234
void EnableThreadNetworkCommissioning()
235
0
{
236
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
237
    SuccessOrDie(sThreadNetworkCommissioningInstance.Init());
238
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
239
0
}
240
241
void EnableWiFiNetworkCommissioning(EndpointId endpoint)
242
0
{
243
0
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
244
0
    sWiFiNetworkCommissioningInstance.Emplace(endpoint, &sWiFiDriver);
245
0
    SuccessOrDie(sWiFiNetworkCommissioningInstance.Value().Init());
246
0
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
247
0
}
248
249
void InitNetworkCommissioning()
250
0
{
251
0
    if (sSecondaryNetworkCommissioningEndpoint.HasValue())
252
0
    {
253
        // Enable secondary endpoint only when we need it, this should be applied to all platforms.
254
0
        emberAfEndpointEnableDisable(sSecondaryNetworkCommissioningEndpoint.Value(), false);
255
0
    }
256
257
0
    bool isThreadEnabled = false;
258
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
259
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
260
    isThreadEnabled = LinuxDeviceOptions::GetInstance().mThreadNodeId > 0;
261
#else
262
    isThreadEnabled = LinuxDeviceOptions::GetInstance().mThread;
263
#endif
264
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
265
266
0
    bool isWiFiEnabled = false;
267
0
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
268
0
    isWiFiEnabled = LinuxDeviceOptions::GetInstance().mWiFi;
269
270
    // On Linux, command-line indicates whether Wi-Fi is supported since determining it from
271
    // the OS level is not easily portable.
272
0
#if CHIP_DEVICE_LAYER_TARGET_LINUX
273
0
    sWiFiDriver.Set5gSupport(LinuxDeviceOptions::GetInstance().wifiSupports5g);
274
0
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
275
276
0
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
277
278
0
    if (isThreadEnabled && isWiFiEnabled)
279
0
    {
280
0
        if (sSecondaryNetworkCommissioningEndpoint.HasValue())
281
0
        {
282
0
            EnableThreadNetworkCommissioning();
283
0
            EnableWiFiNetworkCommissioning(sSecondaryNetworkCommissioningEndpoint.Value());
284
            // Only enable secondary endpoint for network commissioning cluster when both WiFi and Thread are enabled.
285
0
            emberAfEndpointEnableDisable(sSecondaryNetworkCommissioningEndpoint.Value(), true);
286
0
        }
287
0
        else
288
0
        {
289
            // Just use the Thread one.
290
0
            EnableThreadNetworkCommissioning();
291
0
        }
292
0
    }
293
0
    else if (isThreadEnabled)
294
0
    {
295
0
        EnableThreadNetworkCommissioning();
296
0
    }
297
0
    else if (isWiFiEnabled)
298
0
    {
299
0
        EnableWiFiNetworkCommissioning(kRootEndpointId);
300
0
    }
301
0
    else
302
0
    {
303
0
#if CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
304
0
        TEMPORARY_RETURN_IGNORED sEthernetNetworkCommissioningInstance.Init();
305
0
#if CHIP_DEVICE_LAYER_TARGET_LINUX
306
0
        DeviceLayer::ConnectivityMgrImpl().UpdateEthernetNetworkingStatus();
307
0
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
308
0
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
309
0
    }
310
0
}
311
312
} // anonymous namespace
313
314
#if defined(ENABLE_CHIP_SHELL)
315
using chip::Shell::Engine;
316
#endif
317
318
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
319
/*
320
 * The device shall check every kWiFiStartCheckTimeUsec whether Wi-Fi management
321
 * has been fully initialized. If after kWiFiStartCheckAttempts Wi-Fi management
322
 * still hasn't been initialized, the device configuration is reset, and device
323
 * needs to be paired again.
324
 */
325
static constexpr useconds_t kWiFiStartCheckTimeUsec = WIFI_START_CHECK_TIME_USEC;
326
static constexpr uint8_t kWiFiStartCheckAttempts    = WIFI_START_CHECK_ATTEMPTS;
327
#endif
328
329
namespace {
330
AppMainLoopImplementation * gMainLoopImplementation = nullptr;
331
332
// To hold SPAKE2+ verifier, discriminator, passcode
333
LinuxCommissionableDataProvider gCommissionableDataProvider;
334
335
chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
336
chip::DeviceLayer::AllClustersExampleDeviceInfoProviderImpl gAllClustersExampleDeviceInfoProvider;
337
338
void EventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
339
0
{
340
0
    (void) arg;
341
0
    if (event->Type == DeviceLayer::DeviceEventType::kCHIPoBLEConnectionEstablished)
342
0
    {
343
0
        ChipLogProgress(DeviceLayer, "Receive kCHIPoBLEConnectionEstablished");
344
0
    }
345
0
    else if ((event->Type == chip::DeviceLayer::DeviceEventType::kInternetConnectivityChange))
346
0
    {
347
        // Restart the server on connectivity change
348
0
        app::DnssdServer::Instance().StartServer();
349
0
    }
350
0
}
351
352
void StopMainEventLoop()
353
0
{
354
0
    if (gMainLoopImplementation != nullptr)
355
0
    {
356
0
        gMainLoopImplementation->SignalSafeStopMainLoop();
357
0
    }
358
0
    else
359
0
    {
360
0
        Server::GetInstance().GenerateShutDownEvent();
361
0
        TEMPORARY_RETURN_IGNORED SystemLayer().ScheduleLambda([]() { TEMPORARY_RETURN_IGNORED PlatformMgr().StopEventLoopTask(); });
362
0
    }
363
0
}
364
365
void Cleanup()
366
0
{
367
0
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
368
0
    chip::trace::DeInitTrace();
369
0
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
370
371
    // TODO(16968): Lifecycle management of storage-using components like GroupDataProvider, etc
372
0
}
373
374
void StopSignalHandler(int /* signal */)
375
0
{
376
#if defined(ENABLE_CHIP_SHELL)
377
    Engine::Root().StopMainLoop();
378
#endif
379
0
    StopMainEventLoop();
380
0
}
381
382
} // namespace
383
384
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
385
static bool EnsureWiFiIsStarted()
386
0
{
387
0
    for (int cnt = 0; cnt < kWiFiStartCheckAttempts; cnt++)
388
0
    {
389
0
        if (DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted())
390
0
        {
391
0
            return true;
392
0
        }
393
394
0
        usleep(kWiFiStartCheckTimeUsec);
395
0
    }
396
397
0
    return DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted();
398
0
}
399
#endif
400
401
class SampleTestEventTriggerHandler : public TestEventTriggerHandler
402
{
403
    /// NOTE: If you copy this for NON-STANDARD CLUSTERS OR USAGES, please use the reserved range FFFF_FFFF_<VID_HEX>_xxxx for your
404
    /// trigger codes. NOTE: Standard codes are <CLUSTER_ID_HEX>_xxxx_xxxx_xxxx.
405
    static constexpr uint64_t kSampleTestEventTriggerAlwaysSuccess = static_cast<uint64_t>(0xFFFF'FFFF'FFF1'0000ull);
406
407
public:
408
    CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override
409
0
    {
410
0
        ChipLogProgress(Support, "Saw TestEventTrigger: " ChipLogFormatX64, ChipLogValueX64(eventTrigger));
411
412
0
        if (eventTrigger == kSampleTestEventTriggerAlwaysSuccess)
413
0
        {
414
            // Do nothing, successfully
415
0
            ChipLogProgress(Support, "Handling \"Always success\" internal test event");
416
0
            return CHIP_NO_ERROR;
417
0
        }
418
419
0
        return CHIP_ERROR_INVALID_ARGUMENT;
420
0
    }
421
};
422
423
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
424
/*
425
    Get the freq_list from args.
426
    Format:
427
        "freq_list=[freq#1],[freq#2]...[freq#n]"
428
            [freq#1] - [freq#n]: frequence number, separated by ','
429
*/
430
static uint16_t WiFiPAFGet_FreqList(const char * args, std::unique_ptr<uint16_t[]> & freq_list)
431
0
{
432
0
    const char hdstr[] = "freq_list=";
433
0
    std::vector<uint16_t> freq_vect;
434
0
    const std::string argstrn(args);
435
0
    auto pos = argstrn.find(hdstr);
436
0
    if (pos == std::string::npos)
437
0
    {
438
0
        return 0;
439
0
    }
440
0
    std::string nums = argstrn.substr(pos + strlen(hdstr));
441
0
    std::stringstream ss(nums);
442
0
    std::string item;
443
0
    while (std::getline(ss, item, ','))
444
0
    {
445
0
        freq_vect.push_back(std::stoi(item));
446
0
    }
447
0
    uint16_t freq_size = freq_vect.size();
448
0
    freq_list          = std::make_unique<uint16_t[]>(freq_size);
449
0
    for (int i = 0; i < freq_size; i++)
450
0
    {
451
0
        freq_list.get()[i] = freq_vect[i];
452
0
    }
453
0
    return freq_size;
454
0
}
455
#endif
456
457
// Wrapper for DeviceInstanceInfoProvider that allows the example app to set
458
// attribute values from the command-line, provide hardcoded values, or fall
459
// back to the default DeviceInstanceInfoProvider.
460
class ExampleDeviceInstanceInfoProvider : public DeviceInstanceInfoProvider
461
{
462
public:
463
0
    void Init(DeviceInstanceInfoProvider * defaultProvider) { mDefaultProvider = defaultProvider; }
464
465
    CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override
466
0
    {
467
        // Check if it was set from the command line or fall back to default provider.
468
0
        if (mVendorName.has_value())
469
0
        {
470
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mVendorName.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
471
0
            CopyString(buf, bufSize, mVendorName.value().c_str());
472
0
            return CHIP_NO_ERROR;
473
0
        }
474
475
0
        return mDefaultProvider->GetVendorName(buf, bufSize);
476
0
    }
477
478
0
    CHIP_ERROR GetVendorId(uint16_t & vendorId) override { return mDefaultProvider->GetVendorId(vendorId); }
479
480
    CHIP_ERROR GetProductName(char * buf, size_t bufSize) override
481
0
    {
482
        // Check if it was set from the command line or fall back to default provider.
483
0
        if (mProductName.has_value())
484
0
        {
485
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mProductName.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
486
0
            CopyString(buf, bufSize, mProductName.value().c_str());
487
0
            return CHIP_NO_ERROR;
488
0
        }
489
490
0
        return mDefaultProvider->GetProductName(buf, bufSize);
491
0
    }
492
493
0
    CHIP_ERROR GetProductId(uint16_t & productId) override { return mDefaultProvider->GetProductId(productId); }
494
0
    CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override { return mDefaultProvider->GetPartNumber(buf, bufSize); }
495
0
    CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override { return mDefaultProvider->GetProductURL(buf, bufSize); }
496
0
    CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override { return mDefaultProvider->GetProductLabel(buf, bufSize); }
497
498
    CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override
499
0
    {
500
        // Check if it was set from the command line or fall back to default provider.
501
0
        if (mSerialNumber.has_value())
502
0
        {
503
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mSerialNumber.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
504
0
            CopyString(buf, bufSize, mSerialNumber.value().c_str());
505
0
            return CHIP_NO_ERROR;
506
0
        }
507
508
0
        return mDefaultProvider->GetSerialNumber(buf, bufSize);
509
0
    }
510
511
    CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override
512
0
    {
513
0
        return mDefaultProvider->GetManufacturingDate(year, month, day);
514
0
    }
515
    CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override
516
0
    {
517
0
        return mDefaultProvider->GetHardwareVersion(hardwareVersion);
518
0
    }
519
    CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override
520
0
    {
521
        // Check if it was set from the command line or fall back to default provider.
522
0
        if (mHardwareVersionString.has_value())
523
0
        {
524
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mHardwareVersionString.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
525
0
            CopyString(buf, bufSize, mHardwareVersionString.value().c_str());
526
0
            return CHIP_NO_ERROR;
527
0
        }
528
529
0
        return mDefaultProvider->GetHardwareVersionString(buf, bufSize);
530
0
    }
531
532
    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override
533
0
    {
534
0
        return mDefaultProvider->GetRotatingDeviceIdUniqueId(uniqueIdSpan);
535
0
    }
536
537
    CHIP_ERROR GetProductFinish(chip::app::Clusters::BasicInformation::ProductFinishEnum * finish) override
538
0
    {
539
        // Our example device claims to have a Satin finish for now.  We can make
540
        // this configurable as needed.
541
0
        *finish = chip::app::Clusters::BasicInformation::ProductFinishEnum::kSatin;
542
0
        return CHIP_NO_ERROR;
543
0
    }
544
545
    CHIP_ERROR GetProductPrimaryColor(chip::app::Clusters::BasicInformation::ColorEnum * primaryColor) override
546
0
    {
547
        // Our example device claims to have a nice purple color for now.  We can
548
        // make this configurable as needed.
549
0
        *primaryColor = chip::app::Clusters::BasicInformation::ColorEnum::kPurple;
550
0
        return CHIP_NO_ERROR;
551
0
    }
552
553
    // Once an attribute has been set with one of these Set methods, the
554
    // corresponding Get method will return the stored value instead of getting
555
    // the value from the default provider.
556
0
    void SetVendorName(const std::string & buf) { mVendorName = buf; }
557
0
    void SetProductName(const std::string & buf) { mProductName = buf; }
558
0
    void SetSerialNumber(const std::string & buf) { mSerialNumber = buf; }
559
0
    void SetHardwareVersionString(const std::string & buf) { mHardwareVersionString = buf; }
560
561
private:
562
    DeviceInstanceInfoProvider * mDefaultProvider;
563
564
    // Values of basic information cluster attributes that may be set from the command-line.
565
    // When GetX is called, if this has a value it will be returned instead of getting the
566
    // value from the default provider.
567
    std::optional<std::string> mVendorName;
568
    std::optional<std::string> mProductName;
569
    std::optional<std::string> mSerialNumber;
570
    std::optional<std::string> mHardwareVersionString;
571
572
    static inline bool CanFitInNullTerminatedString(const std::string & candidate, size_t bufSizeIncludingNull)
573
0
    {
574
0
        return bufSizeIncludingNull >= (candidate.size() + 1);
575
0
    }
576
};
577
578
ExampleDeviceInstanceInfoProvider gExampleDeviceInstanceInfoProvider;
579
580
int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions,
581
                     const Optional<EndpointId> secondaryNetworkCommissioningEndpoint)
582
0
{
583
0
    CHIP_ERROR err            = CHIP_NO_ERROR;
584
0
    bool isAllClustersVariant = (std::string(argv[0]).find("all-clusters") != std::string::npos);
585
0
    DeviceInstanceInfoProvider * defaultDeviceInstanceInfoProvider = nullptr;
586
587
0
#if CONFIG_NETWORK_LAYER_BLE
588
0
    RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kBLE;
589
#else  // CONFIG_NETWORK_LAYER_BLE
590
    RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kOnNetwork;
591
#endif // CONFIG_NETWORK_LAYER_BLE
592
593
#ifdef CONFIG_RENDEZVOUS_MODE
594
    rendezvousFlags = static_cast<RendezvousInformationFlags>(CONFIG_RENDEZVOUS_MODE);
595
#endif
596
597
0
    err = Platform::MemoryInit();
598
0
    SuccessOrExit(err);
599
600
0
    err = ParseArguments(argc, argv, customOptions);
601
0
    SuccessOrExit(err);
602
603
0
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
604
0
    if (LinuxDeviceOptions::GetInstance().mWiFiPAF)
605
0
    {
606
0
        rendezvousFlags.Set(RendezvousInformationFlag::kWiFiPAF);
607
0
    }
608
0
#endif
609
610
0
    sSecondaryNetworkCommissioningEndpoint = secondaryNetworkCommissioningEndpoint;
611
612
0
#ifdef CHIP_CONFIG_KVS_PATH
613
0
    if (LinuxDeviceOptions::GetInstance().KVS == nullptr)
614
0
    {
615
0
        err = DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH);
616
0
    }
617
0
    else
618
0
    {
619
0
        err = DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(LinuxDeviceOptions::GetInstance().KVS);
620
0
    }
621
0
    SuccessOrExit(err);
622
0
#endif
623
624
#if defined(ENABLE_CHIP_SHELL)
625
    /* Block SIGINT and SIGTERM. Other threads created by the main thread
626
     * will inherit the signal mask. Then we can explicitly unblock signals
627
     * in the shell thread to handle them, so the read(stdin) call can be
628
     * interrupted by a signal. */
629
    sigset_t set;
630
    sigemptyset(&set);
631
    sigaddset(&set, SIGINT);
632
    sigaddset(&set, SIGTERM);
633
    pthread_sigmask(SIG_BLOCK, &set, nullptr);
634
#endif
635
636
0
    err = DeviceLayer::PlatformMgr().InitChipStack();
637
0
    SuccessOrExit(err);
638
639
    // Init the commissionable data provider based on command line options
640
    // to handle custom verifiers, discriminators, etc.
641
0
    err = chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
642
0
    SuccessOrExit(err);
643
0
    DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider);
644
645
0
    err = chip::examples::InitConfigurationManager(reinterpret_cast<ConfigurationManagerImpl &>(ConfigurationMgr()),
646
0
                                                   LinuxDeviceOptions::GetInstance());
647
0
    SuccessOrExit(err);
648
649
0
    if (LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.HasValue())
650
0
    {
651
0
        rendezvousFlags = LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Value();
652
0
    }
653
654
0
    err = GetPayloadContents(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags);
655
0
    SuccessOrExit(err);
656
657
    // We need to set DeviceInfoProvider before Server::Init to set up the storage of DeviceInfoProvider properly.
658
0
    if (isAllClustersVariant)
659
0
    {
660
0
        DeviceLayer::SetDeviceInfoProvider(&gAllClustersExampleDeviceInfoProvider);
661
0
    }
662
0
    else
663
0
    {
664
0
        DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
665
0
    }
666
667
0
    ConfigurationMgr().LogDeviceConfig();
668
669
0
    {
670
0
        ChipLogProgress(NotSpecified, "==== Onboarding payload for Standard Commissioning Flow ====");
671
0
        PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload);
672
0
    }
673
674
#if defined(PW_RPC_ENABLED)
675
    rpc::Init(LinuxDeviceOptions::GetInstance().rpcServerPort);
676
    ChipLogProgress(NotSpecified, "PW_RPC initialized.");
677
#endif // defined(PW_RPC_ENABLED)
678
679
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0);
680
681
0
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
682
0
    if (LinuxDeviceOptions::GetInstance().traceStreamFilename.HasValue())
683
0
    {
684
0
        const char * traceFilename = LinuxDeviceOptions::GetInstance().traceStreamFilename.Value().c_str();
685
0
        auto traceStream           = new chip::trace::TraceStreamFile(traceFilename);
686
0
        chip::trace::AddTraceStream(traceStream);
687
0
    }
688
0
    else if (LinuxDeviceOptions::GetInstance().traceStreamToLogEnabled)
689
0
    {
690
0
        auto traceStream = new chip::trace::TraceStreamLog();
691
0
        chip::trace::AddTraceStream(traceStream);
692
0
    }
693
694
0
    if (LinuxDeviceOptions::GetInstance().traceStreamDecodeEnabled)
695
0
    {
696
0
        chip::trace::TraceDecoderOptions options;
697
0
        options.mEnableProtocolInteractionModelResponse = false;
698
699
0
        chip::trace::TraceDecoder * decoder = new chip::trace::TraceDecoder();
700
0
        decoder->SetOptions(options);
701
0
        chip::trace::AddTraceStream(decoder);
702
0
    }
703
0
    chip::trace::InitTrace();
704
0
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
705
706
0
#if CONFIG_NETWORK_LAYER_BLE
707
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX)
708
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(LinuxDeviceOptions::GetInstance().mBleDevice, false);
709
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
710
0
#endif
711
712
0
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
713
0
    if (LinuxDeviceOptions::GetInstance().mWiFi)
714
0
    {
715
        // Start WiFi management in Concurrent mode
716
0
        DeviceLayer::ConnectivityMgrImpl().StartWiFiManagement();
717
0
        if (!EnsureWiFiIsStarted())
718
0
        {
719
0
            ChipLogError(NotSpecified, "Wi-Fi Management taking too long to start - device configuration will be reset.");
720
0
        }
721
0
    }
722
0
#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
723
0
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
724
0
    if (LinuxDeviceOptions::GetInstance().mWiFi && LinuxDeviceOptions::GetInstance().mWiFiPAF)
725
0
    {
726
0
        ChipLogProgress(WiFiPAF, "WiFi-PAF: initialzing");
727
0
        if (EnsureWiFiIsStarted())
728
0
        {
729
0
            ChipLogProgress(WiFiPAF, "Wi-Fi Management started");
730
0
            DeviceLayer::ConnectivityManager::WiFiPAFAdvertiseParam args;
731
732
0
            args.enable        = LinuxDeviceOptions::GetInstance().mWiFiPAF;
733
0
            args.freq_list_len = WiFiPAFGet_FreqList(LinuxDeviceOptions::GetInstance().mWiFiPAFExtCmds, args.freq_list);
734
0
            TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().WiFiPAFPublish(args);
735
0
            LinuxDeviceOptions::GetInstance().mPublishId = args.publish_id;
736
0
        }
737
0
    }
738
0
#endif
739
740
#if CHIP_ENABLE_OPENTHREAD
741
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
742
    if (LinuxDeviceOptions::GetInstance().mThreadNodeId)
743
    {
744
        std::string nodeid  = std::to_string(LinuxDeviceOptions::GetInstance().mThreadNodeId);
745
        std::string logfile = "--log-file=thread.log";
746
        char * args[]       = { argv[0], logfile.data(), nodeid.data() };
747
748
        otSysInit(MATTER_ARRAY_SIZE(args), args);
749
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().InitThreadStack());
750
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().StartThreadTask());
751
        ChipLogProgress(NotSpecified, "Thread initialized.");
752
    }
753
#else
754
    if (LinuxDeviceOptions::GetInstance().mThread)
755
    {
756
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().InitThreadStack());
757
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().StartThreadTask());
758
        ChipLogProgress(NotSpecified, "Thread initialized.");
759
    }
760
#endif
761
#endif
762
763
#if CHIP_CONFIG_ENABLE_ICD_SERVER
764
    if (LinuxDeviceOptions::GetInstance().icdActiveModeDurationMs.HasValue() ||
765
        LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.HasValue() ||
766
        LinuxDeviceOptions::GetInstance().shortIdleModeDurationS.has_value())
767
    {
768
        // Convert icdIdleModeDurationMs to seconds for SetModeDurations api
769
        std::optional<System::Clock::Seconds32> tmpIdleModeDuration = std::nullopt;
770
        if (LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.HasValue())
771
            tmpIdleModeDuration = std::chrono::duration_cast<System::Clock::Seconds32>(
772
                LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.Value());
773
774
        err = Server::GetInstance().GetICDManager().SetModeDurations(
775
            LinuxDeviceOptions::GetInstance().icdActiveModeDurationMs.std_optional(), tmpIdleModeDuration,
776
            LinuxDeviceOptions::GetInstance().shortIdleModeDurationS);
777
778
        if (err != CHIP_NO_ERROR)
779
        {
780
            ChipLogError(NotSpecified, "Invalid arguments to set ICD mode durations");
781
            SuccessOrExit(err);
782
        }
783
    }
784
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
785
786
    // Initialize the ExampleDeviceInstanceInfoProvider.
787
0
    defaultDeviceInstanceInfoProvider = GetDeviceInstanceInfoProvider();
788
0
    if (defaultDeviceInstanceInfoProvider != &gExampleDeviceInstanceInfoProvider)
789
0
    {
790
0
        gExampleDeviceInstanceInfoProvider.Init(defaultDeviceInstanceInfoProvider);
791
0
        SetDeviceInstanceInfoProvider(&gExampleDeviceInstanceInfoProvider);
792
0
    }
793
794
    // Command line arguments to set attributes of the basic information cluster.
795
0
    if (LinuxDeviceOptions::GetInstance().vendorName.HasValue())
796
0
        gExampleDeviceInstanceInfoProvider.SetVendorName(LinuxDeviceOptions::GetInstance().vendorName.Value());
797
798
0
    if (LinuxDeviceOptions::GetInstance().productName.HasValue())
799
0
        gExampleDeviceInstanceInfoProvider.SetProductName(LinuxDeviceOptions::GetInstance().productName.Value());
800
801
0
    if (LinuxDeviceOptions::GetInstance().serialNumber.HasValue())
802
0
        gExampleDeviceInstanceInfoProvider.SetSerialNumber(LinuxDeviceOptions::GetInstance().serialNumber.Value());
803
804
0
    if (LinuxDeviceOptions::GetInstance().hardwareVersionString.HasValue())
805
0
        gExampleDeviceInstanceInfoProvider.SetHardwareVersionString(
806
0
            LinuxDeviceOptions::GetInstance().hardwareVersionString.Value());
807
808
0
exit:
809
0
    if (err != CHIP_NO_ERROR)
810
0
    {
811
0
        ChipLogProgress(NotSpecified, "Failed to init Linux App: %s ", ErrorStr(err));
812
0
        Cleanup();
813
814
        // End the program with non zero error code to indicate a error.
815
0
        return 1;
816
0
    }
817
0
    return 0;
818
0
}
819
820
struct LinuxCommonCaseDeviceServerInitParams final : public chip::CommonCaseDeviceServerInitParams
821
{
822
    LinuxCommonCaseDeviceServerInitParams()
823
0
    {
824
0
        SuccessOrDie(InitializeStaticResourcesBeforeServerInit());
825
0
        dataModelProvider = app::CodegenDataModelProviderInstance(persistentStorageDelegate);
826
0
    }
827
};
828
829
chip::CommonCaseDeviceServerInitParams & ChipLinuxDefaultServerInitParams()
830
0
{
831
0
    static LinuxCommonCaseDeviceServerInitParams sInitParams;
832
0
    return sInitParams;
833
0
}
834
835
void ChipLinuxAppMainLoop(chip::ServerInitParams & initParams, AppMainLoopImplementation * impl)
836
0
{
837
0
    gMainLoopImplementation = impl;
838
839
#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
840
    if (LinuxDeviceOptions::GetInstance().tcVersion.HasValue() && LinuxDeviceOptions::GetInstance().tcRequired.HasValue())
841
    {
842
        uint16_t version  = LinuxDeviceOptions::GetInstance().tcVersion.Value();
843
        uint16_t required = LinuxDeviceOptions::GetInstance().tcRequired.Value();
844
        Optional<app::TermsAndConditions> requiredAcknowledgements(app::TermsAndConditions(required, version));
845
        SuccessOrDie(
846
            app::TermsAndConditionsManager::GetInstance().Init(initParams.persistentStorageDelegate, requiredAcknowledgements));
847
    }
848
#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
849
850
#if defined(ENABLE_CHIP_SHELL)
851
    Engine::Root().Init();
852
    Shell::RegisterCommissioneeCommands();
853
    std::thread shellThread([]() {
854
        sigset_t set;
855
        sigemptyset(&set);
856
        sigaddset(&set, SIGINT);
857
        sigaddset(&set, SIGTERM);
858
        // Unblock SIGINT and SIGTERM, so that the shell thread can handle
859
        // them - we need read() call to be interrupted.
860
        pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
861
        Engine::Root().RunMainLoop();
862
        StopMainEventLoop();
863
    });
864
#endif
865
0
    initParams.operationalServicePort        = CHIP_PORT;
866
0
    initParams.userDirectedCommissioningPort = CHIP_UDC_PORT;
867
868
0
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
869
    // use a different service port to make testing possible with other sample devices running on same host
870
0
    initParams.operationalServicePort        = LinuxDeviceOptions::GetInstance().securedDevicePort;
871
0
    initParams.userDirectedCommissioningPort = LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort;
872
0
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
873
874
#if CHIP_DEVICE_CONFIG_ENABLE_PORT_RETRY
875
    // Enable automatic port retry to handle port conflicts
876
    initParams.portRetryCount = CHIP_DEVICE_CONFIG_PORT_RETRY_COUNT;
877
#endif
878
879
#if ENABLE_TRACING
880
    chip::CommandLineApp::TracingSetup tracing_setup;
881
882
    for (const auto & trace_destination : LinuxDeviceOptions::GetInstance().traceTo)
883
    {
884
        tracing_setup.EnableTracingFor(trace_destination.c_str());
885
    }
886
#endif
887
888
0
    initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId;
889
890
0
    if (LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrExistingKeyPair)
891
0
    {
892
0
        SuccessOrDie(LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest.Init(
893
0
            initParams.persistentStorageDelegate));
894
0
        initParams.operationalKeystore = &LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest;
895
0
    }
896
897
    // For general testing of TestEventTrigger, we have a common "core" event trigger delegate.
898
0
    static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate;
899
0
    static SampleTestEventTriggerHandler sTestEventTriggerHandler;
900
0
    VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(LinuxDeviceOptions::GetInstance().testEventTriggerEnableKey)) ==
901
0
                CHIP_NO_ERROR);
902
0
    VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sTestEventTriggerHandler) == CHIP_NO_ERROR);
903
904
#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_DIAGNOSTIC_TRIGGER
905
    static SoftwareDiagnosticsTestEventTriggerHandler sSoftwareDiagnosticsTestEventTriggerHandler;
906
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sSoftwareDiagnosticsTestEventTriggerHandler));
907
#endif
908
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_DIAGNOSTIC_TRIGGER
909
    static WiFiDiagnosticsTestEventTriggerHandler sWiFiDiagnosticsTestEventTriggerHandler;
910
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sWiFiDiagnosticsTestEventTriggerHandler));
911
#endif
912
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
913
    // We want to allow triggering OTA queries if OTA requestor is enabled
914
    static OTATestEventTriggerHandler sOtaTestEventTriggerHandler;
915
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler));
916
#endif
917
#if CHIP_DEVICE_CONFIG_ENABLE_SMOKE_CO_TRIGGER
918
    static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler;
919
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sSmokeCOTestEventTriggerHandler));
920
#endif
921
#if CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER
922
    static BooleanStateConfigurationTestEventTriggerHandler sBooleanStateConfigurationTestEventTriggerHandler;
923
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sBooleanStateConfigurationTestEventTriggerHandler));
924
#endif
925
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_PRICE_TRIGGER
926
    static CommodityPriceTestEventTriggerHandler sCommodityPriceTestEventTriggerHandler;
927
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sCommodityPriceTestEventTriggerHandler));
928
#endif
929
#if CHIP_DEVICE_CONFIG_ENABLE_ELECTRICAL_GRID_CONDITIONS_TRIGGER
930
    static ElectricalGridConditionsTestEventTriggerHandler sElectricalGridConditionsTestEventTriggerHandler;
931
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sElectricalGridConditionsTestEventTriggerHandler));
932
#endif
933
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_TARIFF_TRIGGER
934
    static CommodityTariffTestEventTriggerHandler sCommodityTariffTestEventTriggerHandler;
935
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sCommodityTariffTestEventTriggerHandler));
936
#endif
937
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
938
    static EnergyEvseTestEventTriggerHandler sEnergyEvseTestEventTriggerHandler;
939
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sEnergyEvseTestEventTriggerHandler));
940
#endif
941
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
942
    static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler;
943
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler));
944
#endif
945
#if CHIP_DEVICE_CONFIG_ENABLE_METER_IDENTIFICATION_TRIGGER
946
    static MeterIdentificationTestEventTriggerHandler sMeterIdentificationTestEventTriggerHandler;
947
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sMeterIdentificationTestEventTriggerHandler));
948
#endif
949
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
950
    static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler;
951
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler));
952
#endif
953
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
954
    static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler;
955
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler));
956
#endif
957
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_METERING_TRIGGER
958
    static CommodityMeteringTestEventTriggerHandler CommodityMeteringTestEventTriggerHandler;
959
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&CommodityMeteringTestEventTriggerHandler));
960
#endif
961
#if CHIP_CONFIG_ENABLE_ICD_SERVER
962
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&Server::GetInstance().GetICDManager()));
963
#endif
964
965
0
    initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate;
966
967
0
    chip::app::RuntimeOptionsProvider::Instance().SetSimulateNoInternalTime(
968
0
        LinuxDeviceOptions::GetInstance().mSimulateNoInternalTime);
969
970
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
971
    initParams.accessRestrictionProvider = exampleAccessRestrictionProvider.get();
972
#endif
973
974
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
975
    chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
976
    nativeParams.lockCb                = []() { chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); };
977
    nativeParams.unlockCb              = []() { chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); };
978
    nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
979
    initParams.endpointNativeParams    = static_cast<void *>(&nativeParams);
980
#endif
981
0
    if (LinuxDeviceOptions::GetInstance().payload.commissioningFlow == CommissioningFlow::kUserActionRequired)
982
0
    {
983
0
        initParams.advertiseCommissionableIfNoFabrics = false;
984
0
    }
985
986
    // Init ZCL Data Model and CHIP App Server
987
0
    CHIP_ERROR err = Server::GetInstance().Init(initParams);
988
0
    if (err != CHIP_NO_ERROR)
989
0
    {
990
0
        ChipLogError(AppServer, "Server init failed: %" CHIP_ERROR_FORMAT, err.Format());
991
0
        chipDie();
992
0
    }
993
994
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
995
    if (LinuxDeviceOptions::GetInstance().commissioningArlEntries.HasValue())
996
    {
997
        SuccessOrDie(exampleAccessRestrictionProvider->SetCommissioningEntries(
998
            LinuxDeviceOptions::GetInstance().commissioningArlEntries.Value()));
999
    }
1000
1001
    if (LinuxDeviceOptions::GetInstance().arlEntries.HasValue())
1002
    {
1003
        // This example use of the ARL feature proactively installs the provided entries on fabric index 1
1004
        SuccessOrDie(exampleAccessRestrictionProvider->SetEntries(1, LinuxDeviceOptions::GetInstance().arlEntries.Value()));
1005
    }
1006
#endif
1007
0
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
1008
0
    if (Server::GetInstance().GetFabricTable().FabricCount() != 0)
1009
0
    {
1010
0
        ChipLogProgress(AppServer, "Fabric already commissioned. Canceling publishing");
1011
        // TODO #40789: Should we just NOT call WiFiPAFShutdown at startup and instead make sure that WiFiPAF is not published at
1012
        // all? or Change the handling within WiFiPAFShutdown?
1013
        // TODO #40814: Check the Return Value of the call to WiFiPAFShutdown
1014
0
        TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().WiFiPAFShutdown(LinuxDeviceOptions::GetInstance().mPublishId,
1015
0
                                                                                chip::WiFiPAF::WiFiPafRole::kWiFiPafRole_Publisher);
1016
0
    }
1017
0
#endif
1018
1019
0
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
1020
    // Set ReadHandler Capacity for Subscriptions
1021
0
    chip::app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForSubscriptions(
1022
0
        LinuxDeviceOptions::GetInstance().subscriptionCapacity);
1023
0
    chip::app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(true);
1024
0
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1025
    // Set subscription time resumption retry interval seconds
1026
0
    chip::app::InteractionModelEngine::GetInstance()->SetSubscriptionTimeoutResumptionRetryIntervalSeconds(
1027
0
        LinuxDeviceOptions::GetInstance().subscriptionResumptionRetryIntervalSec);
1028
0
#endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1029
0
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
1030
1031
    // Now that the server has started and we are done with our startup logging,
1032
    // log our discovery/onboarding information again so it's not lost in the
1033
    // noise.
1034
0
    ConfigurationMgr().LogDeviceConfig();
1035
1036
0
    PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload);
1037
1038
    // Initialize device attestation config
1039
0
    SetDeviceAttestationCredentialsProvider(LinuxDeviceOptions::GetInstance().dacProvider);
1040
1041
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1042
    ChipLogProgress(AppServer, "Starting commissioner");
1043
    VerifyOrReturn(InitCommissioner(LinuxDeviceOptions::GetInstance().securedCommissionerPort,
1044
                                    LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort,
1045
                                    LinuxDeviceOptions::GetInstance().commissionerFabricId) == CHIP_NO_ERROR);
1046
    ChipLogProgress(AppServer, "Started commissioner");
1047
#if defined(ENABLE_CHIP_SHELL)
1048
    Shell::RegisterControllerCommands();
1049
#endif // defined(ENABLE_CHIP_SHELL)
1050
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1051
1052
0
    InitNetworkCommissioning();
1053
1054
0
    ApplicationInit();
1055
1056
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
1057
#if CHIP_SYSTEM_CONFIG_USE_DISPATCH
1058
    auto & platformMgr = chip::DeviceLayer::PlatformMgrImpl();
1059
    platformMgr.RegisterSignalHandler(SIGINT, ^{
1060
        platformMgr.UnregisterAllSignalHandlers();
1061
        StopSignalHandler(SIGINT);
1062
    });
1063
1064
    platformMgr.RegisterSignalHandler(SIGTERM, ^{
1065
        platformMgr.UnregisterAllSignalHandlers();
1066
        StopSignalHandler(SIGTERM);
1067
    });
1068
#else
1069
    // NOTE: For some reason, on Darwin, the signal handler is not called if the signal is
1070
    //       registered with sigaction() call and TSAN is enabled. The problem seems to be
1071
    //       related with the dispatch_semaphore_wait() function in the RunEventLoop() method.
1072
    //       If this call is commented out, the signal handler is called as expected...
1073
    // NOLINTBEGIN(bugprone-signal-handler)
1074
    signal(SIGINT, StopSignalHandler);
1075
    signal(SIGTERM, StopSignalHandler);
1076
    // NOLINTEND(bugprone-signal-handler)
1077
#endif
1078
#else
1079
0
    struct sigaction sa                        = {};
1080
0
    sa.sa_handler                              = StopSignalHandler;
1081
0
    sa.sa_flags                                = SA_RESETHAND;
1082
0
    sigaction(SIGINT, &sa, nullptr);
1083
0
    sigaction(SIGTERM, &sa, nullptr);
1084
0
#endif
1085
1086
    // This message is used as a marker for when the application process has started.
1087
    // See: scripts/tests/chiptest/test_definition.py
1088
    // TODO: A cleaner and more generic mechanism needs to be developed as a follow-up.
1089
    // Currently other places (OTA, TV) also scrape logs for information and a better way should be
1090
    // possible.
1091
0
    ChipLogProgress(DeviceLayer, "===== APP STATUS: Starting event loop =====");
1092
0
    if (impl != nullptr)
1093
0
    {
1094
0
        impl->RunMainLoop();
1095
0
    }
1096
0
    else
1097
0
    {
1098
0
        DeviceLayer::PlatformMgr().RunEventLoop();
1099
0
    }
1100
0
    gMainLoopImplementation = nullptr;
1101
1102
0
    ApplicationShutdown();
1103
1104
#if defined(ENABLE_CHIP_SHELL)
1105
    shellThread.join();
1106
#endif
1107
1108
0
    Server::GetInstance().Shutdown();
1109
1110
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1111
    // Commissioner shutdown call shuts down entire stack, including the platform manager.
1112
    ShutdownCommissioner();
1113
#else
1114
0
    DeviceLayer::PlatformMgr().Shutdown();
1115
0
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1116
1117
#if ENABLE_TRACING
1118
    tracing_setup.StopTracing();
1119
#endif
1120
1121
0
    Cleanup();
1122
0
}