You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

863 lines
28 KiB
C

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*****************************************************************************
* file lib/process/pd_dbg.c
* author YuLiang
* version 1.0.0
* date 01-June-2023
* brief This file provides all the debug server related operation functions.
******************************************************************************
* Attention
*
* <h2><center>&copy; COPYRIGHT(c) 2021 LandPower</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of LandPower nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef CFG_DEV_TYPE_LAND_PD
/* 标准C库头文件. */
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <netinet/tcp.h>
/* 用户代码头文件. */
#include "cJSON.h"
#include "main.h"
#include "mtimer.h"
#include "pd_dbg.h"
#include "pd_csg.h"
#include "pd_dau.h"
#include "pd_upgrade.h"
/* Private define ------------------------------------------------------------*/
#define DEBUG_HEAD 0x55AA
#define DEBUG_TAIL 0x5AA5
#define DEBUG_CMD_LEN 10 * 1024 * 1024
#define DEBUG_CMU_FILE "PDMonitor"
#define DEBUG_CMU_FILE_BAK "./bak/PDMonitor.bak"
#define DEBUG_CMU_FILE_UPGRADE "PDMonitor.upgrade"
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
debug_ctrl_t debug_ctrl;
dbg_device_info_t dbg_base_config;
dbg_global_config_t dbg_global_config;
dbg_config_port_t dbg_port_config;
static char buf_cmd[DEBUG_CMD_LEN];
/* Private function prototypes -----------------------------------------------*/
/* Internal functions --------------------------------------------------------*/
void _debug_pkt_head_int(dbg_pkt_head_t *head, uint16_t cmd, uint32_t len)
{
head->head = DEBUG_HEAD;
head->cmd = cmd;
head->len = len;
}
/* 回复报文处理. */
int32_t _debug_pkt_common_send(char *buf, uint16_t cmd, uint32_t data_len)
{
uint16_t total_len;
dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf;
head->len = data_len;
uint16_t *tail = (uint16_t*)(buf + sizeof(dbg_pkt_head_t) + data_len);
_debug_pkt_head_int(head, cmd, data_len);
*tail = DEBUG_TAIL;
total_len = sizeof(dbg_pkt_head_t) + data_len + 2;
DBG(DBG_M_DEBUG, "数据包 (总长度: %u bytes):\r\n", total_len);
DBG(DBG_M_DEBUG, " 头部: head=0x%04X, cmd=0x%04X, len=%u\r\n", head->head, head->cmd, head->len);
DBG(DBG_M_DEBUG, " 尾部: 0x%04X\r\n", *tail);
if (write(debug_ctrl.fd_client, buf, total_len) <= 0)
{
DBG(DBG_M_DEBUG, "Write cmd %x ERROR\r\n", head->cmd);
return E_SYS_CALL;
}
return E_NONE;
}
/* 获取配置报文处理. */
int32_t _debug_pkt_factory_cfg_get(char *buf, int len)
{
dbg_device_info_t *info = (dbg_device_info_t *)(buf+sizeof(dbg_pkt_head_t));
memset(info, 0, sizeof(dbg_device_info_t));
info->type_m = device_info.type_m;
info->type_s = device_info.type_s;
info->dev_id = device_info.dev_id;
snprintf((char*)info->hostname, FILE_NAME_LEN, "%s", device_info.hostname);
info->factory_date = device_info.factory_date;
info->deployment_date = device_info.deployment_date;
info->ip = device_info.ip;
memcpy(info->mac, device_info.mac, MAC_ADDR_LEN);
info->mask = device_info.mask;
info->gw = device_info.gw;
strncpy((char*)info->app_version, host.version, 32);
strncpy((char*)info->app_compile_time, host.compile, 32);
//strncpy((char*)info->hardware_version, host.hardversion, 32);
// 赋值 FPGA_version
info->csg_port = csg.server_port;
info->csg_ipv4 = csg.server_ip;
info->running_time = start_time;
int32_t ret = _debug_pkt_common_send(buf, DEBUG_CONFIG_FACTORY_GET, sizeof(dbg_device_info_t));
/* 发送数据. */
return ret;
}
int32_t _debug_pkt_factory_cfg_set(char *buf, int len)
{
REBOOT_MSG boottype = REBOOT_NONE;
dbg_device_info_t *info = (dbg_device_info_t *)(buf+sizeof(dbg_pkt_head_t));
if(device_info.type_m != info->type_m||
device_info.type_s != info->type_s||
device_info.dev_id != info->dev_id)
{
device_info.type_m = info->type_m;
device_info.type_s = info->type_s;
device_info.dev_id = info->dev_id;
boottype = REBOOT_LOCAL_HOST_NAME_CHANGE;
}
snprintf(device_info.hostname, FILE_NAME_LEN, "%s", (const char*)info->hostname);
device_info.factory_date = info->factory_date;
device_info.deployment_date = info->deployment_date;
if (device_info.ip != info->ip)
{
DBG(DBG_M_DEBUG, "IP 地址变更: %u.%u.%u.%u -> %u.%u.%u.%u\r\n",
device_info.ip & 0xFF, (device_info.ip >> 8) & 0xFF, (device_info.ip >> 16) & 0xFF, (device_info.ip >> 24) & 0xFF,
info->ip & 0xFF, (info->ip >> 8) & 0xFF, (info->ip >> 16) & 0xFF, (info->ip >> 24) & 0xFF);
device_info.ip = info->ip;
mac_generate_from_ip(device_info.ip, info->mac);
memcpy(device_info.mac, info->mac, MAC_ADDR_LEN);
boottype = REBOOT_REMOTE_IP_CHANGE;
vtysh_eth0_save();
}
device_info.gw = info->gw;
device_info.mask = info->mask;
vtysh_device_save();
if (csg.server_ip != info->csg_ipv4)
{
csg.server_ip = info->csg_ipv4;
boottype = REBOOT_REMOTE_SERVER_IP_CHANGE;
}
if (csg.server_port != info->csg_port)
{
csg.server_port = info->csg_port;
boottype = REBOOT_REMOTE_SERVER_IP_CHANGE;
}
vtysh_config_save();
// 打印接收到的设备信息
DBG(DBG_M_DEBUG, "================================================\r\n");
DBG(DBG_M_DEBUG, "接收到的设备信息:\r\n");
DBG(DBG_M_DEBUG, " 主设备号 (type_m): %u\r\n", info->type_m);
DBG(DBG_M_DEBUG, " 次设备号 (type_s): %u\r\n", info->type_s);
DBG(DBG_M_DEBUG, " 设备ID (dev_id): %u\r\n", info->dev_id);
DBG(DBG_M_DEBUG, " 主机名 (hostname): %s\r\n", info->hostname);
DBG(DBG_M_DEBUG, " 出厂时间 (factory_date): %u\r\n", info->factory_date);
DBG(DBG_M_DEBUG, " 部署时间 (deployment_date): %u\r\n", info->deployment_date);
DBG(DBG_M_DEBUG, " IP 地址 (ip): %u.%u.%u.%u\r\n",
(info->ip) & 0xFF, (info->ip >> 8) & 0xFF, (info->ip >> 16) & 0xFF, (info->ip >> 24) & 0xFF);
DBG(DBG_M_DEBUG, " 子网掩码 (mask): %u.%u.%u.%u\r\n",
(info->mask) & 0xFF, (info->mask >> 8) & 0xFF, (info->mask >> 16) & 0xFF, (info->mask >> 24) & 0xFF);
DBG(DBG_M_DEBUG, " 网关 (gw): %u.%u.%u.%u\r\n",
(info->gw) & 0xFF, (info->gw >> 8) & 0xFF, (info->gw >> 16) & 0xFF, (info->gw >> 24) & 0xFF);
DBG(DBG_M_DEBUG, " MAC 地址 (mac): %02X:%02X:%02X:%02X:%02X:%02X\r\n",
info->mac[0], info->mac[1], info->mac[2], info->mac[3], info->mac[4], info->mac[5]);
DBG(DBG_M_DEBUG, " CSG 端口 (csg_port): %u\r\n", info->csg_port);
DBG(DBG_M_DEBUG, " CSG 服务器 IP (csg_ipv4): %u.%u.%u.%u\r\n",
(info->csg_ipv4 >> 24) & 0xFF, (info->csg_ipv4 >> 16) & 0xFF, (info->csg_ipv4 >> 8) & 0xFF, info->csg_ipv4 & 0xFF);
if (boottype)
{
_debug_pkt_common_send(buf, DEBUG_CONFIG_FACTORY_SET, 0);
sleep(1);
reboot_system(LOG_DEBUG, boottype);
}
return E_NONE;
}
/* 设置报文处理. */
int32_t _debug_pkt_global_cfg_set(char *pkt, int len)
{
dbg_global_config_t *config = (dbg_global_config_t *)(pkt + sizeof(csg_pkt_head_t));
pd_config.config.sample_frequency = config->sample_frequency;
pd_config.config.trigger_sample_nums = config->trigger_sample_numbers;
pd_config.config.trig_location = (config->pre_trigger_percent << 4) / 100.00;
pd_config.config.trig_threshold = config->trigLevel;
pd_config.config.trend_up_period = config->trend_up_period;
pd_config.config.heartbeat_period = config->heartbeat_period;
pd_config.config.ch_en_mask = config->ch_en_mask;
if (config->sync_mode == 0)
{
BITMAP_RESET(pd_config.config.pt_B_sync_mode, PD_BIT_PT);
}
else
{
BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_PT);
}
pd_config.config.pt_internal_period = 1000000000UL / config->pt_internal_period;
vtysh_config_save();
return _debug_pkt_common_send(pkt, DEBUG_CONFIG_GLOBAL_SET, 0);
}
/* 查询用户参数查询报文处理. */
int32_t _debug_pkt_global_cfg_get(char *pkt, int len)
{
dbg_global_config_t *pconfig = (dbg_global_config_t *)(pkt + sizeof(dbg_pkt_head_t));
pconfig->sample_frequency = pd_config.config.sample_frequency;
pconfig->trigger_sample_numbers = pd_config.config.trigger_sample_nums;
pconfig->pre_trigger_percent = (uint32_t)(pd_config.config.trig_location * 100 / 16.00 + 0.5);
pconfig->trigLevel = pd_config.config.trig_threshold;
pconfig->trend_up_period = pd_config.config.trend_up_period;
pconfig->heartbeat_period = pd_config.config.heartbeat_period;
pconfig->ch_en_mask = pd_config.config.ch_en_mask;
if (IS_BITMAP_SET(pd_config.config.pt_B_sync_mode, PD_BIT_PT))
{
pconfig->sync_mode = 1;
}
else
{
pconfig->sync_mode = 0;
}
pconfig->pt_internal_period = 1000000000UL / pd_config.config.pt_internal_period;
_debug_pkt_common_send(pkt, DEBUG_CONFIG_GLOBAL_GET, sizeof(dbg_global_config_t));
return E_NONE;
}
/* 设置报文处理. */
int32_t _debug_pkt_port_cfg_set(char *pkt, int len)
{
uint8_t unit = 0;
uint8_t port = 0;
dbg_config_port_t *pnet = (dbg_config_port_t *)(pkt + sizeof(dbg_pkt_head_t));
if (dau_vport_to_port(pnet->vport, &unit, &port) != E_NONE)
{
DBG(DBG_M_DEBUG, "Pkt port %d error!\r\n", pnet->vport);
return E_ERROR;
}
pd_config.config_port[unit][port].vport = pnet->vport;
pd_config.config_port[unit][port].type = pnet->channel_type;
pd_config.config_port[unit][port].filter_frequency = pnet->filter_frequency;
pd_config.config_port[unit][port].rise_time = pnet->rise_time;
pd_config.config_port[unit][port].peak_time = pnet->peak_time;
pd_config.config_port[unit][port].fall_time = pnet->fall_time;
pd_config.config_port[unit][port].pulse_width = pnet->pulse_width;
pd_config.config_port[unit][port].peak_count = pnet->peak_count;
pd_config.config_port[unit][port].signal_envelope = pnet->signal_envelope;
pd_config.config_port[unit][port].signal_mean = pnet->signal_mean;
pd_config.config_port[unit][port].signal_variance = pnet->signal_variance;
pd_config.config_port[unit][port].primary_frequency = pnet->primary_frequency;
pd_config.config_port[unit][port].primary_freq_peak = pnet->primary_freq_peak;
pd_config.config_port[unit][port].spectral_peak_count = pnet->spectral_peak_count;
pd_config.config_port[unit][port].spectrum_mean = pnet->spectrum_mean;
pd_config.config_port[unit][port].spectrum_variance = pnet->spectrum_variance;
vtysh_config_save();
_debug_pkt_common_send(pkt, DEBUG_CONFIG_PORT_SET, 0);
return E_NONE;
}
/* 查询用户参数查询报文处理. */
int32_t _debug_pkt_port_cfg_get(char *pkt, int len)
{
dbg_config_port_t *pnet = (dbg_config_port_t *)(pkt + sizeof(dbg_pkt_head_t));
uint8_t unit = 0;
uint8_t port = 0;
if (dau_vport_to_port(pnet->vport, &unit, &port) != E_NONE)
{
DBG(DBG_M_DEBUG, "Pkt port %d error!\r\n", pnet->vport);
return E_ERROR;
}
pnet->vport = pd_config.config_port[unit][port].vport;
pnet->channel_type = pd_config.config_port[unit][port].type;
pnet->vport = pd_config.config_port[unit][port].vport;
pnet->channel_type = pd_config.config_port[unit][port].type;
pnet->filter_frequency = pd_config.config_port[unit][port].filter_frequency;
pnet->rise_time = pd_config.config_port[unit][port].rise_time;
pnet->peak_time = pd_config.config_port[unit][port].peak_time;
pnet->fall_time = pd_config.config_port[unit][port].fall_time;
pnet->pulse_width = pd_config.config_port[unit][port].pulse_width;
pnet->peak_count = pd_config.config_port[unit][port].peak_count;
pnet->signal_envelope = pd_config.config_port[unit][port].signal_envelope;
pnet->signal_mean = pd_config.config_port[unit][port].signal_mean;
pnet->signal_variance = pd_config.config_port[unit][port].signal_variance;
pnet->primary_frequency = pd_config.config_port[unit][port].primary_frequency;
pnet->primary_freq_peak = pd_config.config_port[unit][port].primary_freq_peak;
pnet->spectral_peak_count = pd_config.config_port[unit][port].spectral_peak_count;
pnet->spectrum_mean = pd_config.config_port[unit][port].spectrum_mean;
pnet->spectrum_variance = pd_config.config_port[unit][port].spectrum_variance;
_debug_pkt_common_send(pkt, DEBUG_CONFIG_PORT_GET, sizeof(dbg_config_port_t));
return E_NONE;
}
/* 重启报文处理. */
int32_t _debug_pkt_reboot(char *buf, int len)
{
/* 发送数据. */
_debug_pkt_common_send(buf, DEBUG_REBOOT, 0);
/* 重启. */
reboot_system(LOG_DEBUG, REBOOT_LOCAL_RESET);
return E_NONE;
}
/* 时间设置报文处理. */
int32_t _debug_pkt_time_set(char *buf, int len)
{
uint32_t *timestamp = (uint32_t*)(buf + sizeof(dbg_pkt_head_t));
/* 配置时间. */
time_set(*timestamp);
/* 发送数据. */
_debug_pkt_common_send(buf, DEBUG_TIME_SET, 0);
return E_NONE;
}
/* 获取运行状态报文处理. */
int32_t _debug_pkt_status_get(char *buf, int len)
{
debug_pkt_status_t *status = (debug_pkt_status_t*)(buf + sizeof(dbg_pkt_head_t));
status->utc = time(NULL);
status->run_time = start_time;
status->is_server_link = csg.is_connect;
_debug_pkt_common_send(buf, DEBUG_DEVICE_STATUS, sizeof(debug_pkt_status_t));
return E_NONE;
}
/* 获取运行状态报文处理. */
int32_t _debug_pkt_set_wave_address(char *buf, int len)
{
dbg_wave_addr_t *wave = (dbg_wave_addr_t*)(buf + sizeof(dbg_pkt_head_t));
bzero(&csg.wave_svr, sizeof(csg.wave_svr));
csg.wave_svr.sin_family = AF_INET;
csg.wave_svr.sin_addr.s_addr = inet_addr(wave->ipv4);
csg.wave_svr.sin_port = htons(wave->port);
_debug_pkt_common_send(buf, DEBUG_SET_WAVE_ADDRESS, 0);
return E_NONE;
}
int32_t _debug_pkt_upgrade(char *pkt, int len)
{
static int fd = -1;
static uint32_t fix_len = 0;
dbg_upgrade_data_t *head_msg = (dbg_upgrade_data_t*)(pkt + sizeof(dbg_pkt_head_t));
char *pdata = pkt + sizeof(dbg_pkt_head_t) + sizeof(dbg_upgrade_data_t);
dbg_upgrade_ack_t *pack = (dbg_upgrade_ack_t*)(pkt + sizeof(dbg_pkt_head_t));
int32_t size = 0;
int32_t len_wr = 0;
uint32_t offset = 0;
csg.is_connect = FALSE; //关闭主动上传
/* 首保处理, 打开文件描述符, 初始化变量 */
if (head_msg->index == 0)
{
if (fd > 0)
{
close(fd);
fd = -1;
}
fd = open(PD_UPG_SOFTWARE, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd < 0)
{
DBG(DBG_M_DEBUG, "Open file " PD_UPG_SOFTWARE " error!\r\n");
return E_SYS_CALL;
}
fix_len = head_msg->len;
DBG(DBG_M_DEBUG, "Receive upgrade file start.\r\n");
}
DBG(DBG_M_DEBUG,"type=%d,sum=%d,index=%d,len=%d,fix_len=%d\r\n", head_msg->type, head_msg->sum, head_msg->index, head_msg->len, fix_len);
/* 收包流程 */
size = head_msg->len;
offset = head_msg->index * fix_len;
if (lseek(fd, offset, SEEK_SET) < 0)
{
int error = errno;
DBG(DBG_M_PD_CSG_ERR, "lseek file " PD_UPG_SOFTWARE " error: %s, fd=%d, offset=%ld\r\n",
strerror(error), fd, offset);
// 检查具体错误类型
switch(error) {
case EBADF: // 无效文件描述符
DBG(DBG_M_DEBUG, "Invalid file descriptor\r\n");
break;
case EINVAL: // 无效的 whence 或 offset
DBG(DBG_M_DEBUG, "Invalid offset or whence\r\n");
break;
case EOVERFLOW: // offset 过大
DBG(DBG_M_DEBUG, "Offset overflow\r\n");
break;
}
return E_SYS_CALL;
}
len_wr = write(fd, pdata, size);
if (len_wr != size)
{
DBG(DBG_M_DEBUG, "Write file " PD_UPG_SOFTWARE " error!\r\n");
return E_SYS_CALL;
}
/* 最后一个报文处理 */
if (head_msg->sum - 1 == head_msg->index)
{
close(fd);
fd = -1;
DBG(DBG_M_DEBUG, "Receive upgrade file end.\r\n");
pd_upg_start(PD_UPG_FROM_CSG, head_msg->type);
}
pack->index = head_msg->index;
/* 发送应答 */
_debug_pkt_common_send(pkt, DEBUG_UPGRADE_DATA, sizeof(dbg_upgrade_ack_t));
return E_NONE;
}
/* 报文校验. */
int32_t _debug_pkt_check(char *buf, int len)
{
dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf;
uint16_t *tail = (uint16_t*)(buf + len - 2);
DBG(DBG_M_DEBUG, "receive data head->head is 0X%X!,tail is 0X%X!\r\n",
head->head, *tail);
if (*tail != DEBUG_TAIL)
{
return E_ERROR;
}
if(head->head != DEBUG_HEAD)
{
return E_ERROR;
}
return E_NONE;
}
/* 调试工具报文数据处理. */
int32_t _debug_pkt_process(char *buf, int32_t len)
{
dbg_pkt_head_t *head = (dbg_pkt_head_t*)buf;
/* 报文格式检查. */
LD_E_RETURN(DBG_M_DEBUG, _debug_pkt_check(buf, len));
/* 报文处理. */
switch(head->cmd)
{
case DEBUG_CONFIG_FACTORY_GET:
DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_FACTORY_GET data!\r\n");
_debug_pkt_factory_cfg_get(buf, len);
break;
case DEBUG_CONFIG_FACTORY_SET:
DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_FACTORY_SET data!\r\n");
_debug_pkt_factory_cfg_set(buf, len);
break;
case DEBUG_CONFIG_GLOBAL_GET:
DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_GLOBAL_GET data!\r\n");
_debug_pkt_global_cfg_get(buf, len);
break;
case DEBUG_CONFIG_GLOBAL_SET:
DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_GLOBAL_SET data!\r\n");
_debug_pkt_global_cfg_set(buf, len);
break;
case DEBUG_CONFIG_PORT_GET:
DBG(DBG_M_DEBUG, "get DEBUG_CONFIG_PORT_GET data!\r\n");
_debug_pkt_port_cfg_get(buf, len);
break;
case DEBUG_CONFIG_PORT_SET:
DBG(DBG_M_DEBUG, "set DEBUG_CONFIG_GLOBAL_SET data!\r\n");
_debug_pkt_port_cfg_set(buf, len);
break;
case DEBUG_REBOOT:
_debug_pkt_reboot(buf, len);
break;
case DEBUG_TIME_SET:
_debug_pkt_time_set(buf, len);
break;
case DEBUG_DEVICE_STATUS:
_debug_pkt_status_get(buf, len);
break;
case DEBUG_UPGRADE_DATA:
_debug_pkt_upgrade(buf, len);
break;
case DEBUG_SET_WAVE_ADDRESS:
_debug_pkt_set_wave_address( buf, len);
break;
default:
DBG(DBG_M_DEBUG, "Debug not support cmd:%x\n", head->cmd);
break;
}
return E_NONE;
}
/* tcp 连接粘包处理函数. */
int32_t _debug_pkt_recv_adhesion(char *buf, int len, int *len_recv)
{
dbg_pkt_head_t *head = NULL;
static int len_pkt = 0;
static int bytes_cnt = 0;
static int state = 0;
if (0 == state)
{
/* 首包处理. */
head = (dbg_pkt_head_t*)buf;
bytes_cnt = 0;
if (head->len > 10485000)
{
/* 报文太长不处理. */
return -1;
}
else if (0x55aa == head->head)
{
DBG(DBG_M_DEBUG, "pkt datalen head->len is %d\r\n", head->len);
/* 报文头处理, 置标志位. */
state = 1;
/* 计算剩余报文长度, 复制数据, 并计算收包总长度. */
len_pkt = head->len + 32 - len;
memcpy(buf_cmd + bytes_cnt, buf, len);
bytes_cnt += len;
/* 计算下一包应该接收多大的数据. */
if (len_pkt > DEBUG_BUG_SIZE)
{
*len_recv = DEBUG_BUG_SIZE;
}
else
{
*len_recv = len_pkt;
}
}
else
{
/* 在状体 0 下, 收到的报文不是以 0x55aa 开头, 无效报文不处理. */
return -1;
}
}
else if(1 == state)
{
/* 报文内容处理. */
/* 计算剩余报文长度, 复制数据, 并计算收包总长度. */
len_pkt -= len;
memcpy(buf_cmd + bytes_cnt, buf, len);
bytes_cnt += len;
/* 计算下一包应该接收多大的数据. */
if (len_pkt > DEBUG_BUG_SIZE)
{
*len_recv = DEBUG_BUG_SIZE;
}
else
{
*len_recv = len_pkt;
}
printf("@2len_pkt=%d\n", len_pkt);
}
/* 报文没有收全, 继续等待数据. */
if (len_pkt > 0)
{
return 0;
}
state = 0;
return bytes_cnt;
}
int _debug_keep_alive(int fd)
{
// 开启保活,保活参数 表示60秒内无交互后每隔6秒检测一次40次都没得到响应时会断开连接。
int keep_alive = 1;
int keep_idle = 60;
int keep_interval = 6;
int keep_count = 10;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive, sizeof(keep_alive)))
{
log_err(LOG_DEBUG, "Error setsockopt(SO_KEEPALIVE) failed, return %s!", safe_strerror(errno));
return -1;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_idle, sizeof(keep_idle)))
{
log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPIDLE) failed, return %s!", safe_strerror(errno));
return -1;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)))
{
log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPINTVL) failed, return %s!", safe_strerror(errno));
return -1;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keep_count, sizeof(keep_count)))
{
log_err(LOG_DEBUG, "Error setsockopt(TCP_KEEPCNT) failed, return %s!", safe_strerror(errno));
return -1;
}
return 0;
}
/* 调试工具报文接收处理线程. */
void *_debug_pkt_recv_handle(void *arg)
{
char *buf = debug_ctrl.buf;
int len = 0;
int len_pkt = 0;
int len_recv = DEBUG_BUG_SIZE;
while(1)
{
/* 连接成功. */
len_recv = DEBUG_BUG_SIZE;
if (debug_ctrl.fd_client > 0)
{
/* 读取数据. */
len = read(debug_ctrl.fd_client, buf, len_recv);
if (len <= 0)
{
/* 连接中断, 关闭 socket 和手动采样. */
DBG(DBG_M_DEBUG, "Read len %d, close fd!\r\n", len);
close(debug_ctrl.fd_client);
debug_ctrl.fd_client = -1;
break;
}
/* 粘包处理. */
len_pkt = _debug_pkt_recv_adhesion(buf, len, &len_recv);
if (len_pkt <= 0)
{
continue;
}
_debug_pkt_process(buf_cmd, len_pkt);
len_recv = DEBUG_BUG_SIZE;
}
usleep(10*1000);
}
pthread_exit("thread exit");
return NULL;
}
int32_t _debug_create_recv_thread()
{
struct sched_param param;
pthread_attr_t attr;
int32_t rv = 0;
pthread_t thread;
/* 初始化报文处理线程. */
/* 配置线程RR调度, 优先级25. */
pthread_attr_init(&attr);
param.sched_priority = 25;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
rv = pthread_create(&thread, &attr, _debug_pkt_recv_handle, NULL);
if (rv != 0)
{
log_err(LOG_DEBUG, "PD can't create debug pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("PD_DEBUG", thread);
}
pthread_attr_destroy(&attr);
return E_NONE;
}
void *_debug_accept_connect_handle()
{
struct sockaddr_in cliaddr = {0};
socklen_t clilen;
int connfd;
/* 等待初始化完成 */
while(!is_system_init)
{
usleep(100000);
}
/* 监听端口. */
if ((listen(debug_ctrl.fd, 5)) != 0)
{
log_err(LOG_DEBUG, "ERROR at socket listen return %s!", safe_strerror(errno));
return NULL;
}
while (1)
{
clilen = sizeof(cliaddr);
connfd = accept(debug_ctrl.fd, (struct sockaddr*)&cliaddr, &clilen);
if (connfd < 0)
{
log_err(LOG_DEBUG, "ERROR at socket accept return %s!", safe_strerror(errno));
continue;
}
char buf[20] = {0};
DBG(DBG_M_DEBUG, "new client: %s, port: %d fd_client=%d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, buf, sizeof(buf)),
ntohs(cliaddr.sin_port), debug_ctrl.fd_client);
if (debug_ctrl.fd_client < 0)
{
debug_ctrl.fd_client = connfd;
_debug_create_recv_thread();
_debug_keep_alive(debug_ctrl.fd_client);
}
else
{
DBG(DBG_M_DEBUG, "There is a link trying to connect...\n");
close(connfd);
connfd = -1;
}
}
return NULL;
}
/* Interface functions -------------------------------------------------------*/
/* 调试工具初始化. */
int32_t debug_handle_init(void)
{
return E_NONE;
}
int32_t debug_handle_init_after(void)
{
struct sockaddr_in server;
struct sched_param param;
pthread_attr_t attr;
pthread_t pid;
int32_t rv = 0;
int fd = 0;
int opt = 1;
/* 创建 socket. */
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
log_err(LOG_DEBUG, "ERROR at socket create return %s!", safe_strerror(errno));
return E_SYS_CALL;
}
/* fd 为需要端口复用的套接字. */
opt = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
/* 绑定端口. */
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(DEBUG_MANAGE_TOOL_PORT);
if(bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0)
{
log_err(LOG_DEBUG, "ERROR at socket bind return %s!", safe_strerror(errno));
close(fd);
return E_SYS_CALL;
}
/* 保存数据. */
debug_ctrl.fd = fd;
debug_ctrl.fd_client = -1;
pthread_attr_init(&attr);
param.sched_priority = 25;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _debug_accept_connect_handle, NULL);
if (rv != 0)
{
log_err(LOG_DEBUG, "PD can't create debug pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("PD_DEBUG_ACCEPT", pid);
}
pthread_attr_destroy(&attr);
return E_NONE;
}
/* 升级结果回复处理 */
void debug_upgrade_result_send(int32_t rv, char *buf)
{
char buffer[32] = {0};
int32_t *rt = (int32_t*)(buffer + sizeof(dbg_pkt_head_t));
*rt = rv;
_debug_pkt_common_send(buffer, 0, 4);
}
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/