HCoreBase/src/HDRPC.c
2025-09-08 13:53:16 +08:00

527 lines
13 KiB
C

#include "HDRPC.h"
#include "HDLog.h"
#include <stdint.h>
#include <string.h>
#ifndef LogD
#include <stdio.h>
#define LogD(format, ...) printf("[%s:%s:%d]"format "\r\n", __FILE_NAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
struct RPCInfo {
HDRPCSendData writeCall;
HDRPCCallBuffer *callback;
HDRPCSession *session;
uint8_t callLen;
};
static struct RPCInfo sInfo;
static void UpdateTimeout(HDRPCCallBuffer *callBuff) {
if (callBuff == NULL) {
return ;
}
if (callBuff->enbale == 0) {
return ;
}
uint32_t curr = HDLogGetTime();
if (curr - callBuff->time > HDRPC_TIMEOUT) {
callBuff->enbale = 0;
LogD("Call[%s] Timeout", callBuff->name);
}
}
static void Call(HDRPCSession *session) {
if (session == NULL) {
LogD("Session is nullptr");
return ;
}
// 不是用户数据, 说明不需要回调
const uint8_t index = session->index - 1;
if (session->index > 0 && session->args[index].type != kHDRPCUserData) {
LogD("func type[0x%x] Not call", session->args[index].type);
return ;
}
for (int i = 0; i < sInfo.callLen; i++) {
UpdateTimeout(&sInfo.callback[i]);
if (sInfo.callback[i].enbale == 0) {
continue;
}
if (sInfo.callback[i].nameLen != session->args[index].buffer.len) {
continue;
}
if (strncmp(sInfo.callback[i].name, (char *)session->args[index].buffer.data, session->args[index].buffer.len) != 0) {
continue;
}
LogD("Call[%s]", sInfo.callback[i].name);
sInfo.callback[i].callback(session);
LogD("Call[%s] End", sInfo.callback[i].name);
sInfo.callback[i].enbale = 0;
sInfo.callback[i].nameLen = 0;
sInfo.callback[i].name = NULL;
break;
}
}
static int16_t AddCall(HDRPCCallback callBack, const char *funcName, uint8_t nameLen) {
if (callBack == NULL || nameLen == 0) {
LogD("funcName[%s], len[%d] add Faild", funcName, nameLen);
return -1;
}
for (int i = 0; i < sInfo.callLen; i++) {
UpdateTimeout(&sInfo.callback[i]);
if (sInfo.callback[i].enbale == 1) {
continue;
}
sInfo.callback[i].enbale = 1;
sInfo.callback[i].callback = callBack;
sInfo.callback[i].nameLen = nameLen;
sInfo.callback[i].name = funcName;
sInfo.callback[i].time = HDLogGetTime();
return i;
}
LogD("add call is full, callLen[%d]", sInfo.callLen);
return -1;
}
static uint8_t GetArgLen(HDRPCArgs *args)
{
switch (args->type) {
case kHDRPCUserData:
case kHDRPCBuffer:
case kHDRPCString:
return args->buffer.len + 1;
case kHDRPCU8:
return sizeof(uint8_t);
case kHDRPCException:
case kHDRPCU16:
return sizeof(uint16_t);
case kHDRPCU32:
return sizeof(uint32_t);
#ifdef HDRPC_USE_64
case kHDRPCU64:
return sizeof(uint64_t);
#endif
default:
LogD("Not support type[0x%x]", args->type);
break;
}
return 0;
}
static void AddArgToBuffer(HDRPCArgs *args, uint8_t *data)
{
switch (args->type) {
case kHDRPCUserData:
case kHDRPCBuffer:
case kHDRPCString:
data[0] = args->buffer.len;
memcpy(data + 1, args->buffer.data, args->buffer.len);
break;
case kHDRPCU8:
data[0] = args->dataU8;
break;
case kHDRPCException:
case kHDRPCU16:
data[0] = args->dataU16 >> 8;
data[1] = args->dataU16 & 0xFF;
break;
case kHDRPCU32:
data[0] = args->dataU32 >> 24;
data[1] = (args->dataU32 >> 16) & 0xFF;
data[2] = (args->dataU32 >> 8) & 0xFF;
data[3] = args->dataU32 & 0xFF;
break;
#ifdef HDRPC_USE_64
case kHDRPCU64:
data[0] = args->dataU64 >> 56;
data[1] = (args->dataU64 >> 48) & 0xFF;
data[2] = (args->dataU64 >> 40) & 0xFF;
data[3] = (args->dataU64 >> 32) & 0xFF;
data[4] = (args->dataU64 >> 24) & 0xFF;
data[5] = (args->dataU64 >> 16) & 0xFF;
data[6] = (args->dataU64 >> 8) & 0xFF;
data[7] = args->dataU64 & 0xFF;
break;
#endif
default:
LogD("Not support type[0x%x]", args->type);
break;
}
}
static uint16_t IconvReadData(HDRPCSession *session, uint16_t type, uint8_t *data, uint16_t len) {
if (session == NULL || data == NULL || len == 0) {
LogD("read error, type[0x%x], len[%d]", type, len);
return len;
}
if (session->index >= session->len) {
LogD("index[%d] len[%d] error", session->index, session->len);
return len;
}
const uint8_t index = session->index++;
session->args[index].type = type;
switch (type) {
case kHDRPCUserData:
case kHDRPCBuffer:
case kHDRPCString:
if (len < 2) {
LogD("type[0x%x], len[%d] error", type, len);
return len;
}
session->args[index].buffer.len = data[0];
session->args[index].buffer.data = data + 1;
return session->args[index].buffer.len + 1;
case kHDRPCU8:
session->args[index].dataU8 = data[0];
return sizeof(uint8_t);
case kHDRPCException:
case kHDRPCU16:
if (len < sizeof(uint16_t)) {
LogD("type[0x%x], len[%d] error", type, len);
return len;
}
session->args[index].dataU16 = data[0] << 8 | data[1];
return sizeof(uint16_t);
case kHDRPCU32:
if (len < sizeof(uint32_t)) {
LogD("type[0x%x], len[%d] error", type, len);
return len;
}
session->args[index].dataU32 = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
return sizeof(uint32_t);
#ifdef HDRPC_USE_64
case kHDRPCU64:
if (len < sizeof(uint64_t)) {
LogD("type[0x%x], len[%d] error", type, len);
return len;
}
session->args[index].dataU64 = data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
return sizeof(uint64_t);
#endif
default:
LogD("Not support type[0x%x]", type);
break;
}
return 1;
}
static void ReadCall(HDRPCSession *session, void *data, uint16_t len) {
// 解析数据到参数会话
if (HDRPCParseArgs(data, len, session) == 0) {
LogD("Parse args faild");
}
// 无效功能码
if (session->func == HDRPC_INVAID_FUNC) {
LogD("Invalid Func[0x%x]", session->func);
return ;
}
Call(session);
}
void HDRPCInitSession(HDRPCSession *session, HDRPCArgs *args, uint8_t len)
{
if (session == NULL) {
return ;
}
session->index = 0;
session->len = len;
session->func = 0;
session->args = args;
if (args == NULL && len > 0) {
LogD("args is nullptr, len[%d] error", len);
session->len = 0;
}
for (uint16_t i = 0; i < session->len; ++i) {
memset(&session->args[i], 0, sizeof(HDRPCArgs));
}
}
void HDRPCInitCall(HDRPCSendData writeCall, HDRPCCallBuffer *callBuff, uint8_t len, HDRPCSession *buffer)
{
sInfo.writeCall = writeCall;
sInfo.callback = callBuff;
sInfo.session = buffer;
sInfo.callLen = len;
if (callBuff == NULL && len > 0) {
LogD("callBuff is nullptr, len[%d] error", len);
sInfo.callLen = 0;
}
for (uint16_t i = 0; i < sInfo.callLen; ++i) {
memset(&callBuff[i], 0, sizeof(HDRPCCallBuffer));
}
}
uint8_t _HDRPCAddArgs(HDRPCSession *session, uint8_t type, void *args, uint8_t len)
{
if (session == NULL) {
LogD("Session is nullptr");
return 0;
}
if (len == 0) {
LogD("type[0x%x], args len is 0", type);
return 0;
}
for (uint16_t i = 0; i < len; ++i) {
if (session->index >= session->len) {
LogD("Session type[0x%x] is full", type);
return 0;
}
const uint8_t index = session->index;
++session->index;
session->args[index].type = type;
switch (type) {
case kHDRPCU8:
session->args[index].dataU8 = *(uint8_t *)args;
break;
case kHDRPCException:
case kHDRPCU16:
session->args[index].dataU16 = *(uint16_t *)args;
break;
case kHDRPCU32:
session->args[index].dataU32 = *(uint32_t *)args;
break;
#ifdef HDRPC_USE_64
case kHDRPCU64:
session->args[index].dataU64 = *(uint64_t *)args;
break;
#endif
case kHDRPCUserData:
case kHDRPCBuffer:
case kHDRPCString:
session->args[index].buffer.data = (uint8_t *)args;
session->args[index].buffer.len = len;
return 1;
default:
LogD("Not support type[0x%x]", type);
break;
}
}
return 1;
}
uint8_t HDRPCParseArgs(void *data, uint16_t len, HDRPCSession *session)
{
if (session == NULL) {
return 0;
}
session->func = HDRPC_INVAID_FUNC;
if (len < 2) {
return 0;
}
/**
* 1 - 2字节 - 调用功能ID
* 2 - 多字节 - 参数包
* 参数包根据1字节类型判断对应长度
*/
session->index = 0;
uint8_t *d = (uint8_t *)data;
session->func = d[0] << 8 | d[1];
uint16_t index = 2;
while (index < len) {
const uint8_t type = d[index++];
if (index >= len) {
LogD("func[%x], type[0x%x], index[%d] len[%d] error", session->func, type, index, len);
return 0;
}
const uint8_t useLen = IconvReadData(session, type, d + index, len - index);
index += useLen;
}
return 1;
}
uint8_t _HDRPCCheckArgs(HDRPCSession *session, uint8_t *type, uint8_t len)
{
for (uint16_t i = 0; i < len; ++i) {
if (session->args[i].type != type[i]) {
LogD("Check index[%d] Type[0x%x] faild", i, type[i]);
return 0;
}
}
return 1;
}
HDRPCValue_t _HDRPCGetValue(HDRPCSession *session, uint8_t type, int index)
{
if (session == NULL) {
LogD("Session is nullptr");
return 0;
}
if (index < 0 || index >= session->len) {
LogD("index[%d] len[%d] error", index, session->len);
return 0;
}
if (session->args[index].type != type) {
LogD("index[%d] type[0x%x][0x%x] Not match", index, session->args[index].type, type);
return 0;
}
switch (type) {
case kHDRPCU8:
return session->args[index].dataU8;
case kHDRPCException:
case kHDRPCU16:
return session->args[index].dataU16;
case kHDRPCU32:
return session->args[index].dataU32;
#ifdef HDRPC_USE_64
case kHDRPCU64:
return session->args[index].dataU64;
#endif
default:
LogD("Not match type[0x%x] index[%d]", type, index);
break;
}
return 0;
}
void *_HDRPCGetData(HDRPCSession *session, uint8_t type, int index, uint8_t *len)
{
if (session == NULL) {
LogD("Session is nullptr");
return NULL;
}
if (index < 0 || index >= session->len) {
LogD("index[%d] len[%d] error", index, session->len);
return NULL;
}
if (session->args[index].type != type) {
LogD("index[%d] type[0x%x][0x%x] Not match", index, session->args[index].type, type);
return NULL;
}
switch (type) {
case kHDRPCUserData:
case kHDRPCBuffer:
if (len) {
*len = session->args[index].buffer.len;
}
return session->args[index].buffer.data;
case kHDRPCString:
if (len) {
*len = session->args[index].buffer.len / 2;
}
return session->args[index].buffer.data;
default:
LogD("Not match type[0x%x] index[%d]", type, index);
break;
}
return NULL;
}
void HDRPCReadData(void *data, uint16_t len)
{
if (sInfo.callback == NULL || sInfo.callLen ==0) {
return ;
}
HDRPCSession *session = sInfo.session;
if (session == NULL) {
HDRPCSession buff;
session = &buff;
HDRPCArgs args[HDRPC_USE_SESSION_ARGS];
HDRPCInitSession(session, args, HDRPC_USE_SESSION_ARGS);
ReadCall(session, data, len);
return ;
}
ReadCall(session, data, len);
}
void _HDRPCSendData(HDRPCSession *session, uint16_t funcCode, HDRPCCallback callBack, const char *funcName, uint8_t nameLen)
{
if (sInfo.writeCall == NULL) {
LogD("Write Call is nullptr");
return ;
}
if (session) {
session->func = funcCode;
}
do {
if (nameLen == 0 || callBack == NULL) {
break;
}
if (HDRPCAddUserData(session, (void *)funcName, nameLen) == 0) {
LogD("Add Call Data[%s] faild", funcName);
break;
}
if (AddCall(callBack, funcName, nameLen) == -1) {
LogD("Add Call[%s] faild", funcName);
}
} while (0);
sInfo.writeCall(session);
}
uint16_t HDRPCConvSendData(HDRPCSession *session, uint8_t *data, uint16_t len)
{
if (session == NULL || data == NULL || len < 2) {
return 0;
}
int useLen = 0;
data[useLen++] = session->func >> 8;
data[useLen++] = session->func & 0xFF;
for (int i = 0; i < session->index; ++i) {
const uint8_t argLen = GetArgLen(&session->args[i]);
if (useLen + 1 > len) {
LogD("write Buffer Not enough, len[%d] useLen[%d]", len, useLen);
break;
}
data[useLen++] = session->args[i].type;
AddArgToBuffer(&session->args[i], data + useLen);
useLen += argLen;
}
return useLen;
}