int main()

in source/main.cpp [269:463]


int main(int argc, char *argv[])
{
    CliArgs cliArgs;
    if (!Config::ParseCliArgs(argc, argv, cliArgs) || !config.init(cliArgs))
    {
        LoggerFactory::getLoggerInstance()->shutdown();
        return 0;
    }

    if (!LoggerFactory::reconfigure(config.config) &&
        dynamic_cast<StdOutLogger *>(LoggerFactory::getLoggerInstance().get()) == nullptr)
    {
        // We attempted to start a non-stdout logger and failed, so we should fall back to STDOUT
        config.config.logConfig.deviceClientLogtype = config.config.logConfig.LOG_TYPE_STDOUT;
        LoggerFactory::reconfigure(config.config);
    }

    EnvUtils envUtils;
    if (envUtils.AppendCwdToPath())
    {
        // Failure to append current working directory is not a fatal error,
        // but some features of device client such as standard job action
        // might not work without explicitly setting path to handler in job document.
        LOG_WARN(TAG, "Unable to append current working directory to PATH environment variable.");
    }

    LOGM_INFO(TAG, "Now running AWS IoT Device Client version %s", DEVICE_CLIENT_VERSION_FULL);

    // Register for listening to interrupt signals
    sigset_t sigset;
    memset(&sigset, 0, sizeof(sigset_t));
    int received_signal;
    sigaddset(&sigset, SIGINT);
    sigprocmask(SIG_BLOCK, &sigset, 0);

    shared_ptr<DefaultClientBaseNotifier> listener =
        shared_ptr<DefaultClientBaseNotifier>(new DefaultClientBaseNotifier);
    resourceManager = shared_ptr<SharedCrtResourceManager>(new SharedCrtResourceManager);
    if (!resourceManager.get()->initialize(config.config, &features))
    {
        LOGM_ERROR(TAG, "*** %s: Failed to initialize AWS CRT SDK.", DC_FATAL_ERROR);
        LoggerFactory::getLoggerInstance()->shutdown();
        deviceClientAbort("Failed to initialize AWS CRT SDK");
    }

#if !defined(EXCLUDE_FP)
    if (config.config.fleetProvisioning.enabled &&
        !config.config.fleetProvisioningRuntimeConfig.completedFleetProvisioning)
    {

        /*
         * Establish MQTT connection using claim certificates and private key to provision the device/thing.
         */
#    if !defined(DISABLE_MQTT)
        attemptConnection();
#    endif

        /*
         * Provision Device, parse new runtime conf file and validate its content.
         */
        FleetProvisioning fleetProvisioning;
        if (!fleetProvisioning.ProvisionDevice(resourceManager, config.config) ||
            !config.ParseConfigFile(Config::DEFAULT_FLEET_PROVISIONING_RUNTIME_CONFIG_FILE, true) ||
            !config.ValidateAndStoreRuntimeConfig())
        {
            LOGM_ERROR(
                TAG,
                "*** %s: Failed to Provision thing or validate newly created resources. "
                "Please verify your AWS IoT credentials, "
                "configuration, Fleet Provisioning Template, claim certificate and policy used. ***",
                DC_FATAL_ERROR);
            LoggerFactory::getLoggerInstance()->shutdown();
            deviceClientAbort("Fleet provisioning failed");
        }
        resourceManager->disconnect();
    }
#endif
    /*
     * Establish MQTT connection using permanent certificate and private key to start and run AWS IoT Device Client
     * features.
     */
#if !defined(DISABLE_MQTT)
    attemptConnection();
#endif

#if !defined(EXCLUDE_SHADOW)
#    if !defined(EXCLUDE_CONFIG_SHADOW)
    if (config.config.configShadow.enabled)
    {
        LOG_INFO(TAG, "Config shadow is enabled");
        ConfigShadow configShadow;
        configShadow.reconfigureWithConfigShadow(resourceManager, config.config);
        resourceManager->disconnect();
        attemptConnection();
    }
#    endif
#endif

    featuresReadWriteLock.lock(); // LOCK

#if !defined(EXCLUDE_JOBS)
    unique_ptr<JobsFeature> jobs;
    if (config.config.jobs.enabled)
    {
        LOG_INFO(TAG, "Jobs is enabled");
        jobs = unique_ptr<JobsFeature>(new JobsFeature());
        jobs->init(resourceManager, listener, config.config);
        features.push_back(jobs.get());
    }
    else
    {
        LOG_INFO(TAG, "Jobs is disabled");
    }
#endif

#if !defined(EXCLUDE_ST)
    unique_ptr<SecureTunnelingFeature> tunneling;
    if (config.config.tunneling.enabled)
    {
        LOG_INFO(TAG, "Secure Tunneling is enabled");
        tunneling = unique_ptr<SecureTunnelingFeature>(new SecureTunnelingFeature());
        tunneling->init(resourceManager, listener, config.config);
        features.push_back(tunneling.get());
    }
    else
    {
        LOG_INFO(TAG, "Secure Tunneling is disabled");
    }
#endif

#if !defined(EXCLUDE_DD)
    unique_ptr<DeviceDefenderFeature> deviceDefender;
    if (config.config.deviceDefender.enabled)
    {
        LOG_INFO(TAG, "Device Defender is enabled");
        deviceDefender = unique_ptr<DeviceDefenderFeature>(new DeviceDefenderFeature());
        deviceDefender->init(resourceManager, listener, config.config);
        features.push_back(deviceDefender.get());
    }
    else
    {
        LOG_INFO(TAG, "Device Defender is disabled");
    }
#endif

#if !defined(EXCLUDE_SHADOW)
#    if !defined(EXCLUDE_SAMPLE_SHADOW)
    unique_ptr<SampleShadowFeature> sampleShadow;
    if (config.config.sampleShadow.enabled)
    {
        LOG_INFO(TAG, "Sample shadow is enabled");
        sampleShadow = unique_ptr<SampleShadowFeature>(new SampleShadowFeature());
        sampleShadow->init(resourceManager, listener, config.config);
        features.push_back(sampleShadow.get());
    }
    else
    {
        LOG_INFO(TAG, "Sample shadow is disabled");
    }
#    endif
#endif

#if !defined(EXCLUDE_SAMPLES)
#    if !defined(EXCLUDE_PUBSUB)
    unique_ptr<PubSubFeature> pubSub;
    if (config.config.pubSub.enabled)
    {
        LOG_INFO(TAG, "PubSub is enabled");
        pubSub = unique_ptr<PubSubFeature>(new PubSubFeature());
        pubSub->init(resourceManager, listener, config.config);
        features.push_back(pubSub.get());
    }
    else
    {
        LOG_INFO(TAG, "Pub Sub is disabled");
    }
#    endif
#endif

    resourceManager->startDeviceClientFeatures();
    featuresReadWriteLock.unlock(); // UNLOCK

    // Now allow this thread to sleep until it's interrupted by a signal
    while (true)
    {
        sigwait(&sigset, &received_signal);
        LOGM_INFO(TAG, "Received signal: (%d)", received_signal);
        if (SIGINT == received_signal)
        {
            shutdown();
        }
    }

    return 0;
}