blob: 136b95c74d6b6c6325a1b722df5f05163b825b2a [file] [log] [blame]
/******************************************************************************
* Copyright 2017 Google
* Copyright 2019 NXP
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*****************************************************************************/
// [START iot_mqtt_include]
#define _XOPEN_SOURCE 500
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "MQTTClient.h"
#include "jwt.h"
#include "openssl/conf.h"
#include "openssl/ec.h"
#include "openssl/evp.h"
#include "mqtt_azure.h"
// [END iot_mqtt_include]
#define TRACE 1 /* Set to 1 to enable tracing */
void Usage()
{
printf("azure_imx_connect \\\n");
printf("\t--payload \"Message to publish\"\\\n");
printf("\t--deviceid <your device id>\\\n");
printf("\t--keypath <e.g. ./ec_private.pem>\\\n");
printf("\t--rootpath root CA file of Azure in PEM format\n\n");
printf("\t--devcert device certificate in PEM format\n\n");
printf("\t--hubname azure IoT hub name\n\n");
printf("\t--username azure IoT user name\n\n");
}
bool calculate_url(char* hubname, char * deviceid)
{
size_t n = snprintf(opts.address,
sizeof(opts.address),
"ssl://%s:8883",
hubname);
size_t m = snprintf(opts.username,
sizeof(opts.username),
"%s/%s/?api-version=2018-06-30",
hubname,
deviceid);
if (n > sizeof(opts.address) || m > sizeof(opts.username)) {
printf(
"Error, buffer for storing hubname/username was too small.\n");
return false;
}
return true;
}
bool calculate_topic(char * deviceid)
{
size_t n = snprintf(opts.topic,
sizeof(opts.topic),
"devices/%s/messages/events/",
deviceid);
if (n > sizeof(opts.topic)) {
printf("Error, buffer for storing device ID was too small.\n");
return false;
}
return true;
}
bool get_connection_params_file(char * filename)
{
FILE *fk = fopen(filename, "rb");
if (fk == NULL)
{
printf("Can not open the file [%s]\n", filename);
return false;
}
fseek(fk, 0, SEEK_END);
long json_file_len = ftell(fk);
fseek(fk, 0, SEEK_SET);
char *json_file = malloc(json_file_len +1);
fread(json_file, 1, json_file_len, fk);
json_file[json_file_len] = 0;
fclose(fk);
printf("file contents %s\n", json_file);
char assignedHub[256];
char deviceId[256];
char payload[256];
char key[256];
char cert[256];
char root[256];
if (!get_json_tagValue(json_file, "deviceId", deviceId) ||
!get_json_tagValue(json_file, "assignedHub", assignedHub) ||
!get_json_tagValue(json_file, "payload", payload) ||
!get_json_tagValue(json_file, "keypath", key) ||
!get_json_tagValue(json_file, "devcert", cert) ||
!get_json_tagValue(json_file, "rootpath", root))
{
printf("File missing required parameters!\n");
free(json_file);
return false;
}
free(json_file);
strcpy((char *restrict) & opts.payload, payload);
strcpy((char *restrict) & opts.clientid, deviceId);
strcpy((char *restrict) & opts.keypath, key);
strcpy((char *restrict) & opts.devcert, cert);
strcpy((char *restrict) & opts.rootpath, root);
if (!calculate_url(assignedHub, deviceId) || !calculate_topic(deviceId))
{
return false;
}
return true;
}
/**
* Helper to parse arguments passed to app. Returns false if there are missing
* or invalid arguments; otherwise, returns true indicating the caller should
* free the calculated client ID placed on the opts structure.
*
* TODO: (class) Consider getopt
*/
// [START iot_mqtt_opts]
bool GetOpts(int argc, char **argv)
{
int pos = 1;
if (argc < 2) {
return false;
}
if (strcmp(argv[pos], "--json") == 0) {
if (++pos < argc) {
char * filename = argv[pos];
printf("Reading parameters from json file %s\n", filename);
if (get_connection_params_file(filename))
{
return true;
}
}
exit(EXIT_FAILURE);
}
char *deviceid;
char hubname[257];
bool hasPayload = false;
while (pos < argc) {
if (strcmp(argv[pos], "--payload") == 0) {
if (++pos < argc) {
//opts.payload = argv[pos];
strcpy((char *restrict) & opts.payload, argv[pos]);
hasPayload = true;
}
else {
return false;
}
}
if (strcmp(argv[pos], "--deviceid") == 0) {
if (++pos < argc) {
deviceid = argv[pos];
}
else
return false;
}
else if (strcmp(argv[pos], "--keypath") == 0) {
if (++pos < argc)
strcpy((char *restrict) & opts.keypath, argv[pos]);
//opts.keypath = argv[pos];
else
return false;
}
else if (strcmp(argv[pos], "--devcert") == 0) {
if (++pos < argc)
strcpy((char *restrict) & opts.devcert, argv[pos]);
//opts.devcert = argv[pos];
else
return false;
}
else if (strcmp(argv[pos], "--rootpath") == 0) {
if (++pos < argc)
strcpy((char *restrict) & opts.rootpath, argv[pos]);
//opts.rootpath = argv[pos];
else
return false;
}
else if (strcmp(argv[pos], "--topic") == 0) {
if (++pos < argc) {
strcpy((char *restrict) & opts.topic, argv[pos]);
}
else
return false;
}
else if (strcmp(argv[pos], "--hubname") == 0) {
if (++pos < argc) {
strcpy((char *restrict) & hubname, argv[pos]);
}
else
return false;
}
else if (strcmp(argv[pos], "--username") == 0) {
if (++pos < argc) {
strcpy((char *restrict) & opts.username, argv[pos]);
}
else
return false;
}
pos++;
}
if (!hasPayload) {
printf("Payload not passed\n");
return false;
}
if (!calculate_url(hubname, deviceid) || !calculate_topic(deviceid))
{
return false;
}
strcpy((char *restrict) & opts.clientid, deviceid);
return true;
}
// [END iot_mqtt_opts]
/**
* Connects MQTT client and transmits payload.
*/
// [START iot_mqtt_run]
int main(int argc, char *argv[])
{
if (GetOpts(argc, argv)) {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
OPENSSL_config(NULL);
#else
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
OpenSSL_add_all_algorithms();
OpenSSL_add_all_digests();
OpenSSL_add_all_ciphers();
int rc = -1;
rc = register_device(false);
printf("Publish done with error code : %d\n", rc);
}
else {
Usage();
}
EVP_cleanup();
}
// [END iot_mqtt_run]