fix: 分模块代码审查 — 修复 11 个 Critical/Important bugs
系统模块 (8项): - self_ptl: 修复环形缓冲区溢出逻辑 - self_ptl: 消除 search_frame 竞态条件 - self_ptl: 分离 get_rx_data_locked 避免锁间竞态 - self_ptl/com_router/modbus_m: 添加 EV_STOP 优雅退出 - com_router: 修复 last_state 重复定义 bug - modbus_m: 修复 EV_TIMERx 裸魔数 + task_event_recv flags 错误 协议模块 (2项): - icp67: TI_200/201/202 添加 ASDU 边界检查 公共基础库 (1项): - libfunc: func_cal_crc16/crc32 添加 NULL 指针检查
This commit is contained in:
parent
0409f427aa
commit
9560ea7653
|
|
@ -654,6 +654,7 @@ static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
stru_ti_200_201_202 *p_asdu;
|
stru_ti_200_201_202 *p_asdu;
|
||||||
uint16_t pos;
|
uint16_t pos;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
uint16_t asdu_len;
|
||||||
|
|
||||||
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
||||||
{
|
{
|
||||||
|
|
@ -664,9 +665,21 @@ static int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
p_head = (stru_head *)p_rx;
|
p_head = (stru_head *)p_rx;
|
||||||
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
||||||
|
|
||||||
|
if(rx_len < ICP67_FRAME_OVERHEAD)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_200: frame too short");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for(i = 0; p_icp67->method.mx_trans_cb && i < p_asdu->num; i++)
|
for(i = 0; p_icp67->method.mx_trans_cb && i < p_asdu->num; i++)
|
||||||
{
|
{
|
||||||
|
if(pos + sizeof(float) > asdu_len)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_200: data overflow, num=%d, pos=%d", p_asdu->num, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
p_icp67->method.mx_trans_cb(p_icp67, p_asdu->addr + i,
|
p_icp67->method.mx_trans_cb(p_icp67, p_asdu->addr + i,
|
||||||
*(float *)&p_asdu->data[pos]);
|
*(float *)&p_asdu->data[pos]);
|
||||||
pos += sizeof(float);
|
pos += sizeof(float);
|
||||||
|
|
@ -683,6 +696,7 @@ static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
stru_ti_200_201_202 *p_asdu;
|
stru_ti_200_201_202 *p_asdu;
|
||||||
uint16_t pos;
|
uint16_t pos;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
uint16_t asdu_len;
|
||||||
|
|
||||||
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
||||||
{
|
{
|
||||||
|
|
@ -693,9 +707,21 @@ static int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
p_head = (stru_head *)p_rx;
|
p_head = (stru_head *)p_rx;
|
||||||
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
||||||
|
|
||||||
|
if(rx_len < ICP67_FRAME_OVERHEAD)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_201: frame too short");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for(i = 0; p_icp67->method.st_trans_cb && i < p_asdu->num; i++)
|
for(i = 0; p_icp67->method.st_trans_cb && i < p_asdu->num; i++)
|
||||||
{
|
{
|
||||||
|
if(pos + 1 > asdu_len)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_201: data overflow, num=%d, pos=%d", p_asdu->num, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
p_icp67->method.st_trans_cb(p_icp67, p_asdu->addr + i,
|
p_icp67->method.st_trans_cb(p_icp67, p_asdu->addr + i,
|
||||||
p_asdu->data[pos++]);
|
p_asdu->data[pos++]);
|
||||||
}
|
}
|
||||||
|
|
@ -711,6 +737,7 @@ static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
stru_ti_200_201_202 *p_asdu;
|
stru_ti_200_201_202 *p_asdu;
|
||||||
uint16_t pos;
|
uint16_t pos;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
uint16_t asdu_len;
|
||||||
|
|
||||||
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
if(NULL == p_icp67 || NULL == p_rx || 0 == rx_len)
|
||||||
{
|
{
|
||||||
|
|
@ -721,9 +748,21 @@ static int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l
|
||||||
p_head = (stru_head *)p_rx;
|
p_head = (stru_head *)p_rx;
|
||||||
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
p_asdu = (stru_ti_200_201_202 *)p_head->data;
|
||||||
|
|
||||||
|
if(rx_len < ICP67_FRAME_OVERHEAD)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_202: frame too short");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
asdu_len = (uint16_t)(rx_len - ICP67_FRAME_OVERHEAD);
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for(i = 0; p_icp67->method.dd_trans_cb && i < p_asdu->num; i++)
|
for(i = 0; p_icp67->method.dd_trans_cb && i < p_asdu->num; i++)
|
||||||
{
|
{
|
||||||
|
if(pos + sizeof(float) > asdu_len)
|
||||||
|
{
|
||||||
|
LOG_E("icp67_decode_ti_202: data overflow, num=%d, pos=%d", p_asdu->num, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
p_icp67->method.dd_trans_cb(p_icp67, p_asdu->addr + i,
|
p_icp67->method.dd_trans_cb(p_icp67, p_asdu->addr + i,
|
||||||
*(float *)&p_asdu->data[pos]);
|
*(float *)&p_asdu->data[pos]);
|
||||||
pos += sizeof(float);
|
pos += sizeof(float);
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ uint16_t func_cal_sum_word(const uint8_t *d, uint32_t n)
|
||||||
|
|
||||||
uint16_t func_cal_crc16(const uint8_t *d, uint32_t n)
|
uint16_t func_cal_crc16(const uint8_t *d, uint32_t n)
|
||||||
{
|
{
|
||||||
if (!n)
|
if (!d || !n)
|
||||||
{
|
{
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ uint16_t func_cal_crc16(const uint8_t *d, uint32_t n)
|
||||||
|
|
||||||
uint32_t func_cal_crc32(const uint8_t *d, uint32_t n)
|
uint32_t func_cal_crc32(const uint8_t *d, uint32_t n)
|
||||||
{
|
{
|
||||||
if (!n)
|
if (!d || !n)
|
||||||
{
|
{
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,7 @@ void *app_com_router(void *arg)
|
||||||
* 巡检通道 socket_fd, 断开则记录。
|
* 巡检通道 socket_fd, 断开则记录。
|
||||||
* 未来可在此加自动重连逻辑。
|
* 未来可在此加自动重连逻辑。
|
||||||
*/
|
*/
|
||||||
|
static int last_state[MAX_CHANNELS];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < g_channel_count; i++)
|
for(i = 0; i < g_channel_count; i++)
|
||||||
|
|
@ -574,8 +575,6 @@ void *app_com_router(void *arg)
|
||||||
if(ch->socket_fd < 0)
|
if(ch->socket_fd < 0)
|
||||||
{
|
{
|
||||||
/* 已断开, 仅第一次打印 */
|
/* 已断开, 仅第一次打印 */
|
||||||
static int last_state[MAX_CHANNELS];
|
|
||||||
|
|
||||||
if(last_state[i] >= 0)
|
if(last_state[i] >= 0)
|
||||||
{
|
{
|
||||||
LOG_I("com_router: %s disconnected", ch->key);
|
LOG_I("com_router: %s disconnected", ch->key);
|
||||||
|
|
@ -584,7 +583,10 @@ void *app_com_router(void *arg)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static int last_state[MAX_CHANNELS];
|
if(last_state[i] <= 0)
|
||||||
|
{
|
||||||
|
LOG_I("com_router: %s connected", ch->key);
|
||||||
|
}
|
||||||
last_state[i] = 1;
|
last_state[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -615,6 +617,12 @@ void *app_com_router(void *arg)
|
||||||
{
|
{
|
||||||
p_app->run_cnt++;
|
p_app->run_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(EV_STOP & event)
|
||||||
|
{
|
||||||
|
LOG_I("app_com_router: received EV_STOP, exiting");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -1000,29 +1000,35 @@ void *app_modbus_m(void *arg)
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
task_event_recv(p_app->p_event,
|
task_event_recv(p_app->p_event,
|
||||||
0x01 | 0x02 | 0x04,
|
EV_TIMER1 | EV_TIMER2 | EV_TIMER3,
|
||||||
0x02 | 0x04,
|
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||||
TASK_EVENT_WAIT_FOREVER,
|
TASK_EVENT_WAIT_FOREVER,
|
||||||
&event);
|
&event);
|
||||||
|
|
||||||
if(event & 0x01)
|
if(event & EV_TIMER1)
|
||||||
{
|
{
|
||||||
// 处理写请求队列
|
// 处理写请求队列 (10ms)
|
||||||
process_write_queue();
|
process_write_queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event & 0x02)
|
if(event & EV_TIMER2)
|
||||||
{
|
{
|
||||||
// 轮询遥信(100ms)
|
// 轮询遥信 (100ms)
|
||||||
poll_groups(st_groups);
|
poll_groups(st_groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event & 0x04)
|
if(event & EV_TIMER3)
|
||||||
{
|
{
|
||||||
// 轮询遥测/参数(1000ms)
|
// 轮询遥测/参数 (1000ms)
|
||||||
poll_groups(mx_groups);
|
poll_groups(mx_groups);
|
||||||
p_app->run_cnt++;
|
p_app->run_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(EV_STOP & event)
|
||||||
|
{
|
||||||
|
LOG_I("app_modbus_m: received EV_STOP, exiting");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -132,13 +132,21 @@ static void put_rx_data(stru_self_rx *p_self_rx, uint8_t *p_rx, uint16_t len)
|
||||||
{
|
{
|
||||||
p_self_rx->buf[p_self_rx->wptr] = p_rx[i];
|
p_self_rx->buf[p_self_rx->wptr] = p_rx[i];
|
||||||
p_self_rx->wptr = (p_self_rx->wptr + 1) % p_self_rx->size;
|
p_self_rx->wptr = (p_self_rx->wptr + 1) % p_self_rx->size;
|
||||||
p_self_rx->cnt++;
|
|
||||||
|
|
||||||
if(p_self_rx->cnt > p_self_rx->size)
|
if(p_self_rx->cnt >= p_self_rx->size)
|
||||||
{
|
{
|
||||||
p_self_rx->cnt--;
|
/* 环形缓冲区已满: 丢弃最旧字节, 只警告一次 */
|
||||||
|
static int overflow_warned = 0;
|
||||||
|
if(!overflow_warned)
|
||||||
|
{
|
||||||
|
LOG_E("put_rx_data: ring buffer overflow, dropping old data");
|
||||||
|
overflow_warned = 1;
|
||||||
|
}
|
||||||
p_self_rx->rptr = (p_self_rx->rptr + 1) % p_self_rx->size;
|
p_self_rx->rptr = (p_self_rx->rptr + 1) % p_self_rx->size;
|
||||||
LOG_E("put_rx_data overflow, rptr=%d, wptr=%d", p_self_rx->rptr, p_self_rx->wptr);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p_self_rx->cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,6 +178,27 @@ static void get_rx_data(stru_self_rx *p_self_rx, uint8_t *p_data, uint16_t *p_da
|
||||||
pthread_mutex_unlock(&p_self_rx->mutex);
|
pthread_mutex_unlock(&p_self_rx->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get_rx_data 的无锁版本 (调用者已持锁) */
|
||||||
|
static void get_rx_data_locked(stru_self_rx *p_self_rx, uint8_t *p_data, uint16_t *p_data_len)
|
||||||
|
{
|
||||||
|
uint16_t pos;
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
if(NULL == p_self_rx || NULL == p_data || NULL == p_data_len)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = p_self_rx->rptr;
|
||||||
|
for(i = 0; i < p_self_rx->cnt; i++)
|
||||||
|
{
|
||||||
|
p_data[i] = p_self_rx->buf[pos];
|
||||||
|
pos = (pos + 1) % p_self_rx->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*p_data_len) = p_self_rx->cnt;
|
||||||
|
}
|
||||||
|
|
||||||
static void clear_rx_data(stru_self_rx *p_self_rx)
|
static void clear_rx_data(stru_self_rx *p_self_rx)
|
||||||
{
|
{
|
||||||
if(NULL == p_self_rx)
|
if(NULL == p_self_rx)
|
||||||
|
|
@ -341,6 +370,8 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp
|
||||||
uint16_t pos = 0;
|
uint16_t pos = 0;
|
||||||
uint16_t valid_len = 0;
|
uint16_t valid_len = 0;
|
||||||
stru_self_rx *ring = &g_self_ptl.icp67_rx;
|
stru_self_rx *ring = &g_self_ptl.icp67_rx;
|
||||||
|
uint8_t iec_buf[SELF_PTL_BUF_SIZE];
|
||||||
|
uint16_t iec_buf_len = 0;
|
||||||
|
|
||||||
if(NULL == p_rx || 0 == len || NULL == p_icp67)
|
if(NULL == p_rx || 0 == len || NULL == p_icp67)
|
||||||
{
|
{
|
||||||
|
|
@ -350,14 +381,13 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp
|
||||||
/* 写入环形缓冲区 */
|
/* 写入环形缓冲区 */
|
||||||
put_rx_data(ring, p_rx, len);
|
put_rx_data(ring, p_rx, len);
|
||||||
|
|
||||||
/* 锁住读取 */
|
/* 一次持锁: ICP67 帧处理 + IEC 帧快照, 避免竞态 */
|
||||||
pthread_mutex_lock(&ring->mutex);
|
pthread_mutex_lock(&ring->mutex);
|
||||||
|
|
||||||
/* ICP67 帧搜索: 直接从环形缓冲读取, 零拷贝 */
|
/* ICP67 帧搜索: 直接从环形缓冲读取, 零拷贝 */
|
||||||
while(0 == icp67_search_frame_in_ring(ring->buf, ring->size,
|
while(0 == icp67_search_frame_in_ring(ring->buf, ring->size,
|
||||||
ring->rptr, ring->cnt, &pos, &valid_len))
|
ring->rptr, ring->cnt, &pos, &valid_len))
|
||||||
{
|
{
|
||||||
/* 解码: 帧跨环边界时需临时拷贝 */
|
|
||||||
uint8_t frame_buf[ICP67_TX_BUF_SIZE];
|
uint8_t frame_buf[ICP67_TX_BUF_SIZE];
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
|
||||||
|
|
@ -368,23 +398,22 @@ static void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp
|
||||||
|
|
||||||
p_icp67->decode_cb(p_icp67, frame_buf, valid_len);
|
p_icp67->decode_cb(p_icp67, frame_buf, valid_len);
|
||||||
|
|
||||||
/* 滑窗: advance ring pointer */
|
/* 滑窗 */
|
||||||
pos += valid_len;
|
pos += valid_len;
|
||||||
ring->cnt -= pos;
|
ring->cnt -= pos;
|
||||||
ring->rptr = (ring->rptr + pos) % ring->size;
|
ring->rptr = (ring->rptr + pos) % ring->size;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IEC-104 帧快照 (持锁下拷贝完整剩余数据) */
|
||||||
|
get_rx_data_locked(ring, iec_buf, &iec_buf_len);
|
||||||
|
|
||||||
pthread_mutex_unlock(&ring->mutex);
|
pthread_mutex_unlock(&ring->mutex);
|
||||||
|
|
||||||
/* IEC-104 帧: 需要读取字节序列, 做一次全量拷贝 */
|
/* IEC-104 帧搜索 (锁外执行, 操作快照数据) */
|
||||||
|
if(iec_buf_len > 0)
|
||||||
{
|
{
|
||||||
uint8_t buf[SELF_PTL_BUF_SIZE];
|
if(0 == self_ptl_search_iec_frame(iec_buf, iec_buf_len, &pos, &valid_len))
|
||||||
uint16_t buf_len = 0;
|
|
||||||
|
|
||||||
get_rx_data(ring, buf, &buf_len);
|
|
||||||
|
|
||||||
if(0 == self_ptl_search_iec_frame(buf, buf_len, &pos, &valid_len))
|
|
||||||
{
|
{
|
||||||
LOG_I("self_ptl: found IEC-104 frame at pos=%d, len=%d", pos, valid_len);
|
LOG_I("self_ptl: found IEC-104 frame at pos=%d, len=%d", pos, valid_len);
|
||||||
/* TODO: 将 IEC-104 帧转发到 libiec 解码模块 (待实现) */
|
/* TODO: 将 IEC-104 帧转发到 libiec 解码模块 (待实现) */
|
||||||
|
|
@ -627,6 +656,13 @@ void *app_self_ptl(void *arg)
|
||||||
{
|
{
|
||||||
p_app->run_cnt++;
|
p_app->run_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EV_STOP: 优雅退出 */
|
||||||
|
if(EV_STOP & event)
|
||||||
|
{
|
||||||
|
LOG_I("app_self_ptl: received EV_STOP, exiting");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue