This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-tsg-service-chaining-…/common/src/ctrl_packet.cpp

325 lines
9.5 KiB
C++

#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <cjson/cJSON.h>
#include "log.h"
#include "mpack.h"
#include "utils.h"
#include "ctrl_packet.h"
const char *session_state_to_string(enum session_state state)
{
switch (state)
{
case SESSION_STATE_OPENING:
return "opening";
case SESSION_STATE_CLOSING:
return "closing";
case SESSION_STATE_ACTIVE:
return "active";
case SESSION_STATE_RESETALL:
return "resetall";
default:
return "unknown";
}
}
void ctrl_packet_parser_init(struct ctrl_pkt_parser *handler)
{
memset(handler, 0, sizeof(struct ctrl_pkt_parser));
}
// return 0 : success
// return -1 : error
int ctrl_packet_parser_mpack(struct ctrl_pkt_parser *handler, const char *data, size_t length)
{
mpack_tree_t tree;
mpack_node_t root;
mpack_node_t temp;
mpack_node_t item;
mpack_error_t ret;
char buffer[16];
mpack_tree_init_data(&tree, data, length);
mpack_tree_parse(&tree);
root = mpack_tree_root(&tree);
if (mpack_node_is_nil(root))
{
LOG_ERROR("%s: unexpected control packet: (invalid mpack format)", LOG_TAG_CTRLPKT);
goto error_out;
}
// tsync
temp = mpack_node_map_cstr(root, "tsync");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (tsync no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
mpack_node_copy_cstr(temp, handler->tsync, sizeof(handler->tsync));
if (strcasecmp(handler->tsync, "2.0") != 0)
{
LOG_ERROR("%s: unexpected control packet: (invalid tsync value) %s", LOG_TAG_CTRLPKT, handler->tsync);
goto error_out;
}
// session_id
temp = mpack_node_map_cstr(root, "session_id");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (session_id no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
handler->session_id = mpack_node_u64(temp);
if (handler->session_id == 0)
{
LOG_ERROR("%s: unexpected control packet: (invalid session_id value) %lu", LOG_TAG_CTRLPKT, handler->session_id);
goto error_out;
}
// state
temp = mpack_node_map_cstr(root, "state");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (state no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
mpack_node_copy_cstr(temp, buffer, sizeof(buffer));
if (strcasecmp(buffer, "opening") == 0)
{
handler->state = SESSION_STATE_OPENING;
}
else if (strcasecmp(buffer, "active") == 0)
{
handler->state = SESSION_STATE_ACTIVE;
}
else if (strcasecmp(buffer, "closing") == 0)
{
handler->state = SESSION_STATE_CLOSING;
}
else if (strcasecmp(buffer, "resetall") == 0)
{
handler->state = SESSION_STATE_RESETALL;
}
else
{
LOG_ERROR("%s: unexpected control packet: (invalid state value) %s", LOG_TAG_CTRLPKT, buffer);
goto error_out;
}
if (handler->state != SESSION_STATE_ACTIVE)
{
goto success_out;
}
// method
temp = mpack_node_map_cstr(root, "method");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (method no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
mpack_node_copy_cstr(temp, handler->method, sizeof(handler->method));
if (strcasecmp(handler->method, "policy_update") != 0)
{
LOG_ERROR("%s: unexpected control packet: (invalid method value) %s", LOG_TAG_CTRLPKT, handler->method);
goto error_out;
}
// params
temp = mpack_node_map_cstr(root, "params");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (params no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
// params->sce
temp = mpack_node_map_cstr(temp, "sce");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (sce no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
// params->sce->rule_ids
temp = mpack_node_map_cstr(temp, "rule_ids");
if (mpack_node_is_nil(temp))
{
LOG_ERROR("%s: unexpected control packet: (rule_ids no found)", LOG_TAG_CTRLPKT);
goto error_out;
}
handler->rule_id_num = MIN(mpack_node_array_length(temp), (int)(sizeof(handler->rule_ids) / sizeof(handler->rule_ids[0])));
if (handler->rule_id_num <= 0)
{
LOG_ERROR("%s: unexpected control packet: (invalid rule id num) %ld", LOG_TAG_CTRLPKT, mpack_node_array_length(temp));
goto error_out;
}
for (int i = 0; i < handler->rule_id_num; i++)
{
item = mpack_node_array_at(temp, i);
handler->rule_ids[i] = mpack_node_u64(item);
}
success_out:
ret = mpack_tree_destroy(&tree);
if (ret != mpack_ok)
{
LOG_ERROR("%s: unexpected control packet: (mpack return error) %d", LOG_TAG_CTRLPKT, ret);
return -1;
}
return 0;
error_out:
mpack_tree_destroy(&tree);
return -1;
}
// return 0 : success
// return -1 : error
int ctrl_packet_parser_cjson(struct ctrl_pkt_parser *handler, const char *data, size_t length)
{
int iter = 0;
cJSON *item = NULL;
cJSON *elem = NULL;
cJSON *json = NULL;
json = cJSON_Parse(data);
if (json == NULL)
{
LOG_ERROR("%s: unexpected control packet: (invalid json format) %s", LOG_TAG_CTRLPKT, data);
return -1;
}
// tsync
item = cJSON_GetObjectItem(json, "tsync");
if (!item || !cJSON_IsString(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid tsync format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
memcpy(handler->tsync, item->valuestring, MIN(sizeof(handler->tsync), strlen(item->valuestring)));
// session_id
item = cJSON_GetObjectItem(json, "session_id");
if (!item || !cJSON_IsString(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid session_id format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
handler->session_id = atoll(item->valuestring);
// state
item = cJSON_GetObjectItem(json, "state");
if (!item || !cJSON_IsString(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid state format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
if (strcasecmp(item->valuestring, "opening") == 0)
{
handler->state = SESSION_STATE_OPENING;
}
else if (strcasecmp(item->valuestring, "active") == 0)
{
handler->state = SESSION_STATE_ACTIVE;
}
else if (strcasecmp(item->valuestring, "closing") == 0)
{
handler->state = SESSION_STATE_CLOSING;
}
else if (strcasecmp(item->valuestring, "resetall") == 0)
{
handler->state = SESSION_STATE_RESETALL;
}
else
{
LOG_ERROR("%s: unexpected control packet: (invalid state value) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
if (handler->state != SESSION_STATE_ACTIVE)
{
goto success_out;
}
// method
item = cJSON_GetObjectItem(json, "method");
if (!item || !cJSON_IsString(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid method format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
memcpy(handler->method, item->valuestring, MIN(sizeof(handler->method), strlen(item->valuestring)));
if (strcasecmp(item->valuestring, "policy_update") != 0)
{
LOG_ERROR("%s: unexpected control packet: (invalid method value) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
// params
item = cJSON_GetObjectItem(json, "params");
if (!item || !cJSON_IsObject(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid params format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
item = cJSON_GetObjectItem(item, "service_chaining");
if (!item || !cJSON_IsArray(item) || !cJSON_GetArraySize(item))
{
LOG_ERROR("%s: unexpected control packet: (invalid service_chaining format) %s", LOG_TAG_CTRLPKT, data);
goto error_out;
}
handler->rule_id_num = MIN(cJSON_GetArraySize(item), (int)(sizeof(handler->rule_ids) / sizeof(handler->rule_ids[0])));
cJSON_ArrayForEach(elem, item)
{
if (!cJSON_IsNumber(elem))
{
LOG_ERROR("%s: unexpected control packet: (invalid service_chaining value) %s", LOG_TAG_POLICY, data);
continue;
}
handler->rule_ids[iter] = elem->valueint;
iter++;
if (iter == handler->rule_id_num)
{
break;
}
}
success_out:
cJSON_Delete(json);
return 0;
error_out:
cJSON_Delete(json);
return -1;
}
// return 0 : success
// return -1 : error
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const char *data, size_t length)
{
// return ctrl_packet_parser_cjson(handler, data, length);
return ctrl_packet_parser_mpack(handler, data, length);
}
void ctrl_packet_parser_dump(struct ctrl_pkt_parser *handler)
{
if (handler)
{
LOG_INFO("%s: tsync : %s", LOG_TAG_POLICY, handler->tsync);
LOG_INFO("%s: session_id : %lu", LOG_TAG_POLICY, handler->session_id);
LOG_INFO("%s: state : %s", LOG_TAG_POLICY, session_state_to_string(handler->state));
LOG_INFO("%s: method : %s", LOG_TAG_POLICY, handler->method);
LOG_INFO("%s: rule_id_num : %d", LOG_TAG_POLICY, handler->rule_id_num);
for (int i = 0; i < handler->rule_id_num; i++)
{
LOG_INFO("%s: rule_ids[%03d] : %lu", LOG_TAG_POLICY, i, handler->rule_ids[i]);
}
}
}