Files
kunlun/common/utils/iot_frame_parse.c
2024-09-28 14:24:04 +08:00

301 lines
9.4 KiB
C

#include "iot_frame_parse.h"
#include "iot_io.h"
#include "iot_utils.h"
void* find_str(const uint8_t *pSour, const uint8_t *pDest,
int SourLen, int DestLen)
{
int i = 0, j = 0;
while (i < SourLen && j < DestLen) {
if (*(pSour + i) == *(pDest + j)) {
i++;
j++;
} else {
i = i - j + 1;
j = 0;
}
}
if (j == DestLen) {
return (void*)(pSour + (i - DestLen));
} else {
return NULL;
}
}
void* find_str_ringbuf(ringbuf_t *r, const uint8_t *pDest,
uint32_t DestLen)
{
uint32_t SourLen = iot_ringbuf_elements(r);
uint32_t i = 0, j = 0;
uint8_t c;
uint32_t get_ptr = r->get_ptr;
if (!r || !pDest){
IOT_ASSERT(0);
return NULL;
}
while (i < SourLen && j < DestLen) {
c = r->data[get_ptr];
get_ptr = iot_get_ring_pos((get_ptr + 1), r);
if (c == *(pDest + j)) {
i++;
j++;
} else {
i = i - j + 1;
get_ptr = get_ptr - j;
j = 0;
}
}
if (j == DestLen) {
return (void*)(r->data+ iot_get_ring_pos((r->get_ptr + i - DestLen), r));
} else {
return NULL;
}
}
//uint32_t has_full_frame(uint8_t* buffer, uint32_t* bufferlen, iot_frame_fmt fmt)
//{
// uint8_t *pdest = NULL;
// unsigned long nFrameEnd;
//
////framebegin:
// pdest = (uint8_t*)find_str(buffer, (uint8_t*)fmt.preamble_code, *bufferlen, fmt.preamle_codelen);
// if (pdest)
// {
// unsigned long nFrameStart = (unsigned long)(pdest - buffer);// move buffer to the beginning.
// os_mem_cpy(buffer, buffer + nFrameStart, *bufferlen-nFrameStart);
// os_mem_set(buffer + *bufferlen-nFrameStart, 0, nFrameStart);
// *bufferlen = *bufferlen - nFrameStart;
// }
// else
// return 0;
////frameend:
// pdest = (uint8_t*)find_str(buffer, (uint8_t*)fmt.backcode, *bufferlen, fmt.backcode_Len);
// if (pdest)
// {
// nFrameEnd = (unsigned long)(pdest - buffer + fmt.backcode_Len);
// //printf("found @@, (nCurrectPos=%d, dwRealRead=%d)\n", nCurrectPos, dwRealRead);
//
// return nFrameEnd;
// }
// else
// {
// return 0;
// }
//}
uint32_t has_full_frame(uint8_t* buffer, uint32_t* bufferlen, iot_frame_fmt fmt,
bool_t* has_preamble_code)
{
uint8_t *pdest = NULL;
//datalen size cannot be large than 4
IOT_ASSERT(fmt.datalen_size <= 4);
if (has_preamble_code) {
*has_preamble_code = false;
}
framebegin:
if (fmt.preamble_codelen > 0) {
pdest = (uint8_t*)find_str(buffer, (uint8_t*)fmt.preamble_code,
*bufferlen, fmt.preamble_codelen);
if (pdest) {
// move buffer to the beginning.
unsigned long nFrameStart = (unsigned long)(pdest - buffer);
if (nFrameStart > 0) {
os_mem_cpy(buffer, buffer + nFrameStart, *bufferlen - nFrameStart);
os_mem_set(buffer + *bufferlen - nFrameStart, 0, nFrameStart);
*bufferlen = *bufferlen - nFrameStart;
}
if (has_preamble_code) {
*has_preamble_code = true;
}
} else {
if (*bufferlen) {
iot_printf("has_full_frame func didn't find the preamble\n");
}
return 0;
}
}
uint32_t len = 0;
uint8_t backcode[MAX_FRAME_CODE_LEN] = { 0 };
if ((uint32_t)(fmt.preamble_codelen + fmt.datalen_offset ) > *bufferlen) {
// need receive more data
iot_printf("has_full_frame func need get more buffer for buffer len\n");
return 0;
}
os_mem_cpy(&len, buffer+ fmt.preamble_codelen + fmt.datalen_offset,
fmt.datalen_size);
if (fmt.datalen_endian_mode == DATALEN_ENDIAN_BIG) {
iot_data_reverse((uint8_t *)&len, fmt.datalen_size);
}
if (fmt.datalen_mask) {
len &= fmt.datalen_mask;
}
//after get the len, try to get the back code...
len = fmt.preamble_codelen + fmt.datalen_offset + fmt.datalen_size +
len + fmt.backcode_offset; //get back code start position
len -= fmt.datalen_fix;
if ((len + fmt.backcode_len) > *bufferlen) {
iot_printf("has_full_frame func need get more buffer for back code\n");
return 0;
}
if (fmt.backcode_len == 0) {
iot_printf("has_full_frame func got a full buffer, no backcode\n");
return len;
}
os_mem_cpy(backcode, buffer + len , fmt.backcode_len);
if (os_mem_cmp(backcode, fmt.backcode, fmt.backcode_len) == 0) {
iot_printf("has_full_frame func got a full buffer\n");
return len + fmt.backcode_len;
} else {
// drop the data till next preamle code
iot_printf("has_full_frame func the backcode is not match\n");
pdest = (uint8_t*)find_str(buffer+ fmt.preamble_codelen,
(uint8_t*)fmt.preamble_code, *bufferlen, fmt.preamble_codelen);
if (pdest) {
unsigned long nFrameStart = (unsigned long)(pdest - buffer);// move buffer to the beginning.
if (nFrameStart > 0) {
os_mem_cpy(buffer, buffer + nFrameStart, *bufferlen - nFrameStart);
os_mem_set(buffer + *bufferlen - nFrameStart, 0, nFrameStart);
*bufferlen = *bufferlen - nFrameStart;
}
goto framebegin;
} else {
os_mem_set(buffer, 0, *bufferlen);
*bufferlen = 0;
}
return 0;
}
}
uint32_t has_full_frame_ringbuf(ringbuf_t *r, iot_frame_fmt fmt,
uint32_t *ec_len)
{
uint32_t preamble_offest = 0;
uint8_t *preamble_pos = NULL;
uint32_t invalid_data_len, valid_data_len;
uint32_t len_d = 0, backcode_field_offset;
uint8_t backcode[MAX_FRAME_CODE_LEN] = { 0 };
/* according to the frame format, the offset of the length field
* in the data frame is calculated
*/
uint32_t len_field_offset = fmt.preamble_codelen + fmt.datalen_offset;
ringbuf_t ringbuf_st;
bool_t push = false;
/* datalen size cannot be large than 4 */
IOT_ASSERT(fmt.datalen_size <= 4);
if (!r || !fmt.preamble_codelen
|| !iot_ringbuf_elements(r))
goto out;
again:
preamble_pos = (uint8_t*)find_str_ringbuf(r, (uint8_t*)fmt.preamble_code,
fmt.preamble_codelen);
if (push) {
os_mem_cpy(r, &ringbuf_st, sizeof(ringbuf_t));
}
if (!preamble_pos) {
/* if no preamble is found */
goto out;
}
/* calculated the data length before the preamble code */
invalid_data_len = (uint32_t)iot_get_ring_pos(\
(preamble_pos - (r->data + r->get_ptr)), r);
/* calculated the data length after the preamble code, included Preamble */
valid_data_len = (uint32_t)iot_get_ring_pos(\
((r->put_ptr + r->data) - preamble_pos), r);
if ((uint32_t)(fmt.preamble_codelen + fmt.datalen_offset) > valid_data_len)
{
goto out;
}
/* calculated the offset of the preamble in the ringbuffer */
preamble_offest = (uint32_t)(preamble_pos - r->data);
/* gets the length of the data field */
iot_ringbuf_dummy_gets(r, (uint8_t *)&len_d, fmt.datalen_size,
iot_ringbuf_offset_add(r, preamble_offest, len_field_offset));
if (fmt.datalen_endian_mode == DATALEN_ENDIAN_BIG) {
iot_data_reverse((uint8_t *)&len_d, fmt.datalen_size);
}
if (fmt.datalen_mask) {
len_d &= fmt.datalen_mask;
}
/* calculate the offset of back code in the data frame */
backcode_field_offset = fmt.preamble_codelen + fmt.datalen_offset +
fmt.datalen_size + len_d + fmt.backcode_offset - fmt.datalen_fix;
if ((backcode_field_offset + fmt.backcode_len) > valid_data_len) {
goto try;
}
if (fmt.backcode_len == 0) {
iot_printf("has_full_frame func got a full buffer, no backcode\n");
(*ec_len) = invalid_data_len;
return backcode_field_offset;
}
iot_ringbuf_dummy_gets(r, backcode, fmt.backcode_len,
iot_ringbuf_offset_add(r, preamble_offest, backcode_field_offset));
if (os_mem_cmp(backcode, fmt.backcode, fmt.backcode_len) == 0) {
iot_printf("has_full_frame func got a full buffer\n");
(*ec_len) = invalid_data_len;
return (backcode_field_offset + fmt.backcode_len);
}
/* If the preamble is found, it is unsuccessful to try the
* frame format check, and find the next preamble.
*/
try:
os_mem_cpy(&ringbuf_st, r, sizeof(ringbuf_t));
iot_ringbuf_drop(r,
iot_get_ring_pos((iot_ringbuf_offset_add(r, preamble_offest, \
fmt.preamble_codelen) - r->get_ptr), r));
push = true;
goto again;
out:
return 0;
}
bool_t build_frame_buf(iot_pkt_t* buffer, iot_frame_fmt fmt)
{
if (!buffer) {
return false;
}
if (fmt.preamble_codelen > 0) {
uint8_t * newdata = iot_pkt_push(buffer, fmt.preamble_codelen);
if (newdata) {
os_mem_cpy(newdata, fmt.preamble_code, fmt.preamble_codelen);
} else {
IOT_ASSERT(0);
return false;
}
}
if (fmt.backcode_len > 0) {
uint8_t * newdata = iot_pkt_put(buffer, fmt.backcode_len);
if (newdata) {
os_mem_cpy(newdata + (iot_pkt_data_len(buffer) - fmt.backcode_len),
fmt.backcode, fmt.backcode_len);
} else {
IOT_ASSERT(0);
return false;
}
}
return true;
}