aws iot sample: add a config file option to get settings for the sample
The application uses 'libconfuse' to read the settings from the provided configuration file with the option '-c'. By default, the application looks for the '/etc/awsiotsdk.conf' file. https://jira.digi.com/browse/DEL-4149 Signed-off-by: Tatiana Leon <tatiana.leon@digi.com>
This commit is contained in:
parent
cbbe31f11e
commit
dc2599fd28
|
|
@ -25,7 +25,9 @@ CFLAGS += $(LOG_FLAGS)
|
||||||
CFLAGS += -DGIT_REVISION=\"$(if $(GIT_REVISION),-g$(GIT_REVISION))\"
|
CFLAGS += -DGIT_REVISION=\"$(if $(GIT_REVISION),-g$(GIT_REVISION))\"
|
||||||
|
|
||||||
CFLAGS += $(shell pkg-config --cflags awsiotsdk)
|
CFLAGS += $(shell pkg-config --cflags awsiotsdk)
|
||||||
|
CFLAGS += $(shell pkg-config --cflags libconfuse)
|
||||||
LDLIBS += $(shell pkg-config --libs --static awsiotsdk)
|
LDLIBS += $(shell pkg-config --libs --static awsiotsdk)
|
||||||
|
LDLIBS += $(shell pkg-config --libs --static libconfuse)
|
||||||
|
|
||||||
SRCS = $(wildcard $(SRC)/*.c)
|
SRCS = $(wildcard $(SRC)/*.c)
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#===============================================================================
|
||||||
|
# AWS IoT Device SDK Settings
|
||||||
|
#===============================================================================
|
||||||
|
|
||||||
|
# Thing Name: Thing Name of the Shadow this device is associated with.
|
||||||
|
# A thing is the representation and record of your physical device in the cloud.
|
||||||
|
# Any physical device needs a thing to work with AWS IoT. Creating a thing will
|
||||||
|
# also create a thing shadow.
|
||||||
|
thing_name = ""
|
||||||
|
|
||||||
|
# Client ID: MQTT client ID should be unique for every device.
|
||||||
|
# By default, it is the same as 'thing_name'.
|
||||||
|
#client_id = ""
|
||||||
|
|
||||||
|
# Host: Customer specific MQTT HOST.
|
||||||
|
# This is your custom endpoint that allows your device to connect to AWS IoT.
|
||||||
|
# You can obtain it in your 'AWS IoT Console':
|
||||||
|
# 1. From the dashboard, in the left navigation pane, choose 'Registry' and
|
||||||
|
# then choose 'Things'.
|
||||||
|
# 2. Select the box representing your device to show its details page.
|
||||||
|
# 3. On the details page, in the left navigation pane, choose 'Interact'
|
||||||
|
# 4. Look for the HTTPS section, your endpoint will look something like:
|
||||||
|
# ABCDEFG1234567.iot.us-east-2.amazonaws.com
|
||||||
|
# where 'ABCDEFG1234567' is the subdomain and 'us-east-2' is the region.
|
||||||
|
host = ""
|
||||||
|
|
||||||
|
# Port: Default port for MQTT/S.
|
||||||
|
# By default, 8883.
|
||||||
|
port = 8883
|
||||||
|
|
||||||
|
# Certificates path: Absolute path to the certificates directory in the device.
|
||||||
|
# By default, '/etc/ssl/certs'.
|
||||||
|
certs_path = "/etc/ssl/certs"
|
||||||
|
|
||||||
|
# Root CA file name: Name of the Root CA file located in the configured
|
||||||
|
# 'certs_path'.
|
||||||
|
# By default, 'rootCA.crt'
|
||||||
|
rootca_filename = "rootCA.crt"
|
||||||
|
|
||||||
|
# Signed certificate file name: Name of the device signed certificate file
|
||||||
|
# located in the configured 'certs_path'.
|
||||||
|
# By default, 'cert.pem'
|
||||||
|
signed_cert_filename = "cert.pem"
|
||||||
|
|
||||||
|
# Device private key filename: Name of the device private key file located in
|
||||||
|
# the configured 'certs_path'.
|
||||||
|
# By default, 'privkey.pem'
|
||||||
|
private_key_filename = "privkey.pem"
|
||||||
|
|
||||||
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <aws_iot_config.h>
|
||||||
|
#include <aws_iot_log.h>
|
||||||
|
#include <confuse.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "aws_config.h"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#define SETTING_THING_NAME "thing_name"
|
||||||
|
#define SETTING_CLIENT_ID "client_id"
|
||||||
|
#define SETTING_HOST "host"
|
||||||
|
#define SETTING_PORT "port"
|
||||||
|
#define SETTING_CERTS_PATH "certs_path"
|
||||||
|
#define SETTING_ROOTCA_NAME "rootca_filename"
|
||||||
|
#define SETTING_SCERT_NAME "signed_cert_filename"
|
||||||
|
#define SETTING_PRIVKEY_NAME "private_key_filename"
|
||||||
|
|
||||||
|
#define SETTING_UNKNOWN "__unknown"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
static int fill_aws_iot_config(aws_iot_cfg_t *aws_cfg);
|
||||||
|
static int cfg_check_thing_name(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_client_id(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_port(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_certificates_path(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_cert_file(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_int_range(cfg_t *cfg, cfg_opt_t *opt, uint32_t min, uint32_t max);
|
||||||
|
static int cfg_check_empty_string(cfg_t *cfg, cfg_opt_t *opt);
|
||||||
|
static int cfg_check_string_length(cfg_t *cfg, cfg_opt_t *opt, uint16_t min, uint16_t max);
|
||||||
|
static int file_exists(const char *const filename);
|
||||||
|
static int file_readable(const char *const filename);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
G L O B A L V A R I A B L E S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
static cfg_t *cfg;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
* parse_configuration() - Parse and save the settings of a configuration file
|
||||||
|
*
|
||||||
|
* @filename: Name of the file containing the configuration settings.
|
||||||
|
* @aws_cfg: AWS IoT Device SDK configuration struct (aws_iot_cfg_t) where
|
||||||
|
* the settings parsed from the configuration file are saved.
|
||||||
|
*
|
||||||
|
* Read the provided configuration file and save the settings in the given
|
||||||
|
* aws_iot_cfg_t struct. If the file does not exist or cannot be read, the
|
||||||
|
* configuration struct is initialized with the default settings.
|
||||||
|
*
|
||||||
|
* Return: 0 if the file is parsed successfully, -1 if there is an error
|
||||||
|
* parsing the file.
|
||||||
|
*/
|
||||||
|
int parse_configuration(const char *const filename, aws_iot_cfg_t *aws_cfg)
|
||||||
|
{
|
||||||
|
/* Overall structure of the settings. */
|
||||||
|
static cfg_opt_t opts[] = {
|
||||||
|
/* --------------------------------------------------------------------- */
|
||||||
|
/*| TYPE | SETTING NAME | DEFAULT VALUE | FLAGS |*/
|
||||||
|
/* --------------------------------------------------------------------- */
|
||||||
|
CFG_STR (SETTING_THING_NAME, AWS_IOT_MY_THING_NAME, CFGF_NONE),
|
||||||
|
CFG_STR (SETTING_CLIENT_ID, AWS_IOT_MQTT_CLIENT_ID, CFGF_NONE),
|
||||||
|
CFG_STR (SETTING_HOST, AWS_IOT_MQTT_HOST, CFGF_NONE),
|
||||||
|
CFG_INT (SETTING_PORT, AWS_IOT_MQTT_PORT, CFGF_NONE),
|
||||||
|
|
||||||
|
CFG_STR (SETTING_CERTS_PATH, DEFAULT_CERTS_PATH, CFGF_NONE),
|
||||||
|
CFG_STR (SETTING_ROOTCA_NAME, AWS_IOT_ROOT_CA_FILENAME,CFGF_NONE),
|
||||||
|
CFG_STR (SETTING_SCERT_NAME, AWS_IOT_CERTIFICATE_FILENAME,CFGF_NONE),
|
||||||
|
CFG_STR (SETTING_PRIVKEY_NAME, AWS_IOT_PRIVATE_KEY_FILENAME,CFGF_NONE),
|
||||||
|
|
||||||
|
/* Needed for unknown settings. */
|
||||||
|
CFG_STR (SETTING_UNKNOWN, NULL, CFGF_NONE),
|
||||||
|
CFG_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!file_exists(filename)) {
|
||||||
|
IOT_ERROR("File '%s' does not exist.", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_readable(filename)) {
|
||||||
|
IOT_ERROR("File '%s' cannot be read.", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg = cfg_init(opts, CFGF_IGNORE_UNKNOWN);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_THING_NAME, cfg_check_thing_name);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_CLIENT_ID, cfg_check_client_id);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_HOST, cfg_check_empty_string);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_PORT, cfg_check_port);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_CERTS_PATH, cfg_check_certificates_path);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_ROOTCA_NAME, cfg_check_cert_file);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_SCERT_NAME, cfg_check_cert_file);
|
||||||
|
cfg_set_validate_func(cfg, SETTING_PRIVKEY_NAME, cfg_check_cert_file);
|
||||||
|
|
||||||
|
/* Parse the configuration file. */
|
||||||
|
switch (cfg_parse(cfg, filename)) {
|
||||||
|
case CFG_FILE_ERROR:
|
||||||
|
IOT_ERROR("Configuration file '%s' could not be read: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
case CFG_SUCCESS:
|
||||||
|
break;
|
||||||
|
case CFG_PARSE_ERROR:
|
||||||
|
IOT_ERROR("Error parsing configuration file '%s'\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fill_aws_iot_config(aws_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free_configuration() - Release the configuration var
|
||||||
|
*/
|
||||||
|
void free_configuration(void)
|
||||||
|
{
|
||||||
|
cfg_free(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill_aws_iot_config() - Fill the AWS IoT Device SDK configuration struct
|
||||||
|
*
|
||||||
|
* @aws_cfg: AWS IoT Device SDK configuration struct (aws_iot_cfg_t).
|
||||||
|
*
|
||||||
|
* Return: 0 if the configuration is filled successfully, -1 otherwise.
|
||||||
|
*/
|
||||||
|
static int fill_aws_iot_config(aws_iot_cfg_t *aws_cfg)
|
||||||
|
{
|
||||||
|
aws_cfg->thing_name = cfg_getstr(cfg, SETTING_THING_NAME);
|
||||||
|
if (aws_cfg->thing_name == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->client_id = cfg_getstr(cfg, SETTING_CLIENT_ID);
|
||||||
|
if (aws_cfg->client_id == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->host = cfg_getstr(cfg, SETTING_HOST);
|
||||||
|
if (aws_cfg->host == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->port = cfg_getint(cfg, SETTING_PORT);
|
||||||
|
aws_cfg->certs_path = cfg_getstr(cfg, SETTING_CERTS_PATH);
|
||||||
|
if (aws_cfg->certs_path == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->rootca_fname = cfg_getstr(cfg, SETTING_ROOTCA_NAME);
|
||||||
|
if (aws_cfg->rootca_fname == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->signed_cert_fname = cfg_getstr(cfg, SETTING_SCERT_NAME);
|
||||||
|
if (aws_cfg->signed_cert_fname == NULL)
|
||||||
|
return -1;
|
||||||
|
aws_cfg->priv_key_fname = cfg_getstr(cfg, SETTING_PRIVKEY_NAME);
|
||||||
|
if (aws_cfg->priv_key_fname == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_thing_name() - Validate thing_name in the configuration file
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_thing_name(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_string_length(cfg, opt, 1, MAX_SIZE_OF_THING_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_client_id() - Validate client_id in the configuration file
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_client_id(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_string_length(cfg, opt, 1, MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_port() - Validate port is between 0 and 65535
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_port(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_int_range(cfg, opt, 0, 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_certificates_path() - Validate certs_path value
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_certificates_path(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
DIR *dir = NULL;
|
||||||
|
char *val = cfg_opt_getnstr(opt, 0);
|
||||||
|
|
||||||
|
dir = opendir(val);
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s: cannot find directory '%s'",
|
||||||
|
opt->name, val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_cert_file() - Validate certificate file name value
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_cert_file(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
char *certs_path = NULL;
|
||||||
|
char *file_path = NULL;
|
||||||
|
char *val = cfg_opt_getnstr(opt, 0);
|
||||||
|
|
||||||
|
if (cfg_check_string_length(cfg, opt, 1, 0) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
certs_path = cfg_getstr(cfg, SETTING_CERTS_PATH);
|
||||||
|
if (certs_path == NULL) {
|
||||||
|
cfg_error(cfg, "Invalid %s: NULL value", SETTING_CERTS_PATH);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_path = calloc(1, sizeof(*file_path) * (strlen(certs_path) + strlen(val) + 2));
|
||||||
|
if (file_path == NULL) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Error checking %s: unable to allocate memory",
|
||||||
|
opt->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sprintf(file_path, "%s/%s", certs_path, val);
|
||||||
|
|
||||||
|
if (!file_readable(file_path)) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s: cannot find file '%s'", opt->name, val);
|
||||||
|
free(file_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_int_range() - Validate a parameter int value is between the given range
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
* @min: Minimum value of the parameter.
|
||||||
|
* @max: Maximum value of the parameter.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_int_range(cfg_t *cfg, cfg_opt_t *opt, uint32_t min, uint32_t max)
|
||||||
|
{
|
||||||
|
unsigned long val = cfg_opt_getnint(opt, 0);
|
||||||
|
|
||||||
|
if (val > max || val < min) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s (%d): value must be between %d and %d",
|
||||||
|
opt->name, val, min, max);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_empty_string() - Validate string is empty
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_empty_string(cfg_t *cfg, cfg_opt_t *opt)
|
||||||
|
{
|
||||||
|
return cfg_check_string_length(cfg, opt, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cfg_check_string_length() - Validate the length of a string is in range
|
||||||
|
*
|
||||||
|
* @cfg: The section where the option is defined.
|
||||||
|
* @opt: The option to check.
|
||||||
|
* @min: The string minimum length.
|
||||||
|
* @max: The string maximum length. 0 to unlimited.
|
||||||
|
*
|
||||||
|
* @Return: 0 on success, any other value otherwise.
|
||||||
|
*/
|
||||||
|
static int cfg_check_string_length(cfg_t *cfg, cfg_opt_t *opt, uint16_t min, uint16_t max)
|
||||||
|
{
|
||||||
|
char *val = cfg_opt_getnstr(opt, 0);
|
||||||
|
|
||||||
|
if ((val == NULL) || ((strlen(val) == 0) && (min > 0))) {
|
||||||
|
cfg_error(cfg, "Invalid %s (%s): cannot be empty", opt->name, val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strlen(val) < min) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s (%s): cannot be shorter than %d character(s)",
|
||||||
|
opt->name, val, min);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (max != 0 && strlen(val) > max) {
|
||||||
|
cfg_error(cfg,
|
||||||
|
"Invalid %s (%s): cannot be longer than %d character(s)",
|
||||||
|
opt->name, val, max);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file_exists() - Check that the file with the given name exists
|
||||||
|
*
|
||||||
|
* @filename: Full path of the file to check if it exists.
|
||||||
|
*
|
||||||
|
* Return: 1 if the file exits, 0 if it does not exist.
|
||||||
|
*/
|
||||||
|
static int file_exists(const char *const filename)
|
||||||
|
{
|
||||||
|
return access(filename, F_OK) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file_readable() - Check that the file with the given name can be read
|
||||||
|
*
|
||||||
|
* @filename: Full path of the file to check if it is readable.
|
||||||
|
*
|
||||||
|
* Return: 1 if the file is readable, 0 if it cannot be read.
|
||||||
|
*/
|
||||||
|
static int file_readable(const char *const filename)
|
||||||
|
{
|
||||||
|
return access(filename, R_OK) == 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Digi International Inc.
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AWS_CONFIG_H_
|
||||||
|
#define AWS_CONFIG_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
#define AWS_IOT_CONFIG_FILE "/etc/awsiotsdk.conf"
|
||||||
|
#define DEFAULT_CERTS_PATH "/etc/ssl/certs"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
D A T A T Y P E S D E F I N I T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* aws_iot_cfg_t - AWS IoT Device SDK configuration type
|
||||||
|
*
|
||||||
|
* @thing_name: Thing Name of the Shadow this device is associated with
|
||||||
|
* @client_id: MQTT client ID. It should be unique for every device
|
||||||
|
* @host: MQTT host
|
||||||
|
* @port: Port for MQTT/S
|
||||||
|
* @certs_path: Absolute path to the certificates directory
|
||||||
|
* @rootca_fname: Name of the Root CA file
|
||||||
|
* @signed_cert_fname: Name of the device signed certificate
|
||||||
|
* @priv_key_fname: Name of the device private key
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
char *thing_name;
|
||||||
|
char *client_id;
|
||||||
|
char *host;
|
||||||
|
int port;
|
||||||
|
char *certs_path;
|
||||||
|
char *rootca_fname;
|
||||||
|
char *signed_cert_fname;
|
||||||
|
char *priv_key_fname;
|
||||||
|
} aws_iot_cfg_t;
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
F U N C T I O N D E C L A R A T I O N S
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
int parse_configuration(const char *const filename, aws_iot_cfg_t *aws_cfg);
|
||||||
|
void free_configuration(void);
|
||||||
|
|
||||||
|
#endif /* AWS_CONFIG_H_ */
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "aws_config.h"
|
||||||
#include "daemonize.h"
|
#include "daemonize.h"
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
|
@ -38,6 +39,8 @@
|
||||||
"\n" \
|
"\n" \
|
||||||
"Usage: %s [options]\n\n" \
|
"Usage: %s [options]\n\n" \
|
||||||
" -d --daemon Daemonize the process\n" \
|
" -d --daemon Daemonize the process\n" \
|
||||||
|
" -c --config-file=<PATH> Use a custom configuration file instead of\n" \
|
||||||
|
" the default one located in " AWS_IOT_CONFIG_FILE "\n" \
|
||||||
" -h --help Print help and exit\n" \
|
" -h --help Print help and exit\n" \
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
|
|
@ -66,9 +69,10 @@ int main(int argc, char **argv)
|
||||||
static int opt, opt_index;
|
static int opt, opt_index;
|
||||||
int create_daemon = 0;
|
int create_daemon = 0;
|
||||||
char *config_file = NULL;
|
char *config_file = NULL;
|
||||||
static const char *short_options = "dh";
|
static const char *short_options = "dc:h";
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{"daemon", no_argument, NULL, 'd'},
|
{"daemon", no_argument, NULL, 'd'},
|
||||||
|
{"config-file", required_argument, NULL, 'c'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
@ -83,6 +87,9 @@ int main(int argc, char **argv)
|
||||||
case 'd':
|
case 'd':
|
||||||
create_daemon = 1;
|
create_daemon = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(name);
|
usage(name);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -119,9 +126,13 @@ done:
|
||||||
static int start_aws_iot(const char *config_file)
|
static int start_aws_iot(const char *config_file)
|
||||||
{
|
{
|
||||||
int result = EXIT_SUCCESS;
|
int result = EXIT_SUCCESS;
|
||||||
|
aws_iot_cfg_t aws_cfg;
|
||||||
|
|
||||||
add_sigkill_signal();
|
add_sigkill_signal();
|
||||||
|
|
||||||
|
if (parse_configuration(config_file ? config_file : AWS_IOT_CONFIG_FILE, &aws_cfg) != 0)
|
||||||
|
return EXIT_FAILURE;;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
} while (!check_stop());
|
} while (!check_stop());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue