3 Star 2 Fork 0

y-cz / y_protocol

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
y_protocol.c 15.00 KB
一键复制 编辑 原始数据 按行查看 历史
y-cz 提交于 2023-12-21 14:19 . [版本] 1.发布版本 V0.2.1
/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2022 ycz. All rights reserved.
///
/// Created by ycz on 2022/1/2.
///
/// @brief
/// y_protocol 具体功能实现
///
/// ------------------------------------------------------------------------------------------------------------------------------------
/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------
#include "y_protocol.h"
#include <stdlib.h>
#include <string.h>
#include "y_log.h"
/// ------------------------------------------------------------------------------------------------------------------------------------
/// 私有函数
/// ------------------------------------------------------------------------------------------------------------------------------------
/// @brief 获取 sum8 校验值
/// @param [in] data 要处理数据的指针
/// @param [in] size 要处理数据的大小
/// @return sum8 校验值
static uint8_t _y_protocol_get_sum8(uint8_t *data, uint16_t size) {
uint8_t sum = 0;
while (size--) {
sum += *(data + size); // 求和
}
return ~sum; // 取反
}
/// @brief 加/解密数据
/// @param [in] encrypt_type 加/解密类型
/// @param [in] is_encrypt 加密还是解密
/// @param [in,out] data 要处理数据的指针
/// @param [in] size 要处理数据的大小
/// @retval true 成功
/// @retval false 失败
static bool _y_protocol_encrypt_decrypt(PROTOCOL_ENCRYPT_e encrypt_type, bool is_encrypt, uint8_t *data, uint16_t size) {
// 断言
YLOGA_FALSE(data);
YLOGA_FALSE(size);
// 根据对应的方式进行加密
switch (encrypt_type) {
case PROTOCOL_ENCRYPT_NONE: // 无加密
break;
case PROTOCOL_ENCRYPT_CAESAR_3: { // 凯撒加密 (字符偏移3 A->D B->E 以此类推)
for (int i = 0; i < size; ++i) {
if (is_encrypt) {
data[i] = data[i] + 3; // 加密数据
} else {
data[i] = data[i] - 3; // 解密数据
}
}
} break;
case PROTOCOL_ENCRYPT_XOR: { // 异或加密
for (int i = 0; i < size; ++i) {
data[i] = data[i] ^ 0X4A;
}
} break;
case PROTOCOL_ENCRYPT_MIXED: { // 混合加密 (先凯撒,在异或)
for (int i = 0; i < size; ++i) {
if (is_encrypt) {
data[i] = data[i] + 3; // 凯撒 加密数据
data[i] = data[i] ^ 0X4A; // 异或 加密数据
} else {
data[i] = data[i] ^ 0X4A; // 异或 解密数据
data[i] = data[i] - 3; // 凯撒 解密数据
}
}
} break;
default:
YLOGW("unsupported encrypt");
return false;
}
return true;
}
/// ------------------------------------------------------------------------------------------------------------------------------------
/// 公有函数
/// ------------------------------------------------------------------------------------------------------------------------------------
/// @brief 打印 y_protocol 版本信息
void y_protocol_print_version() {
YLOGI("V%d.%d.%d : module y_protocol", Y_PROTOCOL_MAJOR, Y_PROTOCOL_MINOR, Y_PROTOCOL_PATCH);
}
/// @brief 打包协议
/// @param [in] msg 协议结构体
/// @param [out] pack_data 打包好的数据指针
/// @param [out] pack_size 打包好的数据大小
/// @retval true 成功
/// @retval false 失败
bool y_protocol_pack(void *msg, uint8_t **pack_data, uint16_t *pack_size) {
// 断言
YLOGA_FALSE(msg);
YLOGA_FALSE(pack_data);
YLOGA_FALSE(pack_size);
// 获取协议头
PROTOCOL_HEAD_st *head = msg;
// 根据协议类型 准备打包后的内容
switch (head->type) {
case PROTOCOL_O2O_V1: { // 一对一 V1 协议类型
// 开辟空间
PROTOCOL_O2O_V1_st *p_msg = (PROTOCOL_O2O_V1_st *) msg;
*pack_size = sizeof(PROTOCOL_O2O_V1_st) - sizeof(p_msg->cmd_data) + p_msg->cmd_size + 1;
*pack_data = (uint8_t *) malloc(*pack_size); // 开辟 pack_data 空间 = 结构体大小 - 数据指针大小 + cmd数据大小 + 校验值大小
YLOGA_FALSE(*pack_data);
// 获取消息体大小
p_msg->head.size = sizeof(PROTOCOL_O2O_V1_st) - sizeof(PROTOCOL_HEAD_st) - sizeof(p_msg->cmd_data) + p_msg->cmd_size;
// 填充数据到 pack_data
memcpy(*pack_data, p_msg, sizeof(PROTOCOL_O2O_V1_st) - sizeof(p_msg->cmd_data)); // 填充结构体中的数据 不包含数据指针
if (p_msg->cmd_size) {
if (p_msg->cmd_data == NULL) {
free(*pack_data);
*pack_data = NULL;
*pack_size = 0;
YLOGE("cmd_size !=0 , but cmd_data is NULL");
return false;
}
memcpy(*pack_data + sizeof(PROTOCOL_O2O_V1_st) - sizeof(p_msg->cmd_data), p_msg->cmd_data, p_msg->cmd_size); // 填充数据指针中的数据
}
} break;
case PROTOCOL_M2M_V1: { // 多对多 V1 协议类型
// 开辟空间
PROTOCOL_M2M_V1_st *p_msg = (PROTOCOL_M2M_V1_st *) msg;
*pack_size = sizeof(PROTOCOL_M2M_V1_st) - sizeof(p_msg->cmd_data) + p_msg->cmd_size + 1;
*pack_data = (uint8_t *) malloc(*pack_size); // 开辟 pack_data 空间 = 结构体大小 - 数据指针大小 + cmd数据大小 + 校验值大小
YLOGA_FALSE(*pack_data);
// 获取消息体大小
p_msg->head.size = sizeof(PROTOCOL_M2M_V1_st) - sizeof(PROTOCOL_HEAD_st) - sizeof(p_msg->cmd_data) + p_msg->cmd_size;
// 填充数据到 pack_data
memcpy(*pack_data, p_msg, sizeof(PROTOCOL_M2M_V1_st) - sizeof(p_msg->cmd_data)); // 填充结构体中的数据 不包含数据指针
if (p_msg->cmd_size) {
if (p_msg->cmd_data == NULL) {
free(*pack_data);
*pack_data = NULL;
*pack_size = 0;
YLOGE("cmd_size !=0 , but cmd_data is NULL");
return false;
}
memcpy(*pack_data + sizeof(PROTOCOL_M2M_V1_st) - sizeof(p_msg->cmd_data), p_msg->cmd_data, p_msg->cmd_size); // 填充数据指针中的数据
}
} break;
default:
YLOGW("unsupported pack type");
return false;
}
// 添加累加校验和
(*pack_data)[(*pack_size) - 1] = _y_protocol_get_sum8(*pack_data, (*pack_size) - 1);
// 加密数据
if (_y_protocol_encrypt_decrypt(head->encrypt, true, *pack_data + sizeof(PROTOCOL_HEAD_st), head->size + 1) == false) {
free(*pack_data);
*pack_data = NULL;
*pack_size = 0;
YLOGE("encrypt data error");
return false;
}
return true;
}
/// @brief 解包协议
/// @param [in] unpack_data 解包数据指针
/// @param [in] unpack_size 解包数据大小
/// @param [out] msg 解包后的协议格式结构体
/// @retval true 成功
/// @retval false 失败
bool y_protocol_unpack(uint8_t *unpack_data, uint16_t unpack_size, void **msg) {
// 断言
YLOGA_FALSE(unpack_data);
YLOGA_FALSE(unpack_size <= sizeof(PROTOCOL_HEAD_st));
YLOGA_FALSE(msg);
// 获取协议头
PROTOCOL_HEAD_st *head = (PROTOCOL_HEAD_st *) unpack_data;
if (unpack_size != head->size + sizeof(PROTOCOL_HEAD_st) + 1 || head->size == 0) {
return false; // 数据不够 或 没有消息数据
}
// 解密数据
if (_y_protocol_encrypt_decrypt(head->encrypt, false, unpack_data + sizeof(PROTOCOL_HEAD_st), head->size + 1) == false) {
YLOGE("decrypt data error");
return false;
}
// 检测累加校验和
if (_y_protocol_get_sum8(unpack_data, unpack_size - 1) != unpack_data[unpack_size - 1]) {
YLOGD("unpack_data check sum fail");
return false;
}
// 根据协议类型 解析协议内容
switch (head->type) {
case PROTOCOL_O2O_V1: { // 一对一 V1 协议类型
// 开辟协议结构体空间
PROTOCOL_O2O_V1_st *p_msg = (PROTOCOL_O2O_V1_st *) malloc(sizeof(PROTOCOL_O2O_V1_st));
YLOGA_FALSE(p_msg);
// 填充数据到结构体
uint16_t tmp_size = sizeof(PROTOCOL_O2O_V1_st) - sizeof(p_msg->cmd_data); // 协议除指针部分占用大小
memcpy(p_msg, unpack_data, tmp_size);
if (p_msg->cmd_size != (unpack_size - tmp_size - 1)) {
free(p_msg);
YLOGE("cmd_size error");
return false;
}
if (p_msg->cmd_size) {
p_msg->cmd_data = (uint8_t *) malloc(p_msg->cmd_size);
if (p_msg->cmd_data == NULL) {
free(p_msg);
YLOGE("malloc cmd_data fail");
return false;
}
memcpy(p_msg->cmd_data, unpack_data + tmp_size, p_msg->cmd_size);
}
// 将解包好的协议数据带出去
*msg = p_msg;
} break;
case PROTOCOL_M2M_V1: { // 多对多 V1 协议类型
// 开辟协议结构体空间
PROTOCOL_M2M_V1_st *p_msg = (PROTOCOL_M2M_V1_st *) malloc(sizeof(PROTOCOL_M2M_V1_st));
YLOGA_FALSE(p_msg);
// 填充数据到结构体
uint16_t tmp_size = sizeof(PROTOCOL_M2M_V1_st) - sizeof(p_msg->cmd_data); // 协议除指针部分占用大小
memcpy(p_msg, unpack_data, tmp_size);
if (p_msg->cmd_size != (unpack_size - tmp_size - 1)) {
free(p_msg);
YLOGE("cmd_size error");
return false;
}
if (p_msg->cmd_size) {
p_msg->cmd_data = (uint8_t *) malloc(p_msg->cmd_size);
if (p_msg->cmd_data == NULL) {
free(p_msg);
YLOGE("malloc cmd_data fail");
return false;
}
memcpy(p_msg->cmd_data, unpack_data + tmp_size, p_msg->cmd_size);
}
// 将解包好的协议数据带出去
*msg = p_msg;
} break;
default:
YLOGW("unsupported unpack type");
return false;
}
return true;
}
/// @brief 删除协议消息
/// @param [in] msg 协议格式结构体
/// @retval true 成功
/// @retval false 失败
bool y_protocol_delete(void *msg) {
// 断言
YLOGA_FALSE(msg);
// 获取协议头
PROTOCOL_HEAD_st *head = (PROTOCOL_HEAD_st *) msg;
// 根据类型删除消息
switch (head->type) {
case PROTOCOL_O2O_V1: { // 一对一 V1 协议类型
PROTOCOL_O2O_V1_st *p_msg = (PROTOCOL_O2O_V1_st *) msg;
if (p_msg->cmd_data && p_msg->cmd_size) {
free(p_msg->cmd_data);
}
free(p_msg);
return true;
}
case PROTOCOL_M2M_V1: { // 多对多 V1 协议类型
PROTOCOL_M2M_V1_st *p_msg = (PROTOCOL_M2M_V1_st *) msg;
if (p_msg->cmd_data && p_msg->cmd_size) {
free(p_msg->cmd_data);
}
free(p_msg);
return true;
}
default:
return false;
}
}
/// @brief 转存消息 (使用 malloc 创建, 使用后需要释放)
/// @param [in] msg 协议格式结构体
/// @return 转存消息
void *y_protocol_dump(void *msg) {
// 断言
YLOGA_NULL(msg);
// 获取协议头
PROTOCOL_HEAD_st *head = (PROTOCOL_HEAD_st *) msg;
// 根据协议类型 转存协议内容
switch (head->type) {
case PROTOCOL_O2O_V1: { // 一对一 V1 协议类型
// 开辟空间
PROTOCOL_O2O_V1_st *p_msg = (PROTOCOL_O2O_V1_st *) malloc(sizeof(PROTOCOL_O2O_V1_st));
YLOGA_NULL(p_msg);
memcpy(p_msg, msg, sizeof(PROTOCOL_O2O_V1_st));
if (p_msg->cmd_data) {
p_msg->cmd_data = (uint8_t *) malloc(p_msg->cmd_size);
if (p_msg->cmd_data == NULL) {
free(p_msg);
YLOGE("malloc cmd_data fail");
return NULL;
}
memcpy(p_msg->cmd_data, ((PROTOCOL_O2O_V1_st *) msg)->cmd_data, p_msg->cmd_size);
}
return p_msg;
}
case PROTOCOL_M2M_V1: { // 多对多 V1 协议类型
// 开辟空间
PROTOCOL_M2M_V1_st *p_msg = (PROTOCOL_M2M_V1_st *) malloc(sizeof(PROTOCOL_M2M_V1_st));
YLOGA_NULL(p_msg);
memcpy(p_msg, msg, sizeof(PROTOCOL_M2M_V1_st));
if (p_msg->cmd_data) {
p_msg->cmd_data = (uint8_t *) malloc(p_msg->cmd_size);
if (p_msg->cmd_data == NULL) {
free(p_msg);
YLOGE("malloc cmd_data fail");
return NULL;
}
memcpy(p_msg->cmd_data, ((PROTOCOL_M2M_V1_st *) msg)->cmd_data, p_msg->cmd_size);
}
return p_msg;
}
default:
YLOGW("unsupported dump type");
return NULL;
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/y-cz/y_protocol.git
git@gitee.com:y-cz/y_protocol.git
y-cz
y_protocol
y_protocol
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891