fusion/common/xbuf/xbuf.c

170 lines
5.2 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "xbuf.h"
#include "errno.h"
#include "hlog.h"
#define TAG "TAG_XBUF"
uint32_t xbuf_init(xbuf_handler *hdlr)
{
iobuffer_init(&hdlr->read_io);
return OK;
}
uint32_t xbuf_deinit(xbuf_handler *hdlr)
{
iobuffer_deinit(&hdlr->read_io);
return OK;
}
uint32_t xbuf_put(xbuf_handler *hdlr, const char *data, const uint32_t sz)
{
if ( OK == iobuffer_appendData(&hdlr->read_io, data, sz) )
{
return xbuf_flush(hdlr);
}
return NG;
}
uint32_t xbuf_flush(xbuf_handler *hdlr)
{
kpacket *packet = (kpacket*)hdlr->read_io.iodata;
//hlogd("xbuf_flush len:%d magic:%x %d %d",packet->tlv.L, packet->tlv.magic,hdlr->read_io.size,sizeof(kpacket));
while ( hdlr->read_io.size >= sizeof(kpacket) + packet->tlv.L ) /* 粘包 或 包不齐处理 */
{
if ( packet->tlv.magic == OS_PACKET_MAGIC && kpacket_calc_checksum(packet) == packet->tlv.checksum ){
{ /* 如果 注册了type 处理 */
for ( uint16_t i=0; i< hdlr->ev_list_sz; i++ ){
//hlogd("xbuf_flush len:%d magic:%x",packet->tlv.T, hdlr->ev_list[i].event);
if ( hdlr->ev_list[i].event == packet->tlv.T ){
hdlr->ev_list[i].on_event(packet);
break;
}
}
}
{ /* 增加未注册type的, packet 处理*/
if ( hdlr->on_packet )
{
hdlr->on_packet(packet);
}
}
}else{
hloge("invalid %s magic:0x%x, calc_checksum:%x %x, V:%s", __func__, packet->tlv.magic, kpacket_calc_checksum(packet), packet->tlv.checksum,packet->tlv.V);
}
/* 删除packet占用的内存后面的数据将前移到0位置 */
iobuffer_erase(&hdlr->read_io, 0, sizeof(kpacket) + packet->tlv.L);
}
return OK;
}
/************************************ for tester ************************************/
/* 应用层四步
**
** 一, 声明枚举指令 和 回调函数
** 二, 填写 packet_event 的 ev_list
** 三, 通过xbuf_init注册到xbuf
** 四, 收数xbuf_put到xbuf, 自动回调
**/
/* 第一步 */
enum{
CMD_SYNC = 0x0001, /* 握手指令 */
};
static uint32_t on_sync(const kpacket *packet){
hlogw("%s magic:0x%x, type:%x, extend:%u, len:%u, payload:%s", __func__, packet->tlv.magic, packet->tlv.T, packet->offset, packet->tlv.L, packet->tlv.V);
return OK;
}
static packet_event s_ev_list[]={
{CMD_SYNC, on_sync},
};
/* 第二步 */
static xbuf_handler handler = {
.ev_list = s_ev_list,
.ev_list_sz = sizeof(s_ev_list)/sizeof(s_ev_list[0]),
};
/* 第三和四步 */
static uint32_t kpacket_recv(char *data, uint32_t max_sz);
void xbuf_test()
{
xbuf_init(&handler);
{
/* 用iobuffer */
for ( uint32_t i=0; i<10; i++ )
{
if ( iobuffer_freesize(&handler.read_io) < 1024 ) /* 如果预期接收的数据不小于1024大小也可是256/512字节点 那么扩容一下, 随协议来定*/
{
iobuffer_reserve(&handler.read_io, 1024 + handler.read_io.size); /* 小于1024了申请多些内存 */
}
/*第一种: 直接读到xbuf的iobuffer, 减少一次内存拷贝 */
uint32_t read_cnt = kpacket_recv(handler.read_io.iodata + handler.read_io.size, iobuffer_freesize(&handler.read_io));
if ( read_cnt > 0 )
{
handler.read_io.size += read_cnt;
kpacket *packet = (kpacket*)handler.read_io.iodata;
hlogd("xbuf_test read_cnt:%u %s",read_cnt, packet->tlv.V);
xbuf_flush(&handler); /*将自动回调对应的on_type*/
}
//hlogd("xbuf_test i:%u",i);
}
hlogd("xbuf_test end");
}
xbuf_deinit(&handler);
}
/* 串口, rndis 等的接收*/
static uint32_t kpacket_recv(char *data, uint32_t max_sz)
{
/*******这段为模拟发送端发送的数据 ,即接收*******/
static uint32_t i;
char str[128]; /* 没必要memset 或 ={0}, sprintf 会补 0 */
sprintf(str, "{\"sync\":\"i m :%u\"}", i++);
uint32_t size = strlen(str) + 1; /*+1 for '\0'*/
kpacket *packet = kpacket(CMD_SYNC, size);
kpacket_put_string(packet, str);
kpacket_checksum(packet); /* 生成 crc16 */
hlogd("%s magic:0x%x, calc_checksum:%x %x, V:%s", __func__, packet->tlv.magic, kpacket_calc_checksum(packet), packet->tlv.checksum, packet->tlv.V);
#if 0
send(packet, sizeof(kpacket)+packet->tlv.L); /* 发给接收端数据 */
#endif
/*********************end***********************/
/******* 这段为接收端数据拷贝到目标中data, 如iobuffer.iodata *******/
#if 0
recv_cnt = recv(data, max_sz); /* 发给接收端数据 */
#else
int32_t recv_cnt = sizeof(kpacket) + packet->tlv.L;
memcpy(data, packet, recv_cnt);
#endif
kpacket_dec(packet);/* 释放kpacket */
return recv_cnt;
}
/************************************end************************************/