From 2a99fa1591d6bb852234fc3657e9b575b8c3122d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Thu, 5 Sep 2019 17:32:15 +0300 Subject: [PATCH] samples: google_iot_device: Remove "command line" and replace with config.c (#8) * samples: google_iot_device: Remove "command line" and replace with config.c There is no "command line" in Zephyr RTOS. "Command line" which was used previously is an artifact of a special-purpose, testing target "native_posix", not portable to any other Zephyr target. So, instead provide config.c file, where a user can define all needed application parameters (which previously were passed on "command line"). As such a file contain credentials, it should be never put under version control. This commit includes a template file, config.c.in, which can be copied by a user to config.c, and required values filled in. Signed-off-by: Paul Sokolovsky * samples: google_iot_device: README: Update for moving from cmdline to config.c Signed-off-by: Paul Sokolovsky --- samples/net/google_iot_device/CMakeLists.txt | 2 +- samples/net/google_iot_device/README.rst | 12 +- .../net/google_iot_device/src/commandline.c | 161 ------------------ .../net/google_iot_device/src/commandline.h | 23 --- samples/net/google_iot_device/src/config.c.in | 24 +++ samples/net/google_iot_device/src/config.h | 18 ++ .../net/google_iot_device/src/example_utils.c | 86 +--------- .../net/google_iot_device/src/example_utils.h | 15 +- samples/net/google_iot_device/src/main.c | 37 +--- 9 files changed, 60 insertions(+), 318 deletions(-) delete mode 100644 samples/net/google_iot_device/src/commandline.c delete mode 100644 samples/net/google_iot_device/src/commandline.h create mode 100644 samples/net/google_iot_device/src/config.c.in create mode 100644 samples/net/google_iot_device/src/config.h diff --git a/samples/net/google_iot_device/CMakeLists.txt b/samples/net/google_iot_device/CMakeLists.txt index 0d456765b635..28804db6118f 100644 --- a/samples/net/google_iot_device/CMakeLists.txt +++ b/samples/net/google_iot_device/CMakeLists.txt @@ -22,7 +22,7 @@ add_compile_definitions(IOTC_DISABLE_CERTVERIFY) target_sources(app PRIVATE src/main.c - src/commandline.c + src/config.c src/example_utils.c src/bsp/iotc_bsp_tls_mbedtls.c src/bsp/iotc_bsp_crypto_mbedtls.c diff --git a/samples/net/google_iot_device/README.rst b/samples/net/google_iot_device/README.rst index 100c8db5661b..e39f114845c4 100644 --- a/samples/net/google_iot_device/README.rst +++ b/samples/net/google_iot_device/README.rst @@ -90,16 +90,10 @@ in a Zephyr github repo clone in github/atigyi account - `west update` - `export ZEPHYR_TOOLCHAIN_VARIANT=zephyr` - `cd zephyr/samples/net/google_iot_device` +- Copy template file `config.c.in` to `config.c`, and fill in Google Cloud + connection parameters (read comments there). - `west build -b native_posix -- -G'Unix Makefiles'` -- provide an ECDSA private key in PEM format in the CWD in a file - named `ec_private.pem`. This private key is associated with the - Goolge IoT Device the sample app will impersonate. -- `./build/zephyr/zephyr.exe -testargs -p [GOOGLE_CLOUD_PROJECT_ID] -d - [GOOGLE_CLOUD_DEVICE_PATH] -t [GOOGLE_CLOUD_PUBLIS_TOPIC]` -- example command: `./build/zephyr/zephyr.exe -testargs -p - macr-o-matic-3100t -d - projects/macr-o-matic-3100t/locations/europe-west1/registries/garage-door-meters/devices/sz11-front-reel - -t /devices/sz11-front-reel/state` +- Run the application: `./build/zephyr/zephyr.exe` See `Google Cloud MQTT Documentation `_. diff --git a/samples/net/google_iot_device/src/commandline.c b/samples/net/google_iot_device/src/commandline.c deleted file mode 100644 index 5f8ecc7722ed..000000000000 --- a/samples/net/google_iot_device/src/commandline.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright 2019 Google LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * This module implements a command line argument parser - */ - -#include "commandline.h" -#include -#include -#include -#include "iotc.h" - -#ifndef IOTC_CROSS_TARGET -#include -#define IOTC_EXAMPLE_DEFAULT_QOS IOTC_MQTT_QOS_AT_LEAST_ONCE -#else -#define IOTC_EXAMPLE_DEFAULT_QOS IOTC_MQTT_QOS_AT_MOST_ONCE -#endif /* IOTC_CROSS_TARGET */ - -void iotc_usage(const char* options, unsigned options_length); - -iotc_mqtt_qos_t iotc_example_qos = IOTC_EXAMPLE_DEFAULT_QOS; - -#define DEFAULT_PRIVATE_KEY_FIILENAME "ec_private.pem" - -const char* iotc_project_id; -const char* iotc_device_path; -const char* iotc_publish_topic; -const char* iotc_publish_message; -const char* iotc_private_key_filename; - -int iotc_parse(int argc, char** argv, char* valid_options, - unsigned options_length) { - int c; - int iotc_help_flag = 0; - iotc_project_id = NULL; - iotc_device_path = NULL; - iotc_publish_topic = NULL; - iotc_private_key_filename = DEFAULT_PRIVATE_KEY_FIILENAME; - iotc_publish_message = "Hello From Your IoTC client!"; - - while (1) { - static struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"project_id", required_argument, 0, 'p'}, - {"device_path", required_argument, 0, 'd'}, - {"publish_topic", required_argument, 0, 't'}, - {"publish_message", required_argument, 0, 'm'}, - {"private_key_filename", optional_argument, 0, 'f'}, - {0, 0, 0, 0}}; - - /* getopt_long stores the option index here. */ - int option_index = 0; - - c = getopt_long(argc, argv, valid_options, long_options, &option_index); - - /* Detect the end of the options. */ - if (-1 == c) { - break; - } - - switch (c) { - case 'p': - iotc_project_id = optarg; - break; - case 'd': - iotc_device_path = optarg; - break; - case 't': - iotc_publish_topic = optarg; - break; - case 'm': - iotc_publish_message = optarg; - break; - case 'f': - iotc_private_key_filename = optarg; - break; - case 'h': - default: - iotc_help_flag = 1; - break; - } - } - - /* Print any unrecognized command line arguments. */ - if (optind < argc) { - printf( - "The application could not recognize the following non-option " - "arguments: "); - while (optind < argc) { - printf("%s ", argv[optind++]); - } - putchar('\n'); - } - putchar('\n'); - - if (1 == iotc_help_flag) /* Print the usage statement */ - { - iotc_usage(valid_options, options_length); - return ( - -1); /* Don't run the application if -h --help was on the commandline */ - } - - return (0); -} - -void iotc_usage(const char* options, unsigned options_length) { - assert(NULL != options); - - /* For debugging printf( "options = %s %d\n", options, options_length ); */ - - printf("Usage:\n"); - while (0 < options_length) { - /* printf( "parsing option %c\n", *options ); */ - switch (*options) { - case 'p': - printf( - "-p --project_id\n\tProvide the project_id your device is " - "registered in " - "Cloud IoT Core.\n"); - break; - case 'd': - printf( - "-d --device_path\n\tProvide the full path of your device. For " - "example:\n" - "\t\tprojects//locations//registries/" - "/devices/\n"); - break; - case 't': - printf("-t --publish_topic\n\tThe topic on which to subscribe.\n"); - break; - case 'm': - printf( - "-m --publish_message\n\tThe message to publish. A shell quoted " - "string of characters.\n"); - break; - case 'f': - printf( - "-f --private_key_filename\n\tThe filename, including path from " - "cwd,\n"); - printf(" \t of the device identifying private_key. Defaults to: %s\n", - DEFAULT_PRIVATE_KEY_FIILENAME); - break; - case 'h': /* Don't print anything for the help option since we're printing - usage */ - break; - case ':': /* We'll skip the ':' character since it's not an option. */ - break; - case '\0': - break; - default: - printf("WARNING: Option %c not recognized by usage()\n", *options); - } - ++options; - --options_length; - } - printf("\n"); -} diff --git a/samples/net/google_iot_device/src/commandline.h b/samples/net/google_iot_device/src/commandline.h deleted file mode 100644 index 0647aa2f44ed..000000000000 --- a/samples/net/google_iot_device/src/commandline.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright 2019 Google LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * This module implements a command line argument parser. - */ - -#include - -/* Flags set by commandline arguments. */ -extern iotc_mqtt_qos_t iotc_example_qos; - -/* Parameters returned by the parser. These will be in a structure someday. */ -extern const char* iotc_project_id; -extern const char* iotc_device_path; -extern const char* iotc_publish_topic; -extern const char* iotc_publish_message; -extern const char* iotc_private_key_filename; - -int iotc_parse(int argc, char** argv, char* valid_options, - const unsigned options_length); diff --git a/samples/net/google_iot_device/src/config.c.in b/samples/net/google_iot_device/src/config.c.in new file mode 100644 index 000000000000..9f8f330a1c6d --- /dev/null +++ b/samples/net/google_iot_device/src/config.c.in @@ -0,0 +1,24 @@ +/* Copyright 2019 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "config.h" + +/* CHANGE THIS */ +const char* iotc_project_id = ""; +/* CHANGE THIS */ +const char* iotc_device_path = "projects//locations//registries//devices/"; +/* CHANGE THIS */ +const char* iotc_publish_topic = "/devices//state"; +/* CHANGE THIS*/ +const char* iotc_private_key_pem = +"-----BEGIN EC PRIVATE KEY-----\n" +"use\n" +"your\n" +"key\n" +"-----END EC PRIVATE KEY-----\n"; + +const char* iotc_publish_message = "Hello from Zephyr!"; + +iotc_mqtt_qos_t iotc_example_qos = IOTC_MQTT_QOS_AT_LEAST_ONCE; diff --git a/samples/net/google_iot_device/src/config.h b/samples/net/google_iot_device/src/config.h new file mode 100644 index 000000000000..7cea34224dff --- /dev/null +++ b/samples/net/google_iot_device/src/config.h @@ -0,0 +1,18 @@ +/* Copyright 2019 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Declarations for application config options. + */ + +#include + +extern iotc_mqtt_qos_t iotc_example_qos; + +extern const char* iotc_project_id; +extern const char* iotc_device_path; +extern const char* iotc_private_key_pem; +extern const char* iotc_publish_topic; +extern const char* iotc_publish_message; diff --git a/samples/net/google_iot_device/src/example_utils.c b/samples/net/google_iot_device/src/example_utils.c index ffb43153f027..b4b261ef9f43 100644 --- a/samples/net/google_iot_device/src/example_utils.c +++ b/samples/net/google_iot_device/src/example_utils.c @@ -7,7 +7,7 @@ #include #include -#include "commandline.h" +#include "config.h" #include "example_utils.h" #define IOTC_UNUSED(x) (void)(x) @@ -17,90 +17,6 @@ extern iotc_crypto_key_data_t iotc_connect_private_key_data; static iotc_timed_task_handle_t delayed_publish_task = IOTC_INVALID_TIMED_TASK_HANDLE; -int iotc_example_handle_command_line_args(int argc, char* argv[]) { - char options[] = "h:p:d:t:m:f:"; - int missingparameter = 0; - int retval = 0; - - /* log the executable name and library version */ - printf("\n%s\n%s\n", argv[0], iotc_cilent_version_str); - - /* Parse the argv array for ONLY the options specified in the options string - */ - retval = iotc_parse(argc, argv, options, sizeof(options)); - - if (-1 == retval) { - /* iotc_parse has returned an error, and has already logged the error - to the console. Therefore just silently exit here. */ - return -1; - } - - /* Check to see that the required parameters were all present on the command - * line */ - if (NULL == iotc_project_id) { - missingparameter = 1; - printf("-p --project_id is required\n"); - } - - if (NULL == iotc_device_path) { - missingparameter = 1; - printf("-d --device_path is required\n"); - } - - if (NULL == iotc_publish_topic) { - missingparameter = 1; - printf("-t --publish_topic is required\n"); - } - - if (1 == missingparameter) { - /* Error has already been logged, above. Silently exit here */ - printf("\n"); - return -1; - } - - return 0; -} - -int load_ec_private_key_pem_from_posix_fs(char* buf_ec_private_key_pem, - size_t buf_len) { - FILE* fp = fopen(iotc_private_key_filename, "rb"); - if (fp == NULL) { - printf("ERROR!\n"); - printf( - "\tMissing Private Key required for JWT signing.\n" - "\tPlease copy and paste your device's EC private key into\n" - "\ta file with the following path based on this executable's\n" - "\tcurrent working dir:\n\t\t\'%s\'\n\n" - "\tAlternatively use the --help command line parameter to learn\n" - "\thow to set a path to your file using command line arguments\n", - iotc_private_key_filename); - return -1; - } - - fseek(fp, 0, SEEK_END); - long file_size = ftell(fp); - rewind(fp); - - if ((size_t)file_size > buf_len) { - printf( - "private key file size of %lu bytes is larger that certificate buffer " - "size of %lu bytes\n", - file_size, (long)buf_len); - fclose(fp); - return -1; - } - - long bytes_read = fread(buf_ec_private_key_pem, 1, file_size, fp); - fclose(fp); - - if (bytes_read != file_size) { - printf("could not fully read private key file\n"); - return -1; - } - - return 0; -} - void on_connection_state_changed(iotc_context_handle_t in_context_handle, void* data, iotc_state_t state) { iotc_connection_data_t* conn_data = (iotc_connection_data_t*)data; diff --git a/samples/net/google_iot_device/src/example_utils.h b/samples/net/google_iot_device/src/example_utils.h index d5273aaa7833..f625d16f01b2 100644 --- a/samples/net/google_iot_device/src/example_utils.h +++ b/samples/net/google_iot_device/src/example_utils.h @@ -7,20 +7,13 @@ #include -/* Parses and manages commandline arguments. Project id, device path and publish - * topic are require to be passed as command line arguments. Prints - * notification if either of these is not found. - */ -int iotc_example_handle_command_line_args(int argc, char* argv[]); - -/* Attempts to load the client's identifying private key from disk so that the +/* Attempts to load the client's identifying private key so that the byte data may be passed to the 'iotc_connect function'. Please note that the IoTC API and Board Support Package have various means to use private keys. This example assumes the use of one that must be provided to a TLS implementation in a buffer, but secure chips with slot-based key stores can also be used. Please see the Crypto BSP for more information. */ -int load_ec_private_key_pem_from_posix_fs(char* buf_ec_private_key_pem, - size_t buf_len); +int load_ec_private_key_pem(char* buf_ec_private_key_pem, size_t buf_len); /* A callback function that will be invoked whenever the connection state has changed. @@ -61,8 +54,8 @@ int load_ec_private_key_pem_from_posix_fs(char* buf_ec_private_key_pem, void on_connection_state_changed(iotc_context_handle_t in_context_handle, void* data, iotc_state_t state); -/* A function that publishes to the topic that was specified in the command - line parameters of the application. This is invoked directly upon connect +/* A function that publishes to the topic that was specified in the config + parameters of the application. This is invoked directly upon connect in the 'on_connection_state_changed' function, but also by the IoTC Client's event system on a 5 second interval. */ void publish_function(iotc_context_handle_t context_handle, diff --git a/samples/net/google_iot_device/src/main.c b/samples/net/google_iot_device/src/main.c index 56770cae39b2..87884124ca23 100644 --- a/samples/net/google_iot_device/src/main.c +++ b/samples/net/google_iot_device/src/main.c @@ -3,11 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include -#include "commandline.h" +#include "config.h" #include "example_utils.h" #include #include @@ -19,32 +18,8 @@ char ec_private_key_pem[PRIVATE_KEY_BUFFER_SIZE] = {0}; void main(void) { printk("Example for Zephyr port.\n"); - /* commandline sample: - zephyr.exe -testargs -p -d projects//locations//registries//devices/ -t /devices//state - */ - - int argc = 0; - char** argv = NULL; - - native_get_cmd_line_args(&argc, &argv); - - /* Zephyr passes the "-testargs" internal command line argument too. This code - * skips it to be compatible to the native command line argument handlin. */ - if (1 < argc && 0 == strcmp(argv[1], "-testargs")) { - --argc; - ++argv; - } - - /* parsing GCP IoT related command line arguments */ - if (0 != iotc_example_handle_command_line_args(argc, argv)) { - return; - } - - if (0 != load_ec_private_key_pem_from_posix_fs(ec_private_key_pem, - PRIVATE_KEY_BUFFER_SIZE)) { + if (0 != load_ec_private_key_pem(ec_private_key_pem, + PRIVATE_KEY_BUFFER_SIZE)) { printk("\nApplication exiting due to private key load error.\n\n"); return; } @@ -94,3 +69,9 @@ void main(void) { /* Cleanup internal allocations that were created by iotc_initialize. */ iotc_shutdown(); } + +int load_ec_private_key_pem(char* buf_ec_private_key_pem, size_t buf_len) { + strncpy(buf_ec_private_key_pem, iotc_private_key_pem, buf_len); + buf_ec_private_key_pem[buf_len - 1] = 0; + return 0; +}