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

往期知识点记录:

前言

这部分将分析当设备收到对端设备发现报文时,需要发送响应报文的过程。

接收与响应coap设备发现

/*
    函数功能: 获取服务发现信息
    函数参数: 
            buf :  指向保存有服务信息的数据缓冲区
            size : 数据缓冲区大小
            deviceInfo:  用来保存设备信息
            remoteUrlPtr : 指向用来保存URL的缓存区
    详细:
            1. 判断buf是否为空
            2. buf具有数据那么就分配一个同样大小的空间,并将buf中的数据拷贝到newbuf中,且将buf指针指向newbuf
            3. 调用json_payload.c中ParseServiceDiscover解析出buf所指缓存区的数据(对端设备的 设备信息,设备功能,设备IP)保存在deviceInfo,url保存在由remoteUrlPtr指向的在url的缓存区
            4. 释放newbuf空间
*/
int GetServiceDiscoverInfo(const uint8_t *buf, size_t size, DeviceInfo *deviceInfo, char **remoteUrlPtr)
{
    uint8_t *newBuf = NULL;
    if (size <= 0) {
        return NSTACKX_EFAILED;
    }
    //包含数据
    if (buf[size - 1] != '\0') {
        //newBuf 分配空间并初始化为1
        newBuf = (uint8_t *)calloc(1, size + 1);
        if (newBuf == NULL) {
            return NSTACKX_ENOMEM;
        }·
        if (memcpy_s(newBuf, size + 1, buf, size) != EOK) {
            goto L_COAP_ERR;
        }
        buf = newBuf;
    }
    //解析出设备发现信息
    if (ParseServiceDiscover(buf, deviceInfo, remoteUrlPtr) != NSTACKX_EOK) {
        goto L_COAP_ERR;
    }
    if (newBuf != NULL) {
        free(newBuf);
    }
    return NSTACKX_EOK;
L_COAP_ERR:
    if (newBuf != NULL) {
        free(newBuf);
    }
    return NSTACKX_EFAILED;
}

/*
    函数功能: 对接收到的消息进行服务发现响应
    函数功能: pkt: 接收到的coap数据包
    函数返回值 : 无
    详细:
        1. 声明remoteurl 来存储对端url,deiceInfo保存对端设备信息
        2. 调用GetServiceDiscoverInfo解析出device信息和对端url
        3. 创建字符数组wifiIpAddr用来保存对端ip地址
        4. 将点分IP转换为二进制网络字节序IP,并保存在wifiIpAddr
        5. 发送响应报文,最后释放remoteUrl
*/
void PostServiceDiscover(const COAP_Packet *pkt)
{
    char *remoteUrl = NULL;
    DeviceInfo deviceInfo;
    if (pkt == NULL) {
        return;
    }
    //为deiveInfo分配空间
    (void)memset_s(&deviceInfo, sizeof(deviceInfo), 0, sizeof(deviceInfo));
    if (GetServiceDiscoverInfo(pkt->payload.buffer, pkt->payload.len, &deviceInfo, &remoteUrl) != NSTACKX_EOK) {
        return;
    }
    char wifiIpAddr[NSTACKX_MAX_IP_STRING_LEN];
    (void)memset_s(wifiIpAddr, sizeof(wifiIpAddr), 0, sizeof(wifiIpAddr));  //初始化为0
    (void)inet_ntop(AF_INET, &deviceInfo.netChannelInfo.wifiApInfo.ip, wifiIpAddr, sizeof(wifiIpAddr));
    if (remoteUrl != NULL) {
        CoapResponseService(pkt, remoteUrl, wifiIpAddr);
        free(remoteUrl);
    }
}

/*
    函数功能: 处理读事件
    函数参数 : fd: 可读就绪的套接字
    函数返回值: 无
    详细:
        1. 分配一个1*(COAP_MAX_PDU_SIZE + 1) 接收缓存区
        2. 调用coap_socket.c中CoapSocketRecv函数接收数据
        3. 如果接收错误,释放接收缓冲区空间
        4. 创建一个COAP_Packet,用于保存从接收缓冲区解析出来的coap数据包
        5. 最后需要对接收到的数据做出响应
*/
static void HandleReadEvent(int fd)
{
    int socketFd = fd;
    unsigned char *recvBuffer = calloc(1, COAP_MAX_PDU_SIZE + 1);
    if (recvBuffer == NULL) {
        return;
    }
    ssize_t nRead;
    nRead = CoapSocketRecv(socketFd, recvBuffer, COAP_MAX_PDU_SIZE);
    if ((nRead == 0) || (nRead < 0 && errno != EAGAIN &&
        errno != EWOULDBLOCK && errno != EINTR)) {
        free(recvBuffer);
        return;
    }
    COAP_Packet decodePacket;
    (void)memset_s(&decodePacket, sizeof(COAP_Packet), 0, sizeof(COAP_Packet));
    decodePacket.protocol = COAP_UDP;
    COAP_SoftBusDecode(&decodePacket, recvBuffer, nRead);
    PostServiceDiscover(&decodePacket);
    free(recvBuffer);
}

/*
    函数功能: 接收并处理收到的数据
    详细:
        1. 声明fd_set结构来表示一组等待检查的套接口,用于select 端口复用,可读文件描述符
        2. 获取服务端socket
        3. 将set清零使集合中不含任何fd,将服务socket接入到集合
        4. 需要检查的文件描述字个数(即检查到fd_set的第几位),用来检查可读性的一组文件描述字readSet
        5. 若有就绪描述符,则返回就绪描述符数目,检查readSet中对应serverFd的位是否被设置,如果该位被设置之后,那么readSet中与serverFd对应的位无关的位均清0
        6. 最后处理读事件
*/
static void CoapReadHandle(unsigned int uwParam1, unsigned int uwParam2, unsigned int uwParam3, unsigned int uwParam4)
{
    //这些参数在函数体中没有用到,但是为了防止编译器警告
    (void)uwParam1; 
    (void)uwParam2;
    (void)uwParam3;
    (void)uwParam4;
    int ret;
    //fd_set结构来表示一组等待检查的套接口,用于select 端口复用,可读文件描述符
    fd_set readSet;
    //获取服务端socket
    int serverFd = GetCoapServerSocket();
    SOFTBUS_PRINT("[DISCOVERY] CoapReadHandle coin select begin\n");
    while (g_terminalFlag) {  //设备为终端设备
        FD_ZERO(&readSet);//将set清零使集合中不含任何fd
        FD_SET(serverFd, &readSet); //将服务socket接入到集合
        //需要检查的文件描述字个数(即检查到fd_set的第几位),用来检查可读性的一组文件描述字readSet   
        ret = select(serverFd + 1, &readSet, NULL, NULL, NULL);
        //若有就绪描述符,则返回就绪描述符数目
        if (ret > 0) {
            //检查readSet中对应serverFd的位是否被设置,如果该位被设置之后,那么readSet中与serverFd对应的位无关的位均清0,
            if (FD_ISSET(serverFd, &readSet)) {
                //处理读事件
                HandleReadEvent(serverFd);
            }
        } else {
            SOFTBUS_PRINT("[DISCOVERY]ret:%d,error:%d\n", ret, errno);
        }
    }
    SOFTBUS_PRINT("[DISCOVERY] CoapReadHandle exit\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值