static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags) { char recvBuffer[COAP_MAX_PDU_SIZE]; struct sockaddr_storage srcAddr; socklen_t srcAddrLen = sizeof (srcAddr); ssize_t recvLen = recvfrom(fd, recvBuffer, sizeof (recvBuffer), 0, (struct sockaddr *)&srcAddr, &srcAddrLen); if (-1 == recvLen) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); return CA_STATUS_FAILED; } CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}}; if (flags & CA_IPV6) { sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id; ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0; } CAConvertAddrToName(&srcAddr, sep.endpoint.addr, &sep.endpoint.port); if (flags & CA_SECURE) { #ifdef __WITH_DTLS__ int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen); OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret); #else OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS"); #endif } else { if (g_packetReceivedCallback) { g_packetReceivedCallback(&sep, recvBuffer, recvLen); } } return CA_STATUS_OK; }
static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags) { char recvBuffer[COAP_MAX_PDU_SIZE]; size_t len; int level, type, namelen; struct sockaddr_storage srcAddr; unsigned char *pktinfo = NULL; struct cmsghdr *cmp = NULL; struct iovec iov = { recvBuffer, sizeof (recvBuffer) }; union control { struct cmsghdr cmsg; unsigned char data[CMSG_SPACE(sizeof (struct in6_pktinfo))]; } cmsg; if (flags & CA_IPV6) { namelen = sizeof (struct sockaddr_in6); level = IPPROTO_IPV6; type = IPV6_PKTINFO; len = sizeof (struct in6_pktinfo); } else { namelen = sizeof (struct sockaddr_in); level = IPPROTO_IP; type = IP_PKTINFO; len = sizeof (struct in6_pktinfo); } struct msghdr msg = { .msg_name = &srcAddr, .msg_namelen = namelen, .msg_iov = &iov, .msg_iovlen = 1, .msg_control = &cmsg, .msg_controllen = CMSG_SPACE(len) }; ssize_t recvLen = recvmsg(fd, &msg, flags); if (-1 == recvLen) { OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno)); return CA_STATUS_FAILED; } if (flags & CA_MULTICAST) { for (cmp = CMSG_FIRSTHDR(&msg); cmp != NULL; cmp = CMSG_NXTHDR(&msg, cmp)) { if (cmp->cmsg_level == level && cmp->cmsg_type == type) { pktinfo = CMSG_DATA(cmp); } } } CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}}; if (flags & CA_IPV6) { sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id; ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0; if ((flags & CA_MULTICAST) && pktinfo) { struct in6_addr *addr = &(((struct in6_pktinfo *)pktinfo)->ipi6_addr); unsigned char topbits = ((unsigned char *)addr)[0]; if (topbits != 0xff) { sep.endpoint.flags &= ~CA_MULTICAST; } } } else { if ((flags & CA_MULTICAST) && pktinfo) { struct in_addr *addr = &((struct in_pktinfo *)pktinfo)->ipi_addr; uint32_t host = ntohl(addr->s_addr); unsigned char topbits = ((unsigned char *)&host)[3]; if (topbits < 224 || topbits > 239) { sep.endpoint.flags &= ~CA_MULTICAST; } } } CAConvertAddrToName(&srcAddr, msg.msg_namelen, sep.endpoint.addr, &sep.endpoint.port); if (flags & CA_SECURE) { #ifdef __WITH_DTLS__ int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen); OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret); #else OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS"); #endif } else { if (g_packetReceivedCallback) { g_packetReceivedCallback(&sep, recvBuffer, recvLen); } } return CA_STATUS_OK; }
static void CAReceiveHandler(void *data) { OIC_LOG(DEBUG, IP_SERVER_TAG, "IN"); fd_set readFds; int maxSd = 0; struct timeval timeout; char recvBuffer[COAP_MAX_PDU_SIZE] = { 0 }; while (true != g_packetHandlerStopFlag) { timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&readFds); ca_mutex_lock(g_mutexServerInfoList); uint32_t listIndex = 0; uint32_t listLength = u_arraylist_length(g_serverInfoList); u_arraylist_t *tempServerInfoList = u_arraylist_create(); if (!tempServerInfoList) { OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed"); ca_mutex_unlock(g_mutexServerInfoList); return; } for (listIndex = 0; listIndex < listLength; listIndex++) { CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex); if (!info) { listIndex++; continue; } int sd = info->socketFd; //if valid socket descriptor then add to read list if (sd > 0) { FD_SET(sd, &readFds); } //highest file descriptor number, need it for the select function if (sd > maxSd) { maxSd = sd; } CAServerInfo_t *newInfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t)); if (!newInfo) { OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed"); CAClearServerInfoList(tempServerInfoList); ca_mutex_unlock(g_mutexServerInfoList); return; } *newInfo = *info; CAResult_t result = u_arraylist_add(tempServerInfoList, (void *) newInfo); if (CA_STATUS_OK != result) { OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!Thread exit"); CAClearServerInfoList(tempServerInfoList); ca_mutex_unlock(g_mutexServerInfoList); return; } } ca_mutex_unlock(g_mutexServerInfoList); int ret = select(maxSd + 1, &readFds, NULL, NULL, &timeout); if (g_packetHandlerStopFlag) { OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Packet receiver handler Stop request received. Thread exited"); CAClearServerInfoList(tempServerInfoList); break; } if (ret < 0) { OIC_LOG_V(FATAL, IP_SERVER_TAG, "select returned error %s", strerror(errno)); CAClearServerInfoList(tempServerInfoList); continue; } listLength = u_arraylist_length(tempServerInfoList); for (listIndex = 0; listIndex < listLength; listIndex++) { CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList, listIndex); if (!info) { continue; } int sd = info->socketFd; if (FD_ISSET(sd , &readFds)) { OIC_LOG_V(ERROR, IP_SERVER_TAG, "data Received server information ip %s, port %d socket %d", info->endpoint.addr, info->endpoint.port, sd); memset(recvBuffer, 0, sizeof(recvBuffer)); struct sockaddr_in srcSockAddress = { 0 }; socklen_t srcAddressLen = sizeof(srcSockAddress); //Reading from socket ssize_t recvLen = recvfrom(sd, recvBuffer, sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress, &srcAddressLen); if (-1 == recvLen) { OIC_LOG_V(ERROR, IP_SERVER_TAG, "Recvfrom failed %s", strerror(errno)); continue; } else if (0 == recvLen) { OIC_LOG_V(ERROR, IP_SERVER_TAG, "Server socket shutdown sock fd[%d]", sd); ca_mutex_lock(g_mutexAdapterServerContext); // Notify upper layer this exception if (g_adapterIPServerContext->exceptionCallback) { // need to make proper exception callback. //g_adapterIPServerContext->exceptionCallback(ctx->type); } ca_mutex_unlock(g_mutexAdapterServerContext); } char srcIPAddress[CA_IPADDR_SIZE] = { 0 }; if (!inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress, sizeof(srcIPAddress))) { OIC_LOG(ERROR, IP_SERVER_TAG, "inet_ntop is failed!"); continue; } uint16_t srcPort = ntohs(srcSockAddress.sin_port); OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Received packet from %s:%d len %d", srcIPAddress, srcPort, recvLen); char *netMask = NULL; if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(info->ifAddr, &netMask)) { OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet"); continue; } if (!CAAdapterIsSameSubnet(info->ifAddr, srcIPAddress, netMask)) { OIC_LOG(DEBUG, IP_SERVER_TAG, "Packet received from different subnet, Ignore!"); OICFree(netMask); continue; } OICFree(netMask); CAEndpoint_t ep; strncpy(ep.addr, srcIPAddress, MAX_ADDR_STR_SIZE_CA); ep.port = srcPort; ep.flags = (CATransportFlags_t)CA_IPV4 | CA_IPV6; ep.adapter = CA_ADAPTER_IP; if (info->endpoint.flags & CA_SECURE) { #ifdef __WITH_DTLS__ ep.flags |= CA_SECURE; (void)CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen); OIC_LOG_V(DEBUG, IP_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret); #endif } else //both multicast and unicast { ca_mutex_lock(g_mutexAdapterServerContext); if (g_adapterIPServerContext->packetReceivedCallback) { g_adapterIPServerContext->packetReceivedCallback(&ep, recvBuffer, recvLen); } ca_mutex_unlock(g_mutexAdapterServerContext); } } } CAClearServerInfoList(tempServerInfoList); } OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT"); }