/************************************************* File name : kpacket.h Module : pal Author : amir.liang Version : 0.1 Created on : 2021-09-16 Description : included files required by os environment Modify History: 1. Date: Author: Modification: 20230424 amir use os_lock instead of mutex. *************************************************/ #ifndef __PACKET_H__ #define __PACKET_H__ #include #include "hdef.h" #include "hmutex.h" #include "hatomic.h" #ifndef OK #define OK (char)(0) #endif #ifndef NG #define NG (char)(1) #endif #ifdef __cplusplus extern "C" { #endif /*===========================================*/ /*1. do not use kpacket with stack memory */ /*2. payload address must be algin 4 */ /*===========================================*/ #define KPACKET_DEBUG 1U #if KPACKET_DEBUG #define KPACKET_LOG hlogd #else #define KPACKET_LOG(...) #endif #define OS_PACKET_MAGIC 0xcafe /* *kpacket_put_int: 按int推数据到value, 协议方pop_int对应有即可 *如: kpacket_put_int(kp, 123); val = kpacket_pop_int(kp, -1) val应该是123 */ typedef struct { uint16_t checksum; /* crc16 , just for TLV, include OS_PACKET_MAGIC */ uint16_t magic; /* OS_PACKET_MAGIC */ uint16_t T; /*TLV T: 0~65535 */ uint32_t L; /*TLV L: total size of value */ char V[0]; /*TLV V: the addr of value */ }TLV; TLV *TLV_init(char *buf, uint32_t cap); typedef struct{ hatomic_t ref; /*引用计数, 创建时为1, 当减到值为0时,将释放kpacket内存 */ uint32_t capacity; /*内存容量,主要是 value能存的数据大小 = sizeof(kpacket) + len(value) */ uint32_t offset; /*仅用于标识 value的offset*/ TLV tlv; }kpacket; /* * packet_pool_size recommend 4K * 初始化时必先 init */ void kpacket_init(uint32_t packet_pool_size); /* * * 填充完所有数时,计算并保存checksum到kpacket, 返回checksum */ uint16_t kpacket_checksum(kpacket *packet); /* * * 仅计算并返回checksum, 并不保存在kpacket */ uint16_t kpacket_calc_checksum(kpacket *packet); /* * */ kpacket *kpacket_slab_alloc(uint32_t size); /* * */ void kpacket_slab_free(kpacket *packet); #define kpacket_inc(_packet) ({\ hatomic_inc(&_packet->ref);/*没锁,有风险*/\ KPACKET_LOG("%s packet:%p, inc_ref:%d\n", __func__, _packet, _packet->ref);\ }) #define kpacket_dec(_packet) ({\ if (_packet->ref == 0){\ hloge("%s Error... hv_free_packet:%p, dec_ref should not be:%d\n", __func__, _packet, _packet->ref);\ }\ hatomic_dec(&_packet->ref);/*没锁,可能有风险*/\ if (_packet->ref == 0){\ KPACKET_LOG("%s free_packet:%p, dec_ref:%d ..............\n", __func__, _packet, _packet->ref);\ kpacket_slab_free(_packet);/*os_packet_delete(_packet);*/\ }else KPACKET_LOG("%s :%p, dec_ref:%d\n", __func__, _packet, _packet->ref);\ }) #define os_packet_valid(__packet) ({int32_t _ret;\ if (__packet && __packet-->tlv.magic == OS_PACKET_MAGIC){\ _ret = 1;\ }else{\ KPACKET_LOG("%s err packet:%p(!NULL), packet magic:%X(=%X)\n",__func__, __packet, __packet?__packet-->tlv.magic:0, OS_PACKET_MAGIC);\ _ret = 0;\ }\ _ret;}) #define kpacket(_event, _capacity)({\ kpacket *_packet = kpacket_slab_alloc(sizeof(kpacket) + _capacity);\ if (_packet){\ _packet->tlv.magic = OS_PACKET_MAGIC;\ _packet->tlv.T = _event;\ _packet->ref = 1;\ _packet->capacity = _capacity;\ _packet->tlv.L = 0;\ _packet->offset = 0;\ }else{\ hloge("%s kpacket_create outofmemory", __func__);\ }\ _packet;}) /*do not call os_packet_delete normally, use atomic_dec(packet) instead */ #if 0 #define os_packet_delete(_hv_free_packet)({\ if (os_packet_valid(_hv_free_packet)){\ if (_hv_free_packet->ref == 0) {\ hv_free(_hv_free_packet);\ hloge("%s os_packet_hv_free packet:%p",__func__, _hv_free_packet);\ }else{\ hloge("%s os_packet_hv_free error packet->ref:%d",__func__, _hv_free_packet->ref);\ }\ }else{\ hloge("%s os_packet_hv_free error",__func__);\ }\ }) #endif uint32_t kpacket_put_int(kpacket *p, int32_t val); uint32_t kpacket_put_string(kpacket *p, const char *str);//including '\0' uint32_t kpacket_put_data(kpacket *p, const char *data, uint32_t len); uint32_t kpacket_put_data1data2(kpacket *p, const char *data, uint32_t len, const char *data2, uint32_t len2); //data move to 'zero' and dataLen be 0 void kpacket_reset(kpacket *p); uint32_t kpacket_get_freesize(const kpacket *p); uint32_t kpacket_pop_int(kpacket *p_box, const int32_t defVal); const char *kpacket_pop_string(kpacket *p_box, const char *defVal); uint32_t kpacket_pop_data(kpacket *p_box, char **data); uint32_t kpacket_pop_reset(kpacket *p_box); void kpacket_dump(kpacket *p); void kpacket_test(void); #ifdef __cplusplus } #endif #endif /*_OS_TYPE_H__ */