mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2025-12-10 07:44:41 +01:00
376 lines
11 KiB
C
376 lines
11 KiB
C
/*
|
|
* autonomous_complpolicy.c - CWMP autonomous notification methods
|
|
*
|
|
* Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
|
|
*
|
|
* Author: Suvendhu Hansa <suvendhu.hansa@iopsys.eu>
|
|
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
|
|
*
|
|
* See LICENSE file for license related information.
|
|
*
|
|
*/
|
|
|
|
#include "autonomous_complpolicy.h"
|
|
#include "cwmp_du_state.h"
|
|
#include "log.h"
|
|
#include <libubox/blobmsg_json.h>
|
|
#include "backupSession.h"
|
|
#include "common.h"
|
|
#include "session.h"
|
|
#include "event.h"
|
|
|
|
enum autonomous_notif_type {
|
|
DU_STATE_CHANGE,
|
|
__MAX_NOTIF_TYPE
|
|
};
|
|
|
|
typedef void (*autonomous_event_callback)(struct blob_attr *msg);
|
|
|
|
struct autonomous_event {
|
|
char name[2048];
|
|
autonomous_event_callback cb;
|
|
};
|
|
|
|
static void free_autonomous_du_state_change_complete_data(auto_du_state_change_compl *p);
|
|
static void free_autonomous_transfer_complete_data(auto_transfer_complete *p);
|
|
|
|
static bool validate_du_state_change_data(auto_du_state_change_compl *data)
|
|
{
|
|
|
|
if (data->fault_code && CWMP_STRCMP(cwmp_main->conf.auto_cdu_result_type, "Failure") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_cdu_result_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (!data->fault_code && CWMP_STRCMP(cwmp_main->conf.auto_cdu_result_type, "Success") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_cdu_result_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (data->operation && CWMP_STRSTR(cwmp_main->conf.auto_cdu_oprt_type, data->operation) == NULL)
|
|
return false;
|
|
|
|
char fault_code[5] = {0};
|
|
snprintf(fault_code, 4, "%d", data->fault_code);
|
|
if (CWMP_STRSTR(cwmp_main->conf.auto_cdu_fault_code, fault_code) == NULL)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static void send_du_state_change_notif(struct blob_attr *msg)
|
|
{
|
|
if (!cwmp_main->conf.auto_cdu_enable) {
|
|
CWMP_LOG(INFO, "Autonomous Change DU State is disabled");
|
|
return;
|
|
}
|
|
if (strlen(cwmp_main->conf.auto_cdu_oprt_type) == 0) {
|
|
CWMP_LOG(INFO, "Autonomous Change DU State OperationTypeFilter is empty");
|
|
return;
|
|
}
|
|
(void)msg;
|
|
CWMP_LOG(INFO, "Received DU STATE CHANGE EVENT");
|
|
const struct blobmsg_policy p[2] = {
|
|
{ "name", BLOBMSG_TYPE_STRING },
|
|
{ "input", BLOBMSG_TYPE_TABLE }
|
|
};
|
|
|
|
const struct blobmsg_policy p1[9] = {
|
|
{ "UUID", BLOBMSG_TYPE_STRING },
|
|
{ "Version", BLOBMSG_TYPE_STRING },
|
|
{ "CurrentState", BLOBMSG_TYPE_STRING },
|
|
{ "Resolved", BLOBMSG_TYPE_INT8 },
|
|
{ "StartTime", BLOBMSG_TYPE_STRING },
|
|
{ "CompleteTime", BLOBMSG_TYPE_STRING },
|
|
{ "OperationPerformed", BLOBMSG_TYPE_STRING },
|
|
{ "Fault.FaultCode", BLOBMSG_TYPE_INT32 },
|
|
{ "Fault.FaultString", BLOBMSG_TYPE_STRING }
|
|
};
|
|
|
|
struct blob_attr *tb[2] = {NULL};
|
|
blobmsg_parse(p, 2, tb, blob_data(msg), blob_len(msg));
|
|
|
|
if (tb[1]) {
|
|
char *uuid = NULL, *oper = NULL;
|
|
|
|
char *str = blobmsg_format_json_indent(tb[1], true, -1);
|
|
CWMP_LOG(INFO, "%s\n", str);
|
|
FREE(str);
|
|
|
|
struct blob_attr *tb1[9] = {NULL};
|
|
blobmsg_parse(p1, 9, tb1, blobmsg_data(tb[1]), blobmsg_len(tb[1]));
|
|
|
|
if (tb1[0]) {
|
|
uuid = blobmsg_get_string(tb1[0]);
|
|
}
|
|
|
|
if (tb1[6]) {
|
|
oper = blobmsg_get_string(tb1[6]);
|
|
}
|
|
|
|
CWMP_LOG(INFO, "uuid: %s, oper: %s\n", uuid ? uuid : "", oper ? oper : "");
|
|
if (uuid == NULL || oper == NULL)
|
|
return;
|
|
|
|
if (exists_in_uuid_list(uuid, oper)) {
|
|
/* This DU operation was performed by cwmp */
|
|
remove_node_from_uuid_list(uuid, oper);
|
|
} else {
|
|
/* This DU operation was performed from outside */
|
|
auto_du_state_change_compl *data = calloc(1, sizeof(auto_du_state_change_compl));
|
|
if (data == NULL)
|
|
return;
|
|
|
|
data->uuid = CWMP_STRDUP(uuid);
|
|
data->operation = CWMP_STRDUP(oper);
|
|
|
|
if (tb1[1]) {
|
|
data->ver = CWMP_STRDUP(blobmsg_get_string(tb1[1]));
|
|
}
|
|
|
|
if (tb1[2]) {
|
|
data->current_state = CWMP_STRDUP(blobmsg_get_string(tb1[2]));
|
|
}
|
|
|
|
if (tb1[3]) {
|
|
data->resolved = blobmsg_get_u8(tb1[3]) ? 1 : 0;
|
|
}
|
|
|
|
if (tb1[4]) {
|
|
data->start_time = CWMP_STRDUP(blobmsg_get_string(tb1[4]));
|
|
}
|
|
|
|
if (tb1[5]) {
|
|
data->complete_time = CWMP_STRDUP(blobmsg_get_string(tb1[5]));
|
|
}
|
|
|
|
if (tb1[7]) {
|
|
//data->fault_code = blobmsg_get_u32(tb1[7]);
|
|
data->fault_code = 9001; // for now setting a generic code */
|
|
}
|
|
|
|
if (tb1[8]) {
|
|
data->fault_string = CWMP_STRDUP(blobmsg_get_string(tb1[8]));
|
|
}
|
|
|
|
// Check autonomous_du_state_change_complpolicy data
|
|
if (validate_du_state_change_data(data) == false) {
|
|
CWMP_LOG(INFO, "autonomous du state change data is not valid");
|
|
free_autonomous_du_state_change_complete_data(data);
|
|
return;
|
|
}
|
|
if ((cwmp_main->auto_cdu_id < 0) || (cwmp_main->auto_cdu_id >= MAX_INT_ID)) {
|
|
cwmp_main->auto_cdu_id = 0;
|
|
}
|
|
cwmp_main->auto_cdu_id++;
|
|
data->id = cwmp_main->auto_cdu_id;
|
|
bkp_session_insert_autonomous_du_state_change(data);
|
|
bkp_session_save();
|
|
|
|
CWMP_LOG(INFO, "autonomous du state change event added");
|
|
struct session_timer_event *ubus_inform_event = calloc(1, sizeof(struct session_timer_event));
|
|
|
|
ubus_inform_event->extra_data = data;
|
|
ubus_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event;
|
|
ubus_inform_event->event = EVENT_IDX_12AUTONOMOUS_DU_STATE_CHANGE_COMPLETE;
|
|
trigger_cwmp_session_timer_with_event(&ubus_inform_event->session_timer_evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool validate_transfer_complete_data(auto_transfer_complete *data)
|
|
{
|
|
if (data->is_download && CWMP_STRCMP(cwmp_main->conf.auto_tc_transfer_type, "Download") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_tc_transfer_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (!data->is_download && CWMP_STRCMP(cwmp_main->conf.auto_tc_transfer_type, "Upload") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_tc_transfer_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (data->fault_code && CWMP_STRCMP(cwmp_main->conf.auto_tc_result_type, "Failure") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_tc_result_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (!data->fault_code && CWMP_STRCMP(cwmp_main->conf.auto_tc_result_type, "Success") != 0 && CWMP_STRCMP(cwmp_main->conf.auto_tc_result_type, "Both") != 0)
|
|
return false;
|
|
|
|
if (CWMP_STRLEN(data->file_type) == 0)
|
|
return false;
|
|
|
|
//TODO check if the file_type is among the FileTypeFilter
|
|
return true;
|
|
}
|
|
|
|
static void send_transfer_complete_notif(struct blob_attr *msg)
|
|
{
|
|
if (!cwmp_main->conf.auto_tc_enable) {
|
|
CWMP_LOG(INFO, "Autonomous TransferComplete is disabled");
|
|
return;
|
|
}
|
|
(void)msg;
|
|
CWMP_LOG(INFO, "Received TRANSFER COMPLETE EVENT");
|
|
const struct blobmsg_policy p[2] = {
|
|
{ "name", BLOBMSG_TYPE_STRING },
|
|
{ "input", BLOBMSG_TYPE_TABLE }
|
|
};
|
|
|
|
const struct blobmsg_policy p1[6] = {
|
|
{ "TransferURL", BLOBMSG_TYPE_STRING },
|
|
{ "TransferType", BLOBMSG_TYPE_STRING },
|
|
{ "StartTime", BLOBMSG_TYPE_STRING },
|
|
{ "CompleteTime", BLOBMSG_TYPE_STRING },
|
|
{ "FaultCode", BLOBMSG_TYPE_INT32 },
|
|
{ "FaultString", BLOBMSG_TYPE_STRING }
|
|
};
|
|
|
|
struct blob_attr *tb[2] = {NULL, NULL};
|
|
blobmsg_parse(p, 2, tb, blob_data(msg), blob_len(msg));
|
|
|
|
if (tb[1]) {
|
|
char file_type[256] = {0};
|
|
|
|
char *str = blobmsg_format_json_indent(tb[1], true, -1);
|
|
CWMP_LOG(INFO, "%s\n", str);
|
|
FREE(str);
|
|
|
|
struct blob_attr *tb1[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
|
blobmsg_parse(p1, 6, tb1, blobmsg_data(tb[1]), blobmsg_len(tb[1]));
|
|
|
|
auto_transfer_complete *data = calloc(1, sizeof(auto_transfer_complete));
|
|
if (data == NULL)
|
|
return;
|
|
|
|
data->announce_url = strdup("");
|
|
data->transfer_url = strdup(tb1[0] ? blobmsg_get_string(tb1[0]) : "");
|
|
data->is_download = (tb1[1] && CWMP_STRCMP(blobmsg_get_string(tb1[1]), "Download") == 0) ? true : false;
|
|
data->file_size = 0;
|
|
data->target_file_name = strdup("");
|
|
snprintf(file_type, sizeof(file_type), "X %s %s", cwmp_main->deviceid.oui, data->is_download ? "Download" : "Upload");
|
|
data->file_type = strdup(file_type);
|
|
|
|
if (tb1[2]) {
|
|
data->start_time = CWMP_STRDUP(blobmsg_get_string(tb1[2]));
|
|
}
|
|
|
|
if (tb1[3]) {
|
|
data->complete_time = CWMP_STRDUP(blobmsg_get_string(tb1[3]));
|
|
}
|
|
|
|
data->fault_code = tb1[4] ? blobmsg_get_u32(tb1[4]) : 0;
|
|
if (data->fault_code)
|
|
data->fault_code = 9001;
|
|
|
|
if (tb1[5]) {
|
|
data->fault_string = CWMP_STRDUP(blobmsg_get_string(tb1[5]));
|
|
}
|
|
|
|
// Check autonomous_transfer_complete data
|
|
if (validate_transfer_complete_data(data) == false) {
|
|
CWMP_LOG(INFO, "autonomous transfer complete data is not valid");
|
|
free_autonomous_transfer_complete_data(data);
|
|
return;
|
|
}
|
|
if ((cwmp_main->auto_tc_id < 0) || (cwmp_main->auto_tc_id >= MAX_INT_ID)) {
|
|
cwmp_main->auto_tc_id = 0;
|
|
}
|
|
cwmp_main->auto_tc_id++;
|
|
data->id = cwmp_main->auto_tc_id;
|
|
bkp_session_insert_autonomous_transfer_complete(data);
|
|
bkp_session_save();
|
|
|
|
CWMP_LOG(INFO, "autonomous transfer complete event added");
|
|
struct session_timer_event *ubus_inform_event = calloc(1, sizeof(struct session_timer_event));
|
|
|
|
ubus_inform_event->extra_data = data;
|
|
ubus_inform_event->session_timer_evt.cb = cwmp_schedule_session_with_event;
|
|
ubus_inform_event->event = EVENT_IDX_10AUTONOMOUS_TRANSFER_COMPLETE;
|
|
trigger_cwmp_session_timer_with_event(&ubus_inform_event->session_timer_evt);
|
|
}
|
|
}
|
|
|
|
static struct autonomous_event event_info[] = {
|
|
{ "Device.SoftwareModules.DUStateChange!", send_du_state_change_notif },
|
|
{ "Device.LocalAgent.TransferComplete!", send_transfer_complete_notif }
|
|
};
|
|
|
|
static void send_autonomous_notification(char *ev_name, struct blob_attr *msg)
|
|
{
|
|
int i;
|
|
|
|
if (!ev_name)
|
|
return;
|
|
|
|
int count = sizeof(event_info)/sizeof(struct autonomous_event);
|
|
for (i = 0; i < count; i++) {
|
|
if (CWMP_STRCMP(event_info[i].name, ev_name) == 0) {
|
|
autonomous_event_callback cb = event_info[i].cb;
|
|
cb(msg);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void autonomous_notification_handler(struct ubus_context *ctx __attribute__((unused)),
|
|
struct ubus_event_handler *ev __attribute__((unused)),
|
|
const char *type __attribute__((unused)), struct blob_attr *msg)
|
|
{
|
|
if (!msg)
|
|
return;
|
|
|
|
size_t len = (size_t)blobmsg_data_len(msg);
|
|
struct blob_attr *attr;
|
|
|
|
__blob_for_each_attr(attr, blobmsg_data(msg), len) {
|
|
const char *attr_name = blobmsg_name(attr);
|
|
if (attr_name != NULL && CWMP_STRCMP(attr_name, "name") == 0) {
|
|
send_autonomous_notification(blobmsg_data(attr), msg);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void free_autonomous_du_state_change_complete_data(auto_du_state_change_compl *p)
|
|
{
|
|
if (p == NULL)
|
|
return;
|
|
FREE(p->uuid);
|
|
FREE(p->ver);
|
|
FREE(p->current_state);
|
|
FREE(p->start_time);
|
|
FREE(p->complete_time);
|
|
FREE(p->fault_string);
|
|
FREE(p->operation);
|
|
FREE(p);
|
|
}
|
|
|
|
void free_autonomous_transfer_complete_data(auto_transfer_complete *p)
|
|
{
|
|
if (p == NULL)
|
|
return;
|
|
FREE(p->announce_url);
|
|
FREE(p->transfer_url);
|
|
FREE(p->file_type);
|
|
FREE(p->start_time);
|
|
FREE(p->complete_time);
|
|
FREE(p->fault_string);
|
|
FREE(p->target_file_name);
|
|
FREE(p);
|
|
}
|
|
int cwmp_rpc_acs_destroy_data_autonomous_du_state_change_complete(struct rpc *rpc)
|
|
{
|
|
if (rpc == NULL)
|
|
return 0;
|
|
|
|
auto_du_state_change_compl *p = (auto_du_state_change_compl *)rpc->extra_data;
|
|
if (p) {
|
|
bkp_session_delete_element("autonomous_du_state_change_complete", p->id);
|
|
free_autonomous_du_state_change_complete_data(p);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cwmp_rpc_acs_destroy_data_autonomous_transfer_complete(struct rpc *rpc)
|
|
{
|
|
auto_transfer_complete *p = (auto_transfer_complete *)rpc->extra_data;
|
|
if (p) {
|
|
bkp_session_delete_element("autonomous_transfer_complete", p->id);
|
|
free_autonomous_transfer_complete_data(p);
|
|
}
|
|
|
|
return 0;
|
|
}
|