coap_discover.c实现了基于coap的设备发现功能的细节。在之前说过coap_service.c在实现coap服务发现的前期工作中做了许多前期初始化功能和注册服务的工作,这些功能函数是调用nstackx_device.c提供的接口函数,而nstackx_common.c中的接口函数又调用coap_discover.c中提供的函数接口。所以在coap_discover.c中实现了具体的初始化细节,并且在这个文件中定义了发送设备信息服务和接收对端设备信息服务功能。
首先定义了请求/响应结构
1 /*COAP 请求(响应)结构 , 响应和请求共用统一首部*/ 2 typedef struct CoapRequest { 3 const char *remoteUrl; //URL 4 char *data; // 数据 5 size_t dataLength; //数据长度 6 const char *remoteIp; //远端iP 7 } CoapRequest;
发送coap请求报文
1 /* 2 函数功能:发送coap请求报文 3 函数参数: coapRequest : 待发送的请求数据结构 4 函数返回值: 成功返回0,否则返回非零 5 详细: 6 1.判断请求报文,报文中url和IP地址是否为空 7 2.socket通用操作,将IP字符串格式的ip地址转换为一个uint32_t数字格式,接口转为网络字节序、选择IPv4 8 3.创建一个客户端socket并且connect地址:端口 9 4.获取创建好的客户端socket套接字 10 5.发送请求报文 11 */ 12 static int CoapSendRequest(const CoapRequest *coapRequest) 13 { 14 if (coapRequest == NULL || coapRequest->remoteUrl == NULL) { 15 return NSTACKX_EFAILED; 16 } 17 struct sockaddr_in sockAddr = {0}; 18 if (coapRequest->remoteIp == NULL) { 19 return NSTACKX_EFAILED; 20 } 21 //将IP字符串格式的ip地址转换为一个uint32_t数字格式 22 sockAddr.sin_addr.s_addr = inet_addr(coapRequest->remoteIp); 23 //将接口转为网络字节序 24 sockAddr.sin_port = htons(COAP_DEFAULT_PORT); 25 //选择IPv4 26 sockAddr.sin_family = AF_INET; 27 //创建一个客户端socket并且connect地址:端口 28 int ret = CoapCreateUdpClient(&sockAddr); 29 if (ret != NSTACKX_EOK) { 30 return NSTACKX_EFAILED; 31 } 32 //socket信息,获取创建好的客户端socket套接字 33 SocketInfo socket = {0}; 34 socket.cliendFd = GetCoapClientSocket(); 35 socket.dstAddr = sockAddr; 36 //发送数据 37 if (CoapSocketSend(&socket, (uint8_t *)coapRequest->data, coapRequest->dataLength) == -1) { 38 SOFTBUS_PRINT("[DISCOVERY]reponse coap failed.\r\n"); 39 return NSTACKX_EFAILED; 40 } 41 return NSTACKX_EOK; 42 }
发送响应报文
1 /* 2 函数功能: 发送响应报文 3 函数参数: 4 pkt: coap 报文 5 remoteUrl : 远端Url 6 remoteIp : 远端IP 7 函数返回值:成功返回0,否则非零 8 详细: 9 1. 声明一个响应报文结构,并且初始化 10 2. 设置url和ip 11 3. 调用PrepareServiceDiscover,cJSON封装本地数据(设备信息,iP地址,设备功能) 12 4. 声明coap 读写缓冲区,并分配空间1*COAP_MAX_PDU_SIZE,且初始化为0 13 5. 设置缓存区长度为COAP_MAX_PDU_SIZE,当前还没有数据所以长度为0 14 6. 调用coap_adapter.c中BuildSendPkt函数创建发送coap数据包,组装成的coap数据包存储在sndPktBuff读写缓存区中 15 7. 将存储在sndPktBuff读写缓存区中的coap作为报文结构中的数据主体部分,并设置报文数据长度 16 8. 最后释放缓冲区空间,并将指针置为空,防止野指针 17 */ 18 static int CoapResponseService(const COAP_Packet *pkt, const char* remoteUrl, const char* remoteIp) 19 { 20 int ret; 21 CoapRequest coapRequest; //响应报文结构 22 (void)memset_s(&coapRequest, sizeof(coapRequest), 0, sizeof(coapRequest)); //初始化 23 coapRequest.remoteUrl = remoteUrl; //远端url 24 coapRequest.remoteIp = remoteIp; //远端ip 25 char *payload = PrepareServiceDiscover(); //payload 具有本地设备信息 IP地址,设备功能 26 if (payload == NULL) { 27 return NSTACKX_EFAILED; 28 } 29 //发送读写缓冲区 30 COAP_ReadWriteBuffer sndPktBuff = {0}; 31 sndPktBuff.readWriteBuf = calloc(1, COAP_MAX_PDU_SIZE); 32 //分配不成功 33 if (sndPktBuff.readWriteBuf == NULL) { 34 free(payload); 35 return NSTACKX_EFAILED; 36 } 37 sndPktBuff.size = COAP_MAX_PDU_SIZE; 38 sndPktBuff.len = 0; 39 //创建响应coap数据包,组装成的coap数据包存储在sndPktBuff读写缓存区中 40 ret = BuildSendPkt(pkt, remoteIp, payload, &sndPktBuff); 41 free(payload); 42 if (ret != DISCOVERY_ERR_SUCCESS) { 43 free(sndPktBuff.readWriteBuf); 44 sndPktBuff.readWriteBuf = NULL; 45 return ret; 46 } 47 //将存储在sndPktBuff读写缓存区中的coap作为报文结构中的数据主体部分 48 coapRequest.data = sndPktBuff.readWriteBuf; 49 //设置报文数据长度 50 coapRequest.dataLength = sndPktBuff.len; 51 //发送报文 52 ret = CoapSendRequest(&coapRequest); 53 //最后释放readWriteBuf空间,并置空防止野指针 54 free(sndPktBuff.readWriteBuf); 55 sndPktBuff.readWriteBuf = NULL; 56 return ret; 57 }