2018-02-24 00:30:12 +01:00
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
#include <errno.h>
|
2018-03-04 16:59:20 +01:00
|
|
|
|
2018-02-24 00:30:44 +01:00
|
|
|
#include "mavl.h"
|
2018-03-17 19:32:44 +01:00
|
|
|
|
2018-03-05 20:39:15 +01:00
|
|
|
#include "dbg.h"
|
2018-03-04 16:59:20 +01:00
|
|
|
#include "log.h"
|
2018-02-24 00:30:12 +01:00
|
|
|
|
2018-03-12 11:22:06 +01:00
|
|
|
#include "msgset.h"
|
|
|
|
#include "ktv.h"
|
2018-02-24 00:30:12 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static int cmp_cw_elemhandler_by_id(const void *elem1, const void *elem2)
|
|
|
|
{
|
|
|
|
const struct cw_ElemHandler *e1 = elem1;
|
|
|
|
const struct cw_ElemHandler *e2 = elem2;
|
2018-02-24 00:30:44 +01:00
|
|
|
int r;
|
|
|
|
r = e1->id - e2->id;
|
2018-03-11 10:34:20 +01:00
|
|
|
if (r != 0)
|
2018-02-24 00:30:44 +01:00
|
|
|
return r;
|
|
|
|
r = e1->vendor - e2->vendor;
|
2018-03-11 10:34:20 +01:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
r = e1->proto - e2->proto;
|
|
|
|
if (r != 0)
|
2018-02-24 00:30:44 +01:00
|
|
|
return r;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static int cmp_cw_elemhandler_by_key(const void *elem1, const void *elem2)
|
|
|
|
{
|
|
|
|
const struct cw_ElemHandler *e1 = elem1;
|
|
|
|
const struct cw_ElemHandler *e2 = elem2;
|
|
|
|
return strcmp(e1->key, e2->key);
|
2018-03-03 08:15:19 +01:00
|
|
|
}
|
2018-02-24 00:30:44 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static int cmp_msgdata(const void *elem1, const void *elem2)
|
|
|
|
{
|
|
|
|
const struct cw_MsgData *e1 = elem1;
|
|
|
|
const struct cw_MsgData *e2 = elem2;
|
2018-02-24 01:52:39 +01:00
|
|
|
return e1->type - e2->type;
|
2018-02-24 00:30:44 +01:00
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static int cmp_elemdata(const void *elem1, const void *elem2)
|
2018-03-03 17:42:28 +01:00
|
|
|
{
|
2018-03-11 10:34:20 +01:00
|
|
|
const struct cw_ElemData *e1 = elem1;
|
|
|
|
const struct cw_ElemData *e2 = elem2;
|
2018-03-03 17:42:28 +01:00
|
|
|
int r;
|
|
|
|
r = e1->id - e2->id;
|
2018-03-11 10:34:20 +01:00
|
|
|
if (r != 0)
|
2018-03-03 17:42:28 +01:00
|
|
|
return r;
|
|
|
|
r = e1->vendor - e2->vendor;
|
2018-03-11 10:34:20 +01:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
r = e1->proto - e2->proto;
|
|
|
|
if (r != 0)
|
2018-03-03 17:42:28 +01:00
|
|
|
return r;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static void msgdata_destroy(struct cw_MsgData *data)
|
|
|
|
{
|
2018-03-03 08:15:19 +01:00
|
|
|
if (!data)
|
|
|
|
return;
|
2018-03-12 18:01:40 +01:00
|
|
|
if (data->elements_list)
|
2018-03-03 08:15:19 +01:00
|
|
|
mlist_destroy(data->elements_list);
|
2018-03-12 18:01:40 +01:00
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
if (data->elements_tree)
|
2018-03-11 10:34:20 +01:00
|
|
|
mavl_destroy(data->elements_tree);
|
2018-03-03 08:15:19 +01:00
|
|
|
free(data);
|
|
|
|
}
|
2018-02-24 00:30:44 +01:00
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static void del_mavl_msdgdata(void *d)
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
msgdata_destroy(d);
|
2018-03-03 17:42:28 +01:00
|
|
|
}
|
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Destroy a message set
|
|
|
|
* @param set Message set to destroy
|
|
|
|
*/
|
2018-03-11 10:34:20 +01:00
|
|
|
void cw_msgset_destroy(struct cw_MsgSet *set)
|
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
if (set->msgdata)
|
|
|
|
mavl_destroy(set->msgdata);
|
2018-03-03 17:42:28 +01:00
|
|
|
if (set->handlers_by_id)
|
|
|
|
mavl_destroy(set->handlers_by_id);
|
|
|
|
if (set->handlers_by_key)
|
|
|
|
mavl_destroy(set->handlers_by_key);
|
2018-02-24 00:30:44 +01:00
|
|
|
free(set);
|
|
|
|
}
|
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
/**
|
|
|
|
* @brief Create a message set
|
|
|
|
* @return Message set create, NULL if an error has occured
|
|
|
|
*/
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_MsgSet *cw_msgset_create()
|
|
|
|
{
|
2018-02-24 00:30:44 +01:00
|
|
|
|
|
|
|
/* allocate memory for a message_set */
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_MsgSet *set = malloc(sizeof(struct cw_MsgSet));
|
|
|
|
if (set == NULL)
|
2018-02-24 00:30:44 +01:00
|
|
|
return NULL;
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
memset(set, 0, sizeof(struct cw_MsgSet));
|
2018-02-24 00:30:44 +01:00
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
/* create mavl for all_elems by id */
|
2018-03-11 10:34:20 +01:00
|
|
|
set->handlers_by_id = mavl_create(cmp_cw_elemhandler_by_id, NULL,
|
|
|
|
sizeof(struct cw_ElemHandler));
|
|
|
|
if (set->handlers_by_id == NULL) {
|
2018-03-03 08:15:19 +01:00
|
|
|
cw_msgset_destroy(set);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
/* create mavl for all_elems by key */
|
2018-03-11 10:34:20 +01:00
|
|
|
set->handlers_by_key = mavl_create(cmp_cw_elemhandler_by_key, NULL,
|
|
|
|
sizeof(struct cw_ElemHandler));
|
|
|
|
if (set->handlers_by_key == NULL) {
|
2018-03-03 08:15:19 +01:00
|
|
|
cw_msgset_destroy(set);
|
2018-02-24 00:30:44 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create mavl for messages */
|
2018-03-11 10:34:20 +01:00
|
|
|
set->msgdata = mavl_create(cmp_msgdata, del_mavl_msdgdata,
|
|
|
|
sizeof(struct cw_MsgData));
|
|
|
|
if (set->msgdata == NULL) {
|
2018-03-03 08:15:19 +01:00
|
|
|
cw_msgset_destroy(set);
|
2018-02-24 00:30:44 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-03-12 11:22:06 +01:00
|
|
|
|
|
|
|
set->types_tree = cw_ktv_create_types_tree();
|
|
|
|
if (set->types_tree == NULL){
|
|
|
|
cw_msgset_destroy(set);
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-02-24 00:30:44 +01:00
|
|
|
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_ElemHandler *cw_msgset_get_elemhandler(struct cw_MsgSet *set,
|
|
|
|
int proto, int vendor, int id)
|
2018-03-03 17:42:28 +01:00
|
|
|
{
|
|
|
|
struct cw_ElemHandler search;
|
2018-03-11 10:34:20 +01:00
|
|
|
search.proto = proto;
|
|
|
|
search.vendor = vendor;
|
|
|
|
search.id = id;
|
|
|
|
return mavl_find(set->handlers_by_id, &search);
|
2018-03-03 17:42:28 +01:00
|
|
|
}
|
2018-02-24 00:30:44 +01:00
|
|
|
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
static int update_msgdata(struct cw_MsgSet *set, struct cw_MsgData *msgdata,
|
|
|
|
struct cw_MsgDef *msgdef)
|
2018-03-03 17:42:28 +01:00
|
|
|
{
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_ElemDef *elemdef;
|
2018-03-11 00:56:41 +01:00
|
|
|
struct cw_ElemData ed, *result;
|
2018-03-12 11:22:06 +01:00
|
|
|
mavliter_t it;
|
2018-03-11 10:34:20 +01:00
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
/* iterate through all defined elements */
|
2018-03-11 10:34:20 +01:00
|
|
|
for (elemdef = msgdef->elements; elemdef->id; elemdef++) {
|
|
|
|
struct cw_ElemHandler *handler;
|
2018-03-11 00:56:41 +01:00
|
|
|
int replaced;
|
2018-03-11 10:34:20 +01:00
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
handler = cw_msgset_get_elemhandler(set,
|
2018-03-11 10:34:20 +01:00
|
|
|
elemdef->proto,
|
|
|
|
elemdef->vendor, elemdef->id);
|
2018-03-05 20:39:15 +01:00
|
|
|
/* check if a handler for our element already exists */
|
2018-03-11 10:34:20 +01:00
|
|
|
if (!handler) {
|
2018-03-19 17:26:01 +01:00
|
|
|
cw_log(LOG_ERR, "Creating message set: No handler for message element: %d %d %d [%s]",
|
|
|
|
elemdef->proto, elemdef->vendor, elemdef->id, cw_strelem(elemdef->id));
|
2018-03-03 17:42:28 +01:00
|
|
|
continue;
|
|
|
|
}
|
2018-03-12 11:22:06 +01:00
|
|
|
|
2018-03-25 22:38:07 +02:00
|
|
|
/* if (handler->type != NULL){
|
2018-03-12 11:22:06 +01:00
|
|
|
if (mavl_add_ptr( set->types_tree, handler->type ) == NULL){
|
|
|
|
cw_log(LOG_ERR, "Can't add type from handler: %s", strerror(errno));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2018-03-25 22:38:07 +02:00
|
|
|
*/
|
2018-03-11 10:34:20 +01:00
|
|
|
|
|
|
|
ed.id = elemdef->id;
|
|
|
|
ed.proto = elemdef->proto;
|
|
|
|
ed.vendor = elemdef->vendor;
|
|
|
|
ed.mand = elemdef->mand;
|
|
|
|
|
2018-03-12 18:01:40 +01:00
|
|
|
/* add message element to the elements tree */
|
2018-03-11 00:56:41 +01:00
|
|
|
result = mavl_replace(msgdata->elements_tree, &ed, &replaced);
|
2018-03-05 20:39:15 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
if (!replaced) {
|
|
|
|
cw_dbg(DBG_MOD, " adding message element %d %d %d - %s",
|
|
|
|
elemdef->proto,
|
|
|
|
elemdef->vendor, elemdef->id, handler->name);
|
|
|
|
} else {
|
|
|
|
cw_dbg(DBG_MOD, " replacing message element %d %d %d - %s",
|
|
|
|
elemdef->proto,
|
|
|
|
elemdef->vendor, elemdef->id, handler->name);
|
|
|
|
}
|
2018-03-12 18:01:40 +01:00
|
|
|
|
2018-04-07 19:28:00 +02:00
|
|
|
/* add/delete/replace message elemeent to/from/in the elements list */
|
2018-03-12 18:01:40 +01:00
|
|
|
switch ( elemdef->op & 0xff){
|
|
|
|
case CW_IGNORE:
|
|
|
|
break;
|
|
|
|
case CW_DELETE:
|
2018-04-07 19:28:00 +02:00
|
|
|
mlist_delete(msgdata->elements_list, &ed);
|
2018-03-12 18:01:40 +01:00
|
|
|
break;
|
|
|
|
case CW_APPEND:
|
|
|
|
mlist_append(msgdata->elements_list, &ed);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case CW_REPLACE:
|
|
|
|
if (mlist_replace(msgdata->elements_list, &ed)==NULL){
|
|
|
|
mlist_append(msgdata->elements_list, &ed);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-03-03 17:42:28 +01:00
|
|
|
}
|
2018-03-11 10:34:20 +01:00
|
|
|
|
2018-03-12 18:01:40 +01:00
|
|
|
|
2018-03-12 11:22:06 +01:00
|
|
|
if (msgdata->mand_keys!=NULL){
|
|
|
|
mlist_destroy(msgdata->mand_keys);
|
|
|
|
}
|
|
|
|
msgdata->mand_keys = mlist_create_conststr();
|
|
|
|
|
|
|
|
mavliter_init(&it,msgdata->elements_tree);
|
|
|
|
mavliter_foreach(&it){
|
|
|
|
struct cw_ElemHandler *handler;
|
|
|
|
result = mavliter_get(&it);
|
|
|
|
|
|
|
|
handler = cw_msgset_get_elemhandler(set,
|
|
|
|
result->proto,
|
|
|
|
result->vendor, result->id);
|
|
|
|
if (result->mand){
|
|
|
|
mlist_append_ptr(msgdata->mand_keys,(void*)handler->key);
|
|
|
|
cw_dbg(DBG_MOD," Add mandatory key: %s",handler->key);
|
|
|
|
}
|
|
|
|
/*//printf("Have Result %d %d - %s\n",result->id,result->mand, handler->key);*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2018-02-24 23:58:31 +01:00
|
|
|
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
int cw_msgset_add(struct cw_MsgSet *set,
|
|
|
|
struct cw_MsgDef messages[], struct cw_ElemHandler handlers[]
|
|
|
|
)
|
|
|
|
{
|
2018-02-24 23:58:31 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_ElemHandler *handler;
|
|
|
|
struct cw_MsgDef *msgdef;
|
2018-03-03 17:42:28 +01:00
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
/* Create mavl for all handlers */
|
2018-03-11 10:34:20 +01:00
|
|
|
for (handler = handlers; handler->id; handler++) {
|
|
|
|
cw_dbg(DBG_MOD, "Adding handler for element %d - %s - with key: %s",
|
|
|
|
handler->id, handler->name, handler->key);
|
|
|
|
mavl_replace(set->handlers_by_id, handler, NULL);
|
|
|
|
mavl_replace(set->handlers_by_key, handler, NULL);
|
2018-03-03 08:15:19 +01:00
|
|
|
}
|
2018-02-24 23:58:31 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
for (msgdef = messages; msgdef->type != 0; msgdef++) {
|
2018-03-11 00:56:41 +01:00
|
|
|
struct cw_MsgData search;
|
|
|
|
struct cw_MsgData *msg;
|
|
|
|
int exists;
|
2018-03-11 10:34:20 +01:00
|
|
|
|
2018-04-08 16:48:13 +02:00
|
|
|
/* add the message */
|
2018-03-11 10:34:20 +01:00
|
|
|
search.type = msgdef->type;
|
|
|
|
msg = mavl_add(set->msgdata, &search, &exists);
|
|
|
|
if (msg == NULL) {
|
|
|
|
cw_log(LOG_ERR, "Can't create messae");
|
|
|
|
return 0;
|
2018-03-04 16:59:20 +01:00
|
|
|
}
|
2018-03-11 10:34:20 +01:00
|
|
|
|
2018-04-08 16:48:13 +02:00
|
|
|
/* Look if message already exists */
|
2018-03-11 10:34:20 +01:00
|
|
|
if (!exists) {
|
2018-04-08 16:48:13 +02:00
|
|
|
/* message is fresh createt, initialize data */
|
2018-03-11 10:34:20 +01:00
|
|
|
msg->elements_tree = mavl_create(cmp_elemdata, NULL,
|
|
|
|
sizeof(struct cw_ElemData));
|
2018-03-12 11:22:06 +01:00
|
|
|
msg->mand_keys=NULL;
|
2018-03-12 18:01:40 +01:00
|
|
|
msg->elements_list = mlist_create(cmp_elemdata,NULL,sizeof(struct cw_ElemData));
|
2018-04-08 16:48:13 +02:00
|
|
|
msg->postprocess=NULL;
|
2018-03-11 00:56:41 +01:00
|
|
|
}
|
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
/* Overwrite the found message */
|
|
|
|
if (msgdef->name)
|
2018-03-11 10:34:20 +01:00
|
|
|
msg->name = msgdef->name;
|
2018-03-03 17:42:28 +01:00
|
|
|
if (msgdef->states)
|
2018-03-11 10:34:20 +01:00
|
|
|
msg->states = msgdef->states;
|
2018-04-08 16:48:13 +02:00
|
|
|
if (msgdef->postprocess != NULL)
|
|
|
|
msg->postprocess = msgdef->postprocess;
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
msg->receiver = msgdef->receiver;
|
|
|
|
|
2018-03-03 08:15:19 +01:00
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
cw_dbg(DBG_MOD, "Add message Type:%d - %s ", msgdef->type, msgdef->name);
|
2018-03-05 20:39:15 +01:00
|
|
|
|
|
|
|
|
2018-03-11 10:34:20 +01:00
|
|
|
update_msgdata(set, msg, msgdef);
|
2018-02-24 00:30:44 +01:00
|
|
|
}
|
2018-03-12 11:22:06 +01:00
|
|
|
|
|
|
|
{
|
|
|
|
mavliter_t it;
|
|
|
|
cw_dbg(DBG_MOD," Known types:");
|
|
|
|
mavliter_init(&it,set->types_tree);
|
|
|
|
mavliter_foreach(&it){
|
|
|
|
struct cw_Type * t = mavliter_get_ptr(&it);
|
|
|
|
cw_dbg(DBG_MOD, " Type: %s", t->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
|
|
|
|
return 0;
|
2018-02-24 00:30:12 +01:00
|
|
|
}
|
2018-02-24 01:52:39 +01:00
|
|
|
|
2018-03-04 16:59:20 +01:00
|
|
|
/**
|
|
|
|
* @brief Find message data to a specific message
|
|
|
|
* @param set message set
|
|
|
|
* @param type message type to search for
|
|
|
|
* @return message data or NULL if not found
|
|
|
|
*/
|
2018-03-11 10:34:20 +01:00
|
|
|
struct cw_MsgData *cw_msgset_get_msgdata(struct cw_MsgSet *set, int type)
|
|
|
|
{
|
2018-03-03 08:15:19 +01:00
|
|
|
struct cw_MsgData search;
|
2018-03-11 10:34:20 +01:00
|
|
|
search.type = type;
|
2018-03-12 18:01:40 +01:00
|
|
|
return mavl_find(set->msgdata, &search);
|
2018-03-02 13:36:03 +01:00
|
|
|
}
|