diff --git a/mosquitto.conf b/mosquitto.conf index 6e5f7c69..e61057a4 100644 --- a/mosquitto.conf +++ b/mosquitto.conf @@ -905,4 +905,4 @@ # plugin C:\Users\d.kuhn\Projekte\mosquitto\out\build\x64-Debug\plugins\payload-modification\mosquitto_payload_modification.dll -plugin C:\Users\d.kuhn\Projekte\mosquitto\out\build\x64-Debug\plugins\wamo\wamo.dll \ No newline at end of file +plugin C:\Users\d.kuhn\Projekte\mosquitto\out\build\x64-Release\plugins\wamo\wamo.dll \ No newline at end of file diff --git a/plugins/wamo/json_help.c b/plugins/wamo/json_help.c index d7c02922..e09b54c9 100644 --- a/plugins/wamo/json_help.c +++ b/plugins/wamo/json_help.c @@ -16,16 +16,16 @@ Contributors: #include "mosquitto.h" #include "mosquitto_broker.h" -int json_create_array(cJSON* json, const char* name) { +json_err_t json_create_array(cJSON* json, const char* name) { cJSON* jtmp; jtmp = cJSON_GetObjectItem(json, name); if (jtmp) { if (cJSON_IsArray(jtmp) == true) { - return MOSQ_ERR_INVAL; + return JSON_ERR_ARRAY_EXISTS; } else { - cJSON_AddArrayToObject(json, name); + return JSON_ERR_TYPE_INVAL; } } @@ -33,11 +33,11 @@ int json_create_array(cJSON* json, const char* name) { cJSON_AddArrayToObject(json, name); } - return MOSQ_ERR_SUCCESS; + return JSON_ERR_SUCCESS; } -int json_add_id_to_array(cJSON* json, const char* name, const char * id) +json_err_t json_add_id_to_array(cJSON* json, const char* name, const char * id) { cJSON* jtmp; cJSON* tid; @@ -49,19 +49,19 @@ int json_add_id_to_array(cJSON* json, const char* name, const char * id) cJSON_AddItemToArray(jtmp, tid); } else { - return MOSQ_ERR_INVAL; + return JSON_ERR_TYPE_INVAL; } } else { - return MOSQ_ERR_INVAL; + return JSON_ERR_SYNTAX; } - return MOSQ_ERR_SUCCESS; + return JSON_ERR_SUCCESS; } -int json_del_id_from_array(cJSON* json, const char* name, const char* id) +json_err_t json_del_id_from_array(cJSON* json, const char* name, const char* id) { cJSON* jtmp = NULL; cJSON* tid = NULL; @@ -71,42 +71,55 @@ int json_del_id_from_array(cJSON* json, const char* name, const char* id) jtmp = cJSON_GetObjectItem(json, name); if (jtmp) { - // mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 1"); if (cJSON_IsArray(jtmp) == true) { - // cJSON_DeleteItemFromObject(json, name); - // mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 2"); cJSON_ArrayForEach(tid, jtmp) - { - + { if ( strcmp( cJSON_GetStringValue(tid),id) == 0) { - // mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 3"); detached_item = cJSON_DetachItemFromArray(jtmp, array_index); - + } - else - { - return MOSQ_ERR_INVAL; - // mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 4"); - } array_index++; } - // cJSON_ReplaceItemInObject(json, name, jtmp); - // cJSON_AddItemToObject(json, id, jtmp); + } else { - return MOSQ_ERR_INVAL; + return JSON_ERR_TYPE_INVAL; } } else { - return MOSQ_ERR_INVAL; + return JSON_ERR_SYNTAX; } - return MOSQ_ERR_SUCCESS; + return JSON_ERR_SUCCESS; } + +json_err_t json_del_clientid(cJSON* json, const char* id) +{ + cJSON* next_object = NULL; + + cJSON_ArrayForEach(next_object, json) + { + if (next_object->string != NULL) { + + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting client with id %s from topic %s", id, next_object->string); + json_del_id_from_array(json, next_object->string, id); + } + + + } + + + return JSON_ERR_SUCCESS; + +} + + + + int json_get_bool(cJSON *json, const char *name, bool *value, bool optional, bool default_value) { cJSON *jtmp; diff --git a/plugins/wamo/json_help.h b/plugins/wamo/json_help.h index f11eea3e..513faf8e 100644 --- a/plugins/wamo/json_help.h +++ b/plugins/wamo/json_help.h @@ -8,9 +8,38 @@ Contributors: #include #include -int json_create_array(cJSON* json, const char* name); -int json_add_id_to_array(cJSON* json, const char* name, const char* id); -int json_del_id_from_array(cJSON* json, const char* name, const char* id); + +/* Enum: json_err_t + * Integer values returned from many JSON helper function functions. + * + * JSON_ERR_SUCCESS - the message/packet ID of the PUBLISH message, assuming this is a. + * + * char *topic - the topic the message was delivered on. + * + * void *payload - the message payload. This will be payloadlen bytes long, and + * may be NULL if a zero length payload was sent. + * + * int payloadlen - the length of the payload, in bytes. + * + * int qos - the quality of service of the message, 0, 1, or 2. + */ +typedef enum { + + JSON_ERR_SUCCESS = 0, + JSON_ERR_FAILURE = 1, + JSON_ERR_TYPE_INVAL = 3, + JSON_ERR_VALUE = 4, + JSON_ERR_SYNTAX = 5, + JSON_ERR_ARRAY_EXISTS = 6, + +} json_err_t; + + +json_err_t json_create_array(cJSON* json, const char* name); +json_err_t json_add_id_to_array(cJSON* json, const char* name, const char* id); +json_err_t json_del_id_from_array(cJSON* json, const char* name, const char* id); +json_err_t json_del_clientid(cJSON* json, const char* id); + /* "optional==false" can also be taken to mean "only return success if the key exists and is valid" */ int json_get_bool(cJSON *json, const char *name, bool *value, bool optional, bool default_value); diff --git a/plugins/wamo/wamo.c b/plugins/wamo/wamo.c index b0cd24df..df6bc144 100644 --- a/plugins/wamo/wamo.c +++ b/plugins/wamo/wamo.c @@ -57,52 +57,102 @@ static int callback_control(int event, void* event_data, void* userdata) const char * client_id = mosquitto_client_id(ed->client); const char* topic = ed->topic; - const int access = ed->access; - - + const int access = ed->access; if (access == MOSQ_ACL_SUBSCRIBE) { - json_create_array(subscribedTopics, topic); - json_add_id_to_array(subscribedTopics, topic, client_id); - char* json_string = cJSON_Print(subscribedTopics); - char* payload = cJSON_PrintUnformatted(subscribedTopics); - mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with id %s subscribed to topic %s", client_id, topic); - mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string); + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with ID %s subscribed to topic %s", client_id, topic); - if (payload == NULL) return MOSQ_ERR_MALFORMED_PACKET; + json_err_t rc = json_create_array(subscribedTopics, topic); + if ((rc == JSON_ERR_SUCCESS) || (rc == JSON_ERR_ARRAY_EXISTS)) { + if (json_add_id_to_array(subscribedTopics, topic, client_id) == JSON_ERR_SUCCESS) { + char* json_string = cJSON_Print(subscribedTopics); + char* payload = cJSON_PrintUnformatted(subscribedTopics); - uint32_t payload_len = strlen(payload); - if (payload_len > MQTT_MAX_PAYLOAD) { - free(payload); - return MOSQ_ERR_PAYLOAD_SIZE; + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: new subscribed topics %s", json_string); + + if (payload == NULL) return MOSQ_ERR_MALFORMED_PACKET; + + uint32_t payload_len = strlen(payload); + if (payload_len > MQTT_MAX_PAYLOAD) { + free(payload); + return MOSQ_ERR_PAYLOAD_SIZE; + } + + mosquitto_broker_publish_copy(NULL, "mqtt/subscriptions", + (int)payload_len, payload, 0, 1, NULL); + } + else + { + mosquitto_log_printf(MOSQ_LOG_INFO, "the specified object item does not exist or is not an array"); + } + + } + else { + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: something went wrong while attaching the client ID to JSON object. "\ + "Looks like the specified obejkt item already exists, but is not an array"); } - mosquitto_broker_publish_copy(NULL, "mqtt/subscriptions", - (int)payload_len, payload, 0, 0, NULL); } else if (access == MOSQ_ACL_UNSUBSCRIBE) { - json_del_id_from_array(subscribedTopics, topic, client_id); - char* json_string = cJSON_Print(subscribedTopics); - char* payload = cJSON_PrintUnformatted(subscribedTopics); - mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with id %s unscribed to topic %s", client_id, topic); - mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string); + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with ID %s unscribed to topic %s", client_id, topic); - if (payload == NULL) return MOSQ_ERR_MALFORMED_PACKET; + json_err_t rc = json_del_id_from_array(subscribedTopics, topic, client_id); + if (rc == JSON_ERR_SUCCESS) { + char* json_string = cJSON_Print(subscribedTopics); + char* payload = cJSON_PrintUnformatted(subscribedTopics); + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string); - uint32_t payload_len = strlen(payload); - if (payload_len > MQTT_MAX_PAYLOAD) { - free(payload); - return MOSQ_ERR_PAYLOAD_SIZE; + if (payload == NULL) return MOSQ_ERR_MALFORMED_PACKET; + + uint32_t payload_len = strlen(payload); + if (payload_len > MQTT_MAX_PAYLOAD) { + free(payload); + return MOSQ_ERR_PAYLOAD_SIZE; + } + mosquitto_broker_publish_copy(NULL, "mqtt/subscriptions", + (int)payload_len, payload, 0, 1, NULL); } - mosquitto_broker_publish_copy(NULL, "mqtt/subscriptions", - (int)payload_len, payload, 0, 0, NULL); + else + { + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: something went wrong while deleting the client ID from JSON object. "\ + "The specified object item does not exist or is not an array"); + } + } - - return MOSQ_ERR_SUCCESS; } +static int callback_disconnect(int event, void* event_data, void* userdata) +{ + struct mosquitto_evt_disconnect* ed = event_data; + + UNUSED(event); + UNUSED(userdata); + + const char* client_id = mosquitto_client_id(ed->client); + + json_del_clientid(subscribedTopics, client_id); + + char* json_string = cJSON_Print(subscribedTopics); + char* payload = cJSON_PrintUnformatted(subscribedTopics); + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with ID %s disconnected", client_id ); + mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string); + + if (payload == NULL) return MOSQ_ERR_MALFORMED_PACKET; + + uint32_t payload_len = strlen(payload); + if (payload_len > MQTT_MAX_PAYLOAD) { + free(payload); + return MOSQ_ERR_PAYLOAD_SIZE; + } + mosquitto_broker_publish_copy(NULL, "mqtt/subscriptions", + (int)payload_len, payload, 0, 1, NULL); + + + return MOSQ_ERR_SUCCESS; + +} static int callback_message(int event, void* event_data, void* userdata) { @@ -176,6 +226,20 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t* identifier, void** user_data, s return rc; } + + rc = mosquitto_callback_register(mosq_pid, MOSQ_EVT_DISCONNECT, callback_disconnect, NULL, NULL); + if (rc == MOSQ_ERR_ALREADY_EXISTS) { + mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can only be loaded once."); + return rc; + } + else if (rc == MOSQ_ERR_NOMEM) { + mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); + return rc; + } + else if (rc != MOSQ_ERR_SUCCESS) { + return rc; + } + return MOSQ_ERR_SUCCESS; @@ -187,5 +251,10 @@ int mosquitto_plugin_cleanup(void* user_data, struct mosquitto_opt* opts, int op UNUSED(opts); UNUSED(opt_count); - return mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_ACL_CHECK, callback_control, NULL); + if (mosq_pid) { + mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_ACL_CHECK, callback_control, NULL); + mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_DISCONNECT, callback_disconnect, NULL); + } + + return MOSQ_ERR_SUCCESS; }