这部分将分析当设备收到对端设备发现报文时,需要发送响应报文的过程。
1 /* 2 函数功能: 获取服务发现信息 3 函数参数: 4 buf : 指向保存有服务信息的数据缓冲区 5 size : 数据缓冲区大小 6 deviceInfo: 用来保存设备信息 7 remoteUrlPtr : 指向用来保存URL的缓存区 8 详细: 9 1. 判断buf是否为空 10 2. buf具有数据那么就分配一个同样大小的空间,并将buf中的数据拷贝到newbuf中,且将buf指针指向newbuf 11 3. 调用json_payload.c中ParseServiceDiscover解析出buf所指缓存区的数据(对端设备的 设备信息,设备功能,设备IP)保存在deviceInfo,url保存在由remoteUrlPtr指向的在url的缓存区 12 4. 释放newbuf空间 13 */ 14 int GetServiceDiscoverInfo(const uint8_t *buf, size_t size, DeviceInfo *deviceInfo, char **remoteUrlPtr) 15 { 16 uint8_t *newBuf = NULL; 17 if (size <= 0) { 18 return NSTACKX_EFAILED; 19 } 20 //包含数据 21 if (buf[size - 1] != '\0') { 22 //newBuf 分配空间并初始化为1 23 newBuf = (uint8_t *)calloc(1, size + 1); 24 if (newBuf == NULL) { 25 return NSTACKX_ENOMEM; 26 }· 27 if (memcpy_s(newBuf, size + 1, buf, size) != EOK) { 28 goto L_COAP_ERR; 29 } 30 buf = newBuf; 31 } 32 //解析出设备发现信息 33 if (ParseServiceDiscover(buf, deviceInfo, remoteUrlPtr) != NSTACKX_EOK) { 34 goto L_COAP_ERR; 35 } 36 if (newBuf != NULL) { 37 free(newBuf); 38 } 39 return NSTACKX_EOK; 40 L_COAP_ERR: 41 if (newBuf != NULL) { 42 free(newBuf); 43 } 44 return NSTACKX_EFAILED; 45 }
1 /* 2 函数功能: 对接收到的消息进行服务发现响应 3 函数功能: pkt: 接收到的coap数据包 4 函数返回值 : 无 5 详细: 6 1. 声明remoteurl 来存储对端url,deiceInfo保存对端设备信息 7 2. 调用GetServiceDiscoverInfo解析出device信息和对端url 8 3. 创建字符数组wifiIpAddr用来保存对端ip地址 9 4. 将点分IP转换为二进制网络字节序IP,并保存在wifiIpAddr 10 5. 发送响应报文,最后释放remoteUrl 11 */ 12 void PostServiceDiscover(const COAP_Packet *pkt) 13 { 14 char *remoteUrl = NULL; 15 DeviceInfo deviceInfo; 16 if (pkt == NULL) { 17 return; 18 } 19 //为deiveInfo分配空间 20 (void)memset_s(&deviceInfo, sizeof(deviceInfo), 0, sizeof(deviceInfo)); 21 if (GetServiceDiscoverInfo(pkt->payload.buffer, pkt->payload.len, &deviceInfo, &remoteUrl) != NSTACKX_EOK) { 22 return; 23 } 24 char wifiIpAddr[NSTACKX_MAX_IP_STRING_LEN]; 25 (void)memset_s(wifiIpAddr, sizeof(wifiIpAddr), 0, sizeof(wifiIpAddr)); //初始化为0 26 (void)inet_ntop(AF_INET, &deviceInfo.netChannelInfo.wifiApInfo.ip, wifiIpAddr, sizeof(wifiIpAddr)); 27 if (remoteUrl != NULL) { 28 CoapResponseService(pkt, remoteUrl, wifiIpAddr); 29 free(remoteUrl); 30 } 31 }
1 /* 2 函数功能: 处理读事件 3 函数参数 : fd: 可读就绪的套接字 4 函数返回值: 无 5 详细: 6 1. 分配一个1*(COAP_MAX_PDU_SIZE + 1) 接收缓存区 7 2. 调用coap_socket.c中CoapSocketRecv函数接收数据 8 3. 如果接收错误,释放接收缓冲区空间 9 4. 创建一个COAP_Packet,用于保存从接收缓冲区解析出来的coap数据包 10 5. 最后需要对接收到的数据做出响应 11 */ 12 static void HandleReadEvent(int fd) 13 { 14 int socketFd = fd; 15 unsigned char *recvBuffer = calloc(1, COAP_MAX_PDU_SIZE + 1); 16 if (recvBuffer == NULL) { 17 return; 18 } 19 ssize_t nRead; 20 nRead = CoapSocketRecv(socketFd, recvBuffer, COAP_MAX_PDU_SIZE); 21 if ((nRead == 0) || (nRead < 0 && errno != EAGAIN && 22 errno != EWOULDBLOCK && errno != EINTR)) { 23 free(recvBuffer); 24 return; 25 } 26 COAP_Packet decodePacket; 27 (void)memset_s(&decodePacket, sizeof(COAP_Packet), 0, sizeof(COAP_Packet)); 28 decodePacket.protocol = COAP_UDP; 29 COAP_SoftBusDecode(&decodePacket, recvBuffer, nRead); 30 PostServiceDiscover(&decodePacket); 31 free(recvBuffer); 32 } 33 /* 34 函数功能: 接收并处理收到的数据 35 详细: 36 1. 声明fd_set结构来表示一组等待检查的套接口,用于select 端口复用,可读文件描述符 37 2. 获取服务端socket 38 3. 将set清零使集合中不含任何fd,将服务socket接入到集合 39 4. 需要检查的文件描述字个数(即检查到fd_set的第几位),用来检查可读性的一组文件描述字readSet 40 5. 若有就绪描述符,则返回就绪描述符数目,检查readSet中对应serverFd的位是否被设置,如果该位被设置之后,那么readSet中与serverFd对应的位无关的位均清0 41 6. 最后处理读事件 42 */ 43 static void CoapReadHandle(unsigned int uwParam1, unsigned int uwParam2, unsigned int uwParam3, unsigned int uwParam4) 44 { 45 //这些参数在函数体中没有用到,但是为了防止编译器警告 46 (void)uwParam1; 47 (void)uwParam2; 48 (void)uwParam3; 49 (void)uwParam4; 50 int ret; 51 //fd_set结构来表示一组等待检查的套接口,用于select 端口复用,可读文件描述符 52 fd_set readSet; 53 //获取服务端socket 54 int serverFd = GetCoapServerSocket(); 55 SOFTBUS_PRINT("[DISCOVERY] CoapReadHandle coin select begin\n"); 56 while (g_terminalFlag) { //设备为终端设备 57 FD_ZERO(&readSet);//将set清零使集合中不含任何fd 58 FD_SET(serverFd, &readSet); //将服务socket接入到集合 59 //需要检查的文件描述字个数(即检查到fd_set的第几位),用来检查可读性的一组文件描述字readSet 60 ret = select(serverFd + 1, &readSet, NULL, NULL, NULL); 61 //若有就绪描述符,则返回就绪描述符数目 62 if (ret > 0) { 63 //检查readSet中对应serverFd的位是否被设置,如果该位被设置之后,那么readSet中与serverFd对应的位无关的位均清0, 64 if (FD_ISSET(serverFd, &readSet)) { 65 //处理读事件 66 HandleReadEvent(serverFd); 67 } 68 } else { 69 SOFTBUS_PRINT("[DISCOVERY]ret:%d,error:%d\n", ret, errno); 70 } 71 } 72 SOFTBUS_PRINT("[DISCOVERY] CoapReadHandle exit\n"); 73 }