From 31b5ee634ac6a00da75b9322cef9fbe2617ee2ff Mon Sep 17 00:00:00 2001 From: gc87 Date: Thu, 12 May 2022 17:32:05 +0800 Subject: [PATCH 1/2] feat(mqtt intf): add will topic set --- plugins/mqtt/util.c | 2 ++ src/connection/mqtt_c_client.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/plugins/mqtt/util.c b/plugins/mqtt/util.c index 3205b696..ea957a06 100644 --- a/plugins/mqtt/util.c +++ b/plugins/mqtt/util.c @@ -137,5 +137,7 @@ int mqtt_option_init(neu_config_t *config, neu_mqtt_option_t *option) option->key = key.v.val_str; option->keepalive_interval = 30; option->clean_session = 1; + option->will_topic = NULL; + option->will_payload = NULL; return 0; } diff --git a/src/connection/mqtt_c_client.c b/src/connection/mqtt_c_client.c index a6cc84f0..7dae4d96 100644 --- a/src/connection/mqtt_c_client.c +++ b/src/connection/mqtt_c_client.c @@ -44,6 +44,9 @@ struct reconnect_state { char * password; int keepalive; int clean; + char * will_topic; + char * will_payload; + int will_payload_len; char * ca_file; char * ca_path; char * cert_file; @@ -378,6 +381,14 @@ static void reconnect_state_uninit(struct reconnect_state *state) pthread_mutex_destroy(&state->sock_state_mutex); pthread_mutex_destroy(&state->running_mutex); pthread_mutex_destroy(&state->working_mutex); + + if (NULL != state->will_topic) { + free(state->will_topic); + } + + if (NULL != state->will_payload) { + free(state->will_payload); + } } static void subscribe_on_reconnect(mqtt_c_client_t *client) @@ -429,9 +440,13 @@ static void client_reconnect(struct mqtt_client *mqtt, void **p_reconnect_state) connect_flags = MQTT_CONNECT_CLEAN_SESSION; } - enum MQTTErrors rc = - mqtt_connect(mqtt, client_id, NULL, NULL, 0, state->username, - state->password, connect_flags, state->keepalive); + const char *will_topic = state->will_topic; + const char *will_payload = state->will_payload; + size_t payload_len = state->will_payload_len; + + enum MQTTErrors rc = mqtt_connect( + mqtt, client_id, will_topic, will_payload, payload_len, state->username, + state->password, connect_flags, state->keepalive); if (MQTT_OK != rc) { return; @@ -551,6 +566,14 @@ static mqtt_c_client_t *client_create(const neu_mqtt_option_t *option, pthread_mutex_init(&state->running_mutex, NULL); pthread_mutex_init(&state->working_mutex, NULL); + if (NULL != client->option->will_topic) { + state->will_topic = strdup(option->will_topic); + if (NULL != client->option->will_payload) { + state->will_payload = strdup(client->option->will_payload); + state->will_payload_len = strlen(state->will_payload); + } + } + client->mqtt.publish_response_callback_state = state; return client; } From 241aeb8654ddcf8f9e30068dcd1cd5cacbfcfa9f Mon Sep 17 00:00:00 2001 From: gc87 Date: Thu, 12 May 2022 23:25:59 +0800 Subject: [PATCH 2/2] feat(mqtt-intf): add keypass setting --- ft/common.resource | 2 +- ft/persistence_test.robot | 2 +- plugins/mqtt/mqtt.json | 14 ++++++++++++++ plugins/mqtt/util.c | 12 ++++++++++-- src/connection/mqtt_c_client.c | 25 +++++++++++++++++++------ tests/mqtt_test.cc | 3 ++- 6 files changed, 47 insertions(+), 11 deletions(-) diff --git a/ft/common.resource b/ft/common.resource index 9a2ce962..52b99652 100644 --- a/ft/common.resource +++ b/ft/common.resource @@ -75,7 +75,7 @@ ${MQTT_CONFIG_HOST} 127.0.0.1 ${MQTT_CONFIG_PORT} ${1883} ${MQTT_CONFIG} {"client-id": "${MQTT_CLIENTID}", "upload-topic": "", "format": 1, ... "ssl": false, "host": "${MQTT_CONFIG_HOST}", "port": ${MQTT_CONFIG_PORT}, -... "username": "", "password": "", "ca":"", "cert":"", "key":""} +... "username": "", "password": "", "ca":"", "cert":"", "key":"", "keypass":""} ${MODBUS_TCP_CONFIG} {"host": "127.0.0.1", "port": 60502, "connection_mode": 0} diff --git a/ft/persistence_test.robot b/ft/persistence_test.robot index c339ec15..88217580 100644 --- a/ft/persistence_test.robot +++ b/ft/persistence_test.robot @@ -93,7 +93,7 @@ Get the setted adapters information after stopping and restarting Neuron, it sho Node Setting ${modbus_tcp2_id} {"host": "127.0.0.1", "port": 502, "connection_mode": 0} ${mqtt_id} = Get Node ID ${NODE_MQTT} mqtt-1 - Node Setting ${mqtt_id} {"client-id":"upload123", "upload-topic":"", "format": 0, "ssl":false,"host":"127.0.0.1","port":1883,"username":"admin","password":"0000","ca":"", "cert":"", "key":""} + Node Setting ${mqtt_id} {"client-id":"upload123", "upload-topic":"", "format": 0, "ssl":false,"host":"127.0.0.1","port":1883,"username":"admin","password":"0000","ca":"", "cert":"", "key":"", "keypass":""} Neuron Stop Running ${process} ${process} = Neuron Start Running diff --git a/plugins/mqtt/mqtt.json b/plugins/mqtt/mqtt.json index 29036b6a..b4c57252 100644 --- a/plugins/mqtt/mqtt.json +++ b/plugins/mqtt/mqtt.json @@ -128,5 +128,19 @@ "valid": { "length": 81960 } + }, + "keypass": { + "name": "keypass", + "description": "key password", + "attribute": "optional", + "type": "file", + "condition": { + "field": "ssl", + "value": true + }, + "default": "", + "valid": { + "length": 256 + } } } \ No newline at end of file diff --git a/plugins/mqtt/util.c b/plugins/mqtt/util.c index ea957a06..18663223 100644 --- a/plugins/mqtt/util.c +++ b/plugins/mqtt/util.c @@ -80,6 +80,11 @@ void mqtt_option_uninit(neu_mqtt_option_t *option) free(option->key); option->key = NULL; } + + if (NULL != option->keypass) { + free(option->keypass); + option->keypass = NULL; + } } int mqtt_option_init(neu_config_t *config, neu_mqtt_option_t *option) @@ -101,9 +106,11 @@ int mqtt_option_init(neu_config_t *config, neu_mqtt_option_t *option) neu_json_elem_t ca = { .name = "ca", .t = NEU_JSON_STR }; neu_json_elem_t cert = { .name = "cert", .t = NEU_JSON_STR }; neu_json_elem_t key = { .name = "key", .t = NEU_JSON_STR }; + neu_json_elem_t keypass = { .name = "keypass", .t = NEU_JSON_STR }; - ret = neu_parse_param(config->buf, &error, 11, &id, &upload, &format, &ssl, - &host, &port, &username, &password, &ca, &cert, &key); + ret = neu_parse_param(config->buf, &error, 12, &id, &upload, &format, &ssl, + &host, &port, &username, &password, &ca, &cert, &key, + &keypass); if (0 != ret) { return ret; } @@ -139,5 +146,6 @@ int mqtt_option_init(neu_config_t *config, neu_mqtt_option_t *option) option->clean_session = 1; option->will_topic = NULL; option->will_payload = NULL; + option->keypass = keypass.v.val_str; return 0; } diff --git a/src/connection/mqtt_c_client.c b/src/connection/mqtt_c_client.c index 7dae4d96..11e6cc44 100644 --- a/src/connection/mqtt_c_client.c +++ b/src/connection/mqtt_c_client.c @@ -51,6 +51,7 @@ struct reconnect_state { char * ca_path; char * cert_file; char * key_file; + char * keypass; mqtt_c_client_t *client; uint8_t send_buf[SEND_BUF_SIZE]; uint8_t recv_buf[RECV_BUF_SIZE]; @@ -90,7 +91,7 @@ static neu_err_code_e client_destroy(mqtt_c_client_t *client); static neu_err_code_e client_subscribe_send(mqtt_c_client_t * client, struct subscribe_tuple *tuple); -static X509 *ssl_ctx_load_cert(const char *b64) +static X509 *ssl_ctx_load_cert(const char *b64, const char *password) { unsigned char *bin = NULL; int len = 0; @@ -102,13 +103,13 @@ static X509 *ssl_ctx_load_cert(const char *b64) X509 *cert = NULL; BIO * bio = NULL; bio = BIO_new_mem_buf((void *) bin, len); - cert = PEM_read_bio_X509(bio, NULL, 0, NULL); + cert = PEM_read_bio_X509(bio, NULL, 0, (void *) password); BIO_free_all(bio); free(bin); return cert; } -static EVP_PKEY *ssl_ctx_load_key(const char *b64) +static EVP_PKEY *ssl_ctx_load_key(const char *b64, const char *password) { unsigned char *bin = NULL; int len = 0; @@ -120,7 +121,7 @@ static EVP_PKEY *ssl_ctx_load_key(const char *b64) EVP_PKEY *key = NULL; BIO * bio = NULL; bio = BIO_new_mem_buf((void *) bin, len); - key = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL); + key = PEM_read_bio_PrivateKey(bio, NULL, 0, (void *) password); BIO_free_all(bio); free(bin); return key; @@ -196,7 +197,7 @@ static void ssl_ctx_init(struct reconnect_state *state) // setup cert if (NULL != cert_file && 0 < strlen(cert_file)) { - state->cert = ssl_ctx_load_cert(cert_file); + state->cert = ssl_ctx_load_cert(cert_file, NULL); if (NULL != state->cert) { if (0 >= SSL_CTX_use_certificate(state->ssl_ctx, state->cert)) { log_error("failed to use certificate"); @@ -208,7 +209,8 @@ static void ssl_ctx_init(struct reconnect_state *state) // setup key if (NULL != key_file && 0 < strlen(key_file)) { - state->key = ssl_ctx_load_key(key_file); + const char *keypass = state->keypass; + state->key = ssl_ctx_load_key(key_file, keypass); if (NULL != state->key) { if (0 >= SSL_CTX_use_PrivateKey(state->ssl_ctx, state->key)) { log_error("failed to use privatekey"); @@ -389,6 +391,10 @@ static void reconnect_state_uninit(struct reconnect_state *state) if (NULL != state->will_payload) { free(state->will_payload); } + + if (NULL != state->keypass) { + free(state->keypass); + } } static void subscribe_on_reconnect(mqtt_c_client_t *client) @@ -574,6 +580,13 @@ static mqtt_c_client_t *client_create(const neu_mqtt_option_t *option, } } + if (NULL != client->option->keypass && + 0 < strlen(client->option->keypass)) { + state->keypass = strdup(client->option->keypass); + } else { + state->keypass = NULL; + } + client->mqtt.publish_response_callback_state = state; return client; } diff --git a/tests/mqtt_test.cc b/tests/mqtt_test.cc index 0435ddbb..4683ec27 100644 --- a/tests/mqtt_test.cc +++ b/tests/mqtt_test.cc @@ -13,7 +13,8 @@ TEST(MQTTTest, mqtt_option_init_by_config) "\"upload123\", \"upload-topic\":\"\", \"format\": " "0,\"ssl\":false,\"host\":\"192.168.10." "116\",\"port\":1883,\"username\":\"\",\"password\":" - "\"\",\"ca\":\"\", \"cert\":\"\", \"key\":\"\"}}"; + "\"\",\"ca\":\"\", \"cert\":\"\", \"key\":\"\", " + "\"keypass\":\"\"}}"; int rc = mqtt_option_init(&config, &option); EXPECT_EQ(0, rc);