OpenHarmony之分布式软总线coap_discover.c(四)

往期知识点记录:

//接口状态
typedef enum {
    STATUS_UP,
    STATUS_DOWN
} InterfaceStatus;
//接口信息  
typedef struct {
    char ip[NSTACKX_MAX_IP_STRING_LEN];
    InterfaceStatus status;
    int flag;
} InterfaceInfo;
/*
    函数功能: 获取网络接口信息
    函数参数: 
            fd: 接口文件描述符
            interfaceName: 接口名
            length: 接口名长度
            info: 用来保存获得到的接口信息
    函数过程:
        1. 检查各个参数
        2. 声明 ifreq 结构体 ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的
        3. 调用ioctl 获取 本地网络接口信息,接口是否处于活动状态且准备好传输数据  ,如果是 接口状态就是上传 那么info状态就是上传,否则接口就在下载
        4. 调用ioctl 获取接口IP地址
        5. 将ip地址以点分十进制复制到info中
*/
void GetInterfaceInfo(int fd, const char* interfaceName, int length, InterfaceInfo *info)
{
    if (fd < 0 || info == NULL || interfaceName == NULL) {
        return;
    }
    struct ifreq ifr;  //ifreq 结构体 ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的
    /*
        struct ifreq {
    char ifr_name[IFNAMSIZ];   //接口名
    union  
      {  (IP地址,广播地址,子网掩码,MAC号,MTU等)
        struct sockaddr ifru_addr;     
        struct sockaddr ifru_dstaddr;  
        struct sockaddr ifru_broadaddr;  
        struct sockaddr ifru_netmask;  
        struct sockaddr ifru_hwaddr;  
        short int ifru_flags;  
        int ifru_ivalue;  
        int ifru_mtu;  
        struct ifmap ifru_map;  
        char ifru_slave[IFNAMSIZ]; 
        char ifru_newname[IFNAMSIZ];  
        __caddr_t ifru_data;  
      } ifr_ifru
}; */
    memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq));
    //将接口名拷贝到ifreq
    int ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), interfaceName, length);
    if (ret != EOK) {
        SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp ifr.ifr_name cpy fail\n");
        return;
    }
    //ioctl 获取本地网络接口信息
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
        return;
    }
    //接口是否处于活动状态且准备好传输数据  ,如果是 接口状态就是上传
    if ((unsigned short int)ifr.ifr_flags & IFF_UP) {
        info->status = STATUS_UP;
    } else {
        //否则接口就在下载
        info->status = STATUS_DOWN;
        info->ip[0] = '\0';
        info->flag = 1;
        return;
    }
    memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq));
    ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), interfaceName, length);
    if (ret != EOK) {
        SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp ifr.ifr_name cpy fail\n");
        return;
    }
    //获取接口IP地址
    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        return;
    }
    //将ip地址以点分十进制复制到info中
    ret = strcpy_s(info->ip, sizeof(info->ip),
        inet_ntoa(((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr));
    if (ret != EOK) {
        SOFTBUS_PRINT("[DISCOVERY] CoapGetWifiIp cpy fail\n");
    }
    info->flag = 1;
    return;
}

/*
    函数功能: 获取wifi ip地址
    函数参数: 
            ip: 用来保存获取到的ip
            length: ip长度
    详细:  
        1.创建一个socket套接字, 声明InterfaceInfo结构体,调用GetInterfaceInfo获取网络接口信息
*/
void CoapGetWifiIp(char *ip, int length)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        return;
    }
    InterfaceInfo info = {0};
    GetInterfaceInfo(fd, ETH, strlen(ETH) + 1, &info);
    //获取以太网网络接口信息失败
    if (!info.flag) {
        memset_s(&info, sizeof(info), 0, sizeof(info));
        GetInterfaceInfo(fd, WLAN, strlen(WLAN) + 1, &info);
    }
    if (!info.flag) {
        close(fd);
        return;
    }
    //将接口ip复制到ip中
    if (strcpy_s(ip, length, info.ip) != EOK) {
        SOFTBUS_PRINT("[DISCOVERY]copy ip to dst failed.\n");
    }
    close(fd);
}

/*
    函数功能: 创建监听线程
    函数返回值:成功返回1,否则返回非零
    详细: 
        1.设置终端设备标志
        2. 如果g_coapTaskId不为0,那么表示监听线程之前就创建好
        3. 设置线程属性
        4. 创建线程
*/
int CreateCoapListenThread(void)
{
    g_terminalFlag = 1;
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
    if (g_coapTaskId != NULL) {
        return NSTACKX_EOK;
    }
    osThreadAttr_t attr;
    attr.name = "coap_listen_task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    attr.priority = osPriorityNormal4; // COAP_DEFAULT_PRIO -> cmsis prio
    g_coapTaskId = osThreadNew((osThreadFunc_t)CoapReadHandle, NULL, &attr);
    if (g_coapTaskId == NULL) {
        g_terminalFlag = 0;
        SOFTBUS_PRINT("[DISCOVERY] create task fail\n");
        return NSTACKX_EFAILED;
    }
#else
    if (g_coapTaskId != -1) {
        return NSTACKX_EOK;
    }
    ThreadAttr attr = {"coap_listen_task", 0x800, 20, 0, 0};
    int error = CreateThread((Runnable)CoapReadHandle, NULL, &attr, (unsigned int *)&g_coapTaskId);
    if (error != 0) {
        g_terminalFlag = 0;
        SOFTBUS_PRINT("[DISCOVERY] create task fail\n");
        return NSTACKX_EFAILED;
    }
#endif
    return NSTACKX_EOK;
}

/*
    函数功能: 撤销监听线程
    详细:
        1.终端标识设置为0
        2. 如果线程没有运行完毕,那么等待运行完成
*/
void ExitCoapListenThread(void)
{
    g_terminalFlag = 0;
#if defined(__LITEOS_M__) || defined(__LITEOS_RISCV__)
    if (g_coapTaskId != NULL) {
        if (osThreadTerminate(g_coapTaskId) != 0) {
            SOFTBUS_PRINT("[DISCOVERY] ExitCoapListenThread pthread_join fail\n");
            return;
        }
    }
#else
    if (g_coapTaskId != -1) {
        int ret = pthread_join((pthread_t)g_coapTaskId, NULL);
        if (ret != 0) {
            SOFTBUS_PRINT("[DISCOVERY] ExitCoapListenThread pthread_join fail\n");
            return;
        }
    }
#endif
}

/*
    函数功能: 设备发现初始化
    详细: 创建socket, 设置wifi事件, 创建处理消息队列线程,创建COAP监听线程
*/
int CoapInitDiscovery(void)
{
    int ret = CoapInitSocket();
    if (ret != NSTACKX_EOK) {
        SOFTBUS_PRINT("[DISCOVERY] Init socket fail\n");
        return ret;
    }
    ret = CoapInitWifiEvent();
    if (ret != NSTACKX_EOK) {
        SOFTBUS_PRINT("[DISCOVERY] Init wifi event fail\n");
        return ret;
    }
#if defined(__LITEOS_A__)
    ret = CreateQueryIpThread();
    if (ret != NSTACKX_EOK) {
        SOFTBUS_PRINT("[DISCOVERY] Init query Ip fail\n");
        return ret;
    }
#endif
    if (CreateMsgQueThread() != NSTACKX_EOK) {
        return NSTACKX_EFAILED;
    }
    return CreateCoapListenThread();
}

/*
    函数功能: 撤销设备发现
    详细: 
        1.退出监听线程
        2.撤销wifi事件
        3.关闭socket
*/
int CoapDeinitDiscovery(void)
{
    //
    ExitCoapListenThread();
    int rtn = CoapDeinitWifiEvent();
    if (rtn != NSTACKX_EOK) {
        return NSTACKX_EFAILED;
    }
#if defined(__LITEOS_A__)
    ExitQueryIpThread();
#endif
    CoapDeinitSocket();
    return NSTACKX_EOK;
}

/*
    函数功能: 检查IP是否有效
    详细: 
        1.判断ip是否为空,长度是否在范围内
        2. 判断是否是0.0.0.0的ip
        3. 判断是否是网关ip
*/
int CheckIpIsValid(const char *ip, int length)
{
    if (ip == NULL || length < IP_MIN_LEN || length > IP_MAX_LEN) {
        return -1;
    }
    if (strcmp(ip, "0.0.0.0") == 0) {
        return -1;
    }
    int pos = length - 1;
    if (ip[pos] == '1' && ip[pos - 1] == '.') {
        return -1;
    }
    return 0;
}
/*
    函数功能: 获取ip
    详细:
        1. 设置ip请求标志为1 
        2. 设置请求次数 (300/无限)
        3. 调用CoapGetWifiIp获取wifi ip
        4. 检查获取到的ip的有效性
*/
void CoapGetIp(char *ip, int length, int finite)
{
    if (ip == NULL || length != NSTACKX_MAX_IP_STRING_LEN) {
        return;
    }
    g_queryIpFlag = 1;
    int count = finite ? GET_IP_TIMES : GET_IP_INFINITE;
    while (g_queryIpFlag) {
        CoapGetWifiIp(ip, length);
        if (CheckIpIsValid(ip, strlen(ip)) == 0) {
            break;
        }
        if (count == 0) {
            break;
        }
        count--;
        usleep(TEN_MS);
    }
    return;
}

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请看下图提示:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值