static void CAReceiveMessage(int fd) { // #1. get remote device information from file descriptor. size_t index = 0; CATCPSessionInfo_t *svritem = CAGetSessionInfoFromFD(fd, &index); if (!svritem) { OIC_LOG(ERROR, TAG, "there is no connection information in list"); return; } // #2. get already allocated memory size. size_t bufSize = (svritem->totalDataLen == 0) ? TCP_MAX_HEADER_LEN : svritem->totalDataLen; if (!svritem->recvData) { svritem->recvData = (unsigned char *) OICCalloc(1, bufSize); if (!svritem->recvData) { OIC_LOG(ERROR, TAG, "out of memory"); CADisconnectTCPSession(svritem, index); return; } } // #3. receive data from remote device. ssize_t recvLen = recv(fd, svritem->recvData + svritem->recvDataLen, bufSize - svritem->recvDataLen, 0); if (recvLen <= 0) { if(EWOULDBLOCK != errno) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); CADisconnectTCPSession(svritem, index); } return; } svritem->recvDataLen += recvLen; // #4. get actual data length from coap over tcp header. if (!svritem->totalDataLen) { coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *) svritem->recvData)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (svritem->recvDataLen >= headerLen) { svritem->totalDataLen = CAGetTotalLengthFromHeader( (unsigned char *) svritem->recvData); bufSize = svritem->totalDataLen; unsigned char *newBuf = OICRealloc(svritem->recvData, bufSize); if (!newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); CADisconnectTCPSession(svritem, index); return; } svritem->recvData = newBuf; } }
static CAResult_t CAReceiveMessage() { uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); size_t i = 0; unsigned char *recvBuffer = NULL; CATCPServerInfo_t *svritem = NULL; for (i = 0; i < length; i++) { svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem->u4tcp.fd < 0) { continue; } size_t bufSize = TCP_MAX_HEADER_LEN; recvBuffer = (unsigned char *) OICCalloc(1, bufSize); if (!recvBuffer) { OIC_LOG(ERROR, TAG, "out of memory"); goto exit; } bool isHeaderChecked = false; size_t totalLen = 0; size_t totalReceivedLen = 0; do { ssize_t recvLen = recv(svritem->u4tcp.fd, recvBuffer + totalReceivedLen, bufSize - totalReceivedLen, 0); if (recvLen <= 0) { if(EWOULDBLOCK != errno) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); goto exit; } // if received data length is zero, we are breaking loop. // because we use non-blocking socket to receive data from remote device. if (!totalReceivedLen) { break; } continue; } totalReceivedLen += recvLen; if (!isHeaderChecked && totalReceivedLen) { coap_transport_type transport = coap_get_tcp_header_type_from_initbyte( ((unsigned char *)recvBuffer)[0] >> 4); size_t headerLen = coap_get_tcp_header_length_for_transport(transport); if (totalReceivedLen >= headerLen) { // get actual data length from coap over tcp header totalLen = CAGetTotalLengthFromHeader((unsigned char *) recvBuffer); bufSize = totalLen; unsigned char *newBuf = OICRealloc(recvBuffer, bufSize); if (NULL == newBuf) { OIC_LOG(ERROR, TAG, "out of memory"); goto exit; } recvBuffer = newBuf; isHeaderChecked = true; } } if (totalLen == totalReceivedLen) { CAEndpoint_t ep = { .adapter = CA_ADAPTER_TCP, .port = svritem->u4tcp.port }; strncpy(ep.addr, svritem->addr, sizeof(ep.addr)); if (g_packetReceivedCallback) { g_packetReceivedCallback(&ep, recvBuffer, totalLen); } OIC_LOG_V(DEBUG, TAG, "received data len:%d", totalLen); break; } } while (!totalLen || totalLen > totalReceivedLen); OICFree(recvBuffer); }