Closed eternal-echo closed 1 year ago
DNS解析网址时调用了esp8266_domain_resolve函数,其中通过
esp8266_domain_resolve
example里的HAL_TCP_Establish函数会调用getaddrinfo函数,最终会进入sal_getaddrinfo函数里然后跳转到at_getaddrinfo接口。 实际调用了esp8266的at_device函数esp8266_domain_resolve。 ,at_gethostbyname函数调用esp8266_domain_resolve接口解析host,通过ipstr_to_u32将ip存入u32变量里。
HAL_TCP_Establish
getaddrinfo
sal_getaddrinfo
at_getaddrinfo
at_gethostbyname
ipstr_to_u32
struct hostent *at_gethostbyname(const char *name) { struct at_device *device = RT_NULL; ip_addr_t addr; char ipstr[16] = { 0 }; /* buffer variables for at_gethostbyname() */ static struct hostent s_hostent; static char *s_aliases; static ip_addr_t s_hostent_addr; static ip_addr_t *s_phostent_addr[2]; static char s_hostname[DNS_MAX_NAME_LENGTH + 1]; size_t idx = 0; if (name == RT_NULL) { LOG_E("AT gethostbyname input name error!"); return RT_NULL; } device = at_device_get_first_initialized(); if (device == RT_NULL) { return RT_NULL; } for (idx = 0; idx < strlen(name) && !isalpha(name[idx]); idx++); if (idx < strlen(name)) { if (device->class->socket_ops->at_domain_resolve(name, ipstr) < 0) { return RT_NULL; } } else { strncpy(ipstr, name, strlen(name)); } #if NETDEV_IPV4 && NETDEV_IPV6 addr.u_addr.ip4.addr = ipstr_to_u32(ipstr); addr.type = IPADDR_TYPE_V4; #elif NETDEV_IPV4 addr.addr = ipstr_to_u32(ipstr); #elif NETDEV_IPV6 #error "not support IPV6." #endif /* NETDEV_IPV4 && NETDEV_IPV6 */ /* fill hostent structure */ s_hostent_addr = addr; s_phostent_addr[0] = &s_hostent_addr; s_phostent_addr[1] = RT_NULL; strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); s_hostname[DNS_MAX_NAME_LENGTH] = 0; s_hostent.h_name = s_hostname; s_aliases = RT_NULL; s_hostent.h_aliases = &s_aliases; s_hostent.h_addrtype = AF_AT; s_hostent.h_length = sizeof(ip_addr_t); s_hostent.h_addr_list = (char**) &s_phostent_addr; return &s_hostent; } /* IP address to unsigned int type */ static uint32_t ipstr_to_u32(char *ipstr) { char ipBytes[4] = { 0 }; uint32_t i; for (i = 0; i < 4; i++, ipstr++) { ipBytes[i] = (char) ipstr_atol(ipstr); if ((ipstr = strchr(ipstr, '.')) == RT_NULL) { break; } } return *(uint32_t *) ipBytes; }
后调用ipaddr_to_ipstr函数来将u32变量转换回ipstr
ipaddr_to_ipstr
/* ipaddr structure change to IP address */ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr) { struct sockaddr_in *sin = (struct sockaddr_in *) sockaddr; /* change network ip_addr to ip string */ rt_snprintf(ipstr, 16, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); return 0; }
这个过程中将ip地址四个段的顺序弄反,需要修改
at_device软件包的esp8266_domain_resolve函数中关于"+CIPDOMAIN:%s"指令的解析有误,应为"+CIPDOMAIN:\"%s\"",才是正确的ip字符串,原来的解析多输入了引号,导致转换出错。 软件包的修改已同步到at_device中
bug
记录
DNS解析网址时调用了
esp8266_domain_resolve
函数,其中通过分析
example里的
HAL_TCP_Establish
函数会调用getaddrinfo
函数,最终会进入sal_getaddrinfo
函数里然后跳转到at_getaddrinfo
接口。 实际调用了esp8266的at_device函数esp8266_domain_resolve
。,
at_gethostbyname
函数调用esp8266_domain_resolve
接口解析host,通过ipstr_to_u32
将ip存入u32变量里。后调用
ipaddr_to_ipstr
函数来将u32变量转换回ipstr这个过程中将ip地址四个段的顺序弄反,需要修改