eternal-echo / zigbee-gateway-stm32

0 stars 0 forks source link

[bug] ipstr和u32间来回转换后顺序相反了 #4

Closed eternal-echo closed 1 year ago

eternal-echo commented 1 year ago

bug

记录

DNS解析网址时调用了esp8266_domain_resolve函数,其中通过 image

分析

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变量里。

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 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地址四个段的顺序弄反,需要修改

eternal-echo commented 1 year ago

解决

at_device软件包的esp8266_domain_resolve函数中关于"+CIPDOMAIN:%s"指令的解析有误,应为"+CIPDOMAIN:\"%s\"",才是正确的ip字符串,原来的解析多输入了引号,导致转换出错。 image 软件包的修改已同步到at_device