Files
BLV_C1F_Module/BasicCode/Drive/NET/DNS.c
caocong 95916b9995 fix:修改UDP通讯中,取电变化上报机制
1、问题点:当RCU网络状态异常的情况下,网络还处于协商状态下,还未进入正常通讯环节时,取电变化不会进行判断。这会导致取电变化上报与实际产生取电状态时间点对不上。
2、将BLV_C1F_Module代码上传至Gitea,之前代码修改记录请查看 .\BasicCode\Readme.txt
2026-01-23 09:23:12 +08:00

449 lines
15 KiB
C
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 "DNS.h"
#include "CH57xNET.H"
#include "DBG.h"
#define CH57xNET_DBG 1
/* 变量定义 */
UINT8 DNS_SERVER_IP[4]={223,5,5,5}; /* DNS服务器1 */
UINT8 DNS_SERVER_IP2[4]={114,114,114,114}; /* DNS服务器2 */
#define IPPORT_DOMAIN 53 /* DNS默认端口 */
UINT16 MSG_ID = 0x1100; /* 标识 */
//UINT32 count = 0;
//UINT8 dns_buf[MAX_DNS_BUF_SIZE];
UINT8* dns_buf = NULL;
//UINT8 url_dn4[] = "www.boonlive-rcu.com";
/*******************************************************************************
* Function Name : get16
* Description : 将缓冲区UINT8数据转为UINT16格式数据
* Input : s -UINT8类型数据
* Output : None
* Return : 转化后的UINT16类型数据
*******************************************************************************/
UINT16 get16(UINT8 * s)
{
UINT16 i;
i = *s++ << 8;
i = i + *s;
return i;
}
/*******************************************************************************
* Function Name : ParseName
* Description : 分析完整的域名
* Input : msg -指向报文的指针
compressed -指向报文中主域名的指针
buf -缓冲区指针,用于存放转化后域名
* Output : None
* Return : 压缩报文的长度
*******************************************************************************/
int ParseName(UINT8 * msg, UINT8 * compressed, char * buf)
{
UINT16 slen; /* 当前片段长度*/
UINT8 * cp;
int clen = 0; /* 压缩域名长度 */
int indirect = 0;
int nseg = 0; /* 域名被分割的片段总数 */
cp = compressed;
for (;;){
slen = *cp++; /* 首字节的计数值*/
if (!indirect) clen++;
if ((slen & 0xc0) == 0xc0){ /* 计数字节高两比特为1用于压缩格式 */
if (!indirect) clen++;
indirect = 1;
cp = &msg[((slen & 0x3f)<<8) + *cp]; /* 按计数字节数值指针偏移到指定位置 */
slen = *cp++;
}
if (slen == 0) break; /* 计数为0结束 */
if (!indirect) clen += slen;
while (slen-- != 0) *buf++ = (char)*cp++;
*buf++ = '.';
nseg++;
}
if (nseg == 0){
/* 根域名; */
*buf++ = '.';
}
*buf++ = '\0';
return clen; /* 压缩报文长度 */
}
/*******************************************************************************
* Function Name : DnsQuestion
* Description : 分析响应报文中的问题记录部分
* Input : msg -指向响应报文的指针
cp -指向问题记录的指针
* Output : None
* Return : 指向下一记录的指针
*******************************************************************************/
UINT8 * DnsQuestion(UINT8 * msg, UINT8 * cp)
{
int len;
char name[MAX_DNS_BUF_SIZE];
len = ParseName(msg, cp, name);
cp += len;
cp += 2; /* 类型 */
cp += 2; /* 类 */
return cp;
}
/*******************************************************************************
* Function Name : DnsAnswer
* Description : 分析响应报文中的回答记录部分
* Input : msg -指向响应报文的指针
cp -指向回答记录的指针
psip
* Output : None
* Return :指向下一记录的指针
*******************************************************************************/
UINT8 * DnsAnswer(UINT8 * msg, UINT8 * cp, UINT8 * pSip)
{
int len, type;
char name[MAX_DNS_BUF_SIZE];
len = ParseName(msg, cp, name);
cp += len;
type = get16(cp);
cp += 2; /* 类型 */
cp += 2; /* 类 */
cp += 4; /* 生存时间 */
cp += 2; /* 资源数据长度 */
switch ( type ){
case TYPE_A:
pSip[0] = *cp++;
pSip[1] = *cp++;
pSip[2] = *cp++;
pSip[3] = *cp++;
break;
case TYPE_CNAME:
case TYPE_MB:
case TYPE_MG:
case TYPE_MR:
case TYPE_NS:
case TYPE_PTR:
len = ParseName(msg, cp, name);
cp += len;
break;
case TYPE_HINFO:
case TYPE_MX:
case TYPE_SOA:
case TYPE_TXT:
break;
default:
break;
}
return cp;
}
/*******************************************************************************
* Function Name : parseMSG
* Description : 分析响应报文中的资源记录部分
* Input : msg -指向DNS报文头部的指针
cp -指向响应报文的指针
* Output : None
* Return :成功返回1否则返回0
*******************************************************************************/
UINT8 parseMSG(struct dhdr * pdhdr, UINT8 * pbuf, UINT8 * pSip)
{
UINT16 tmp;
UINT16 i;
UINT8 * msg;
UINT8 * cp;
msg = pbuf;
memset(pdhdr, 0, sizeof(*pdhdr));
pdhdr->id = get16(&msg[0]);
tmp = get16(&msg[2]);
if (tmp & 0x8000) pdhdr->qr = 1;
pdhdr->opcode = (tmp >> 11) & 0xf;
if (tmp & 0x0400) pdhdr->aa = 1;
if (tmp & 0x0200) pdhdr->tc = 1;
if (tmp & 0x0100) pdhdr->rd = 1;
if (tmp & 0x0080) pdhdr->ra = 1;
pdhdr->rcode = tmp & 0xf;
pdhdr->qdcount = get16(&msg[4]);
pdhdr->ancount = get16(&msg[6]);
pdhdr->nscount = get16(&msg[8]);
pdhdr->arcount = get16(&msg[10]);
/* 分析可变数据长度部分*/
cp = &msg[12];
/* 查询问题 */
for (i = 0; i < pdhdr->qdcount; i++)
{
cp = DnsQuestion(msg, cp);
}
/* 回答 */
for (i = 0; i < pdhdr->ancount; i++)
{
cp = DnsAnswer(msg, cp, pSip);
}
/*授权 */
for (i = 0; i < pdhdr->nscount; i++)
{
/*待解析*/ ;
}
/* 附加信息 */
for (i = 0; i < pdhdr->arcount; i++)
{
/*待解析*/ ;
}
if(pdhdr->rcode == 0) return 1; /* rcode = 0:成功 */
else return 0;
}
/*******************************************************************************
* Function Name : put16
* Description :UINT16 格式数据按UINT8格式存到缓冲区
* Input : s -缓冲区首地址
i -UINT16数据
* Output : None
* Return : 偏移指针
*******************************************************************************/
UINT8 * put16(UINT8 * s, UINT16 i)
{
*s++ = i >> 8;
*s++ = i;
return s;
}
/*******************************************************************************
* Function Name : MakeDnsQuery
* Description : 制作DNS查询报文
input : op - 递归
* name - 指向待查域名指针
* buf - DNS缓冲区.
* len - 缓冲区最大长度.
* Output : None
* Return : 指向DNS报文指针
*******************************************************************************/
UINT16 MakeDnsQueryMsg(UINT16 op, char * name, UINT8 * buf, UINT16 len)
{
UINT8 *cp;
char *cp1;
char tmpname[MAX_DNS_BUF_SIZE];
char *dname;
UINT16 p;
UINT16 dlen;
//printf("Domain name:%s \n",name);
cp = buf;
MSG_ID++;
cp = put16(cp, MSG_ID); /* 标识 */
p = (op << 11) | 0x0100;
cp = put16(cp, p); /* 0x0100Recursion desired */
cp = put16(cp, 1); /* 问题数1 */
cp = put16(cp, 0); /* 资源记录数0 */
cp = put16(cp, 0); /* 资源记录数0 */
cp = put16(cp, 0); /* 额外资源记录数0 */
strcpy(tmpname, name);
dname = tmpname;
dlen = strlen(dname);
for (;;){ /* 按照DNS请求报文域名格式把URI写入到buf里面去 */
cp1 = strchr(dname, '.');
if (cp1 != NULL) len = cp1 - dname;
else len = dlen;
*cp++ = len;
if (len == 0) break;
strncpy((char *)cp, dname, len);
cp += len;
if (cp1 == NULL)
{
*cp++ = 0;
break;
}
dname += len+1; /* dname首地址后移 */
dlen -= len+1; /* dname长度减小 */
}
cp = put16(cp, 0x0001); /* type 1------ip地址 */
cp = put16(cp, 0x0001); /* class1-------互联网地址 */
return ((UINT16)(cp - buf));
}
/*******************************************************************************
* Function Name : DnsQuery
* Description : 进行DNS查询
input : s -socket索引
* name - 指向待查域名指针
pSip -查询结果
* Output : None
* Return : 查询结果。成功返回1失败返回2
*******************************************************************************/
//UINT8 DnsQuery2(UINT8* s, UINT8 * name, UINT8 * pSip)
//{
// struct dhdr dhp;
// UINT8 ret;
// UINT32 len;
// if(Status >1 ){
// count++;
// DelayMs(10);
// if( count>20000 ){
//#if CH57xNET_DBG
// printf("DNS Fail!!!!!\n");
//#endif
// count=0;
// Status = 0;
// return 2;
// }
// }
// if(Status == 1)
// {
// DNS_SocketParamInit(s, DNS_SERVER_IP, 4000, IPPORT_DOMAIN);
// //UDPSocketParamInit(*s,DNS_SERVER_IP,4000,IPPORT_DOMAIN);
// Status = 2;
//#if CH57xNET_DBG
// printf(" 2 status = %d!\n",Status);
//#endif
// }
// if(Status ==2)
// {
// len = MakeDnsQueryMsg(0,(char *)name, dns_buf, MAX_DNS_BUF_SIZE);
// ret = CH57xNET_SocketSend(*s,dns_buf,&len);
// if ( ret ) return(0);
// else{
// Status = 3;
//#if CH57xNET_DBG
// printf("status = 3!\n");
//#endif
// }
// }
// if(Status ==4)
// {
// //CH57xNET_SocketClose(*s,TCP_CLOSE_NORMAL );
// return(parseMSG(&dhp, dns_buf, pSip)); /*解析响应报文并返回结果*/
//
// }
// return 0;
//}
/*******************************************************************************
* Function Name : DnsQuery_Task
* Description : 进行DNS查询
input : s -socket索引
* name - 指向待查域名指针
pSip -查询结果
* Output : None
* Return : 查询结果。成功返回1失败返回2
*用 法 : 循环调用
*******************************************************************************/
UINT8 DnsQuery_Task(UINT8* s, UINT8 * name, UINT8 * pSip)
{
static uint32_t dnschange_wait_tick1 = 0;
switch(server_info.dns_sta)
{
case DNS_INIT:
{
if(dns_buf == NULL) dns_buf = (UINT8*)malloc(MAX_DNS_BUF_SIZE/2); //为DNS分配空间
UINT8 ret = DNS_SocketParamInit(s, DNS_SERVER_IP, 4000, IPPORT_DOMAIN); //创建DNS用的套接字
if(ret == CH57xNET_ERR_SUCCESS)
{
server_info.dns_sta = DNS_DATA_SEND;
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS socket创建成功,DNS Server IP:%d.%d.%d.%d",\
DNS_SERVER_IP[0],DNS_SERVER_IP[1],DNS_SERVER_IP[2],DNS_SERVER_IP[3]);
}
else
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS socket重新创建,DNS Server IP:%d.%d.%d.%d",\
DNS_SERVER_IP[0],DNS_SERVER_IP[1],DNS_SERVER_IP[2],DNS_SERVER_IP[3]);
server_info.dns_sta = DNS_ClOSE; //2023-03-06
server_info.dns_fail++; //2023-03-06
}
}
break;
case DNS_INIT1:
{
if(dns_buf == NULL) dns_buf = (UINT8*)malloc(MAX_DNS_BUF_SIZE/2); //为DNS分配空间
UINT8 ret = DNS_SocketParamInit(s, DNS_SERVER_IP2, 4000, IPPORT_DOMAIN); //创建DNS用的套接字
if(ret == CH57xNET_ERR_SUCCESS)
{
server_info.dns_sta = DNS_DATA_SEND;
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS socket创建成功,DNS Server IP:%d.%d.%d.%d",\
DNS_SERVER_IP2[0],DNS_SERVER_IP2[1],DNS_SERVER_IP2[2],DNS_SERVER_IP2[3]);
}
else
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS socket重新创建,DNS Server IP:%d.%d.%d.%d",\
DNS_SERVER_IP2[0],DNS_SERVER_IP2[1],DNS_SERVER_IP2[2],DNS_SERVER_IP2[3]);
server_info.dns_sta = DNS_ClOSE; //2023-03-06
server_info.dns_fail++; //2023-03-06
}
}
break;
case DNS_DATA_SEND:
{
UINT32 len = MakeDnsQueryMsg(0,(char *)name, dns_buf, MAX_DNS_BUF_SIZE); //数据组包
UINT8 ret = CH57xNET_SocketSend(*s, dns_buf, &len); //发送到DNS服务器
if(ret == CH57xNET_ERR_SUCCESS)
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS等待接收");
}
else Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS发送失败");
server_info.wait_cot = SysTick_10ms;
server_info.dns_sta = DNS_WAIT_RECV;
server_info.dns_flg = 0x00;
}
break;
case DNS_WAIT_RECV: //如果DNS成功会在接收数据后关闭套接字
if(server_info.dns_flg == 1) //如果成功获取到服务器ip
{
struct dhdr dhp;
UINT8 rev = 0; //将该套接字索引清零
Dbg_Println(DBG_BIT_NET_STATUS_bit,"DNS 耗时:%d0ms", SysTick_10ms - server_info.wait_cot);
rev = parseMSG(&dhp, dns_buf, pSip); /*这个函数的返回值是0x01:成功0x00:失败*/
CH57xNET_SocketClose(*s,SOCK_STAT_CLOSED );
Dbg_Println(DBG_BIT_NET_STATUS_bit,"释放DNS套接字");
if(rev == 0x01) /*parseMSG 解析响应报文并返回结果 2022-06-08*/
{
return 0x01; //解析成功
}else {
server_info.dns_fail++;
server_info.dns_sta = DNS_ClOSE;
dnschange_wait_tick1 = SysTick_10ms;
}
}
else if(SysTick_10ms - server_info.wait_cot > 200) //等待接收超时
{
server_info.wait_cot = SysTick_10ms;
server_info.dns_sta = DNS_ClOSE;
server_info.dns_fail++;
}
break;
case DNS_ClOSE:
free(dns_buf); //释放DNS空间
dns_buf = NULL;
CH57xNET_SocketClose(*s,SOCK_STAT_CLOSED ); //将该套接字索引清零
if(server_info.dns_fail == 0x01)
{
if(SysTick_10ms - dnschange_wait_tick1 > 50)
{
Dbg_Println(DBG_BIT_NET_STATUS_bit,"切换DNS域名解析服务器");
dnschange_wait_tick1 = SysTick_10ms;
server_info.dns_sta = DNS_INIT1;
}
}
else if(server_info.dns_fail >= 0x02)
{
*s = 0;
server_info.dns_fail = 0x00;
return 0x02; //解析失败
}
break;
}
return 0;
}