2023-02-10 14:22:40 +08:00
|
|
|
#include <string.h>
|
2023-02-17 17:15:53 +08:00
|
|
|
#include <cjson/cJSON.h>
|
2023-02-10 14:22:40 +08:00
|
|
|
|
2023-02-17 17:15:53 +08:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "utils.h"
|
2023-02-10 14:22:40 +08:00
|
|
|
#include "ctrl_packet.h"
|
|
|
|
|
|
2023-02-17 17:15:53 +08:00
|
|
|
static const char *session_state_to_string(enum session_state state)
|
|
|
|
|
{
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case SESSION_STATE_OPENING:
|
|
|
|
|
return "opening";
|
|
|
|
|
case SESSION_STATE_CLONING:
|
|
|
|
|
return "closing";
|
|
|
|
|
case SESSION_STATE_ACTIVE:
|
|
|
|
|
return "active";
|
|
|
|
|
case SESSION_STATE_RESETALL:
|
|
|
|
|
return "resetall";
|
|
|
|
|
default:
|
|
|
|
|
return "unknown";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 14:22:40 +08:00
|
|
|
void ctrl_packet_parser_init(struct ctrl_pkt_parser *handler)
|
|
|
|
|
{
|
|
|
|
|
memset(handler, 0, sizeof(struct ctrl_pkt_parser));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return 0 : success
|
|
|
|
|
// return -1 : error
|
2023-02-17 17:15:53 +08:00
|
|
|
int ctrl_packet_parser_parse(struct ctrl_pkt_parser *handler, const char *data, size_t length)
|
2023-02-10 14:22:40 +08:00
|
|
|
{
|
2023-02-17 17:15:53 +08:00
|
|
|
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_IsNumber(item))
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR("%s: unexpected control packet: (invalid session_id format) %s", LOG_TAG_CTRLPKT, data);
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
handler->session_id = item->valueint;
|
|
|
|
|
|
|
|
|
|
// 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_CLONING;
|
|
|
|
|
}
|
|
|
|
|
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->policy_id_num = MIN(cJSON_GetArraySize(item), (int)(sizeof(handler->policy_ids) / sizeof(handler->policy_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->policy_ids[iter] = elem->valueint;
|
|
|
|
|
iter++;
|
|
|
|
|
|
|
|
|
|
if (iter == handler->policy_id_num)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
success_out:
|
|
|
|
|
cJSON_Delete(json);
|
2023-02-10 14:22:40 +08:00
|
|
|
return 0;
|
2023-02-17 17:15:53 +08:00
|
|
|
|
|
|
|
|
error_out:
|
|
|
|
|
cJSON_Delete(json);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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: policy_id_num : %d", LOG_TAG_POLICY, handler->policy_id_num);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < handler->policy_id_num; i++)
|
|
|
|
|
{
|
|
|
|
|
LOG_INFO("%s: policy_ids[%03d] : %i", LOG_TAG_POLICY, i, handler->policy_ids[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|