CAResult_t CAStopListeningServerAdapters() { OIC_LOG(DEBUG, TAG, "IN"); u_arraylist_t *list = CAGetSelectedNetworkList(); if (!list) { OIC_LOG(ERROR, TAG, "No selected network"); return CA_STATUS_FAILED; } for (uint32_t i = 0; i < u_arraylist_length(list); i++) { void* ptrType = u_arraylist_get(list, i); if(ptrType == NULL) { continue; } CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType; int index = CAGetAdapterIndex(connType); if (index == -1) { OIC_LOG(ERROR, TAG, "unknown connectivity type!"); continue; } if (g_adapterHandler[index].stopListenServer != NULL) { g_adapterHandler[index].stopListenServer(); } } OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
void CAEDRNativeRemoveDevice(const char *remoteAddress) { OIC_LOG(DEBUG, TAG, "CAEDRNativeRemoveDeviceforStateList"); if (!g_deviceStateList) { OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null"); return; } if (!remoteAddress) { OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null"); return; } jint index; jint length = u_arraylist_length(g_deviceStateList); for (index = 0; index < length; index++) { state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); if (!state) { OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null"); continue; } if (!strcmp((const char*) state->address, remoteAddress)) { OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove state : %s", remoteAddress); OICFree(state); u_arraylist_remove(g_deviceStateList, index); break; } } return; }
static void CAClearCacheList() { OIC_LOG(DEBUG, NET_DTLS_TAG, "IN"); uint32_t list_index = 0; uint32_t list_length = 0; if (NULL == g_caDtlsContext) { OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL"); return; } list_length = u_arraylist_length(g_caDtlsContext->cacheList); for (list_index = 0; list_index < list_length; list_index++) { stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList, list_index); if (msg != NULL) { CAFreeCacheMsg(msg); } } u_arraylist_free(&g_caDtlsContext->cacheList); g_caDtlsContext->cacheList = NULL; OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT"); }
static void sendMulticastData4(const u_arraylist_t *iflist, CAEndpoint_t *endpoint, const void *data, uint32_t datalen) { struct ip_mreq mreq = { .imr_multiaddr = IPv4MulticastAddress }; OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST); int fd = caglobals.ip.u4.fd; uint32_t len = u_arraylist_length(iflist); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family != AF_INET) { continue; } struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; mreq.imr_interface = inaddr; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq))) { OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)", strerror(errno)); } sendData(fd, endpoint, data, datalen, "multicast", "ipv4"); } }
CAResult_t CAReadData() { u_arraylist_t *list = CAGetSelectedNetworkList(); if (!list) { return CA_STATUS_FAILED; } uint8_t i = 0; for (i = 0; i < u_arraylist_length(list); i++) { void *ptrType = u_arraylist_get(list, i); if (NULL == ptrType) { OIC_LOG(ERROR, TAG, "get list fail"); return CA_STATUS_FAILED; } CATransportAdapter_t connType = *(CATransportAdapter_t *) ptrType; int index = CAGetAdapterIndex(connType); if (0 > index) { OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); continue; } if (g_adapterHandler[index].readData != NULL) { g_adapterHandler[index].readData(); } } return CA_STATUS_OK; }
CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress) { OIC_LOG(DEBUG, TAG, "CAEDRIsConnectedDevice"); if (!remoteAddress) { OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null"); return STATE_DISCONNECTED; } if (!g_deviceStateList) { OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceStateList is null"); return STATE_DISCONNECTED; } jint index; jint length = u_arraylist_length(g_deviceStateList); for (index = 0; index < length; index++) { state_t* state = (state_t*) u_arraylist_get(g_deviceStateList, index); if (!state) { OIC_LOG(DEBUG, TAG, "[EDR][Native] state_t object is null"); continue; } if (!strcmp((const char*) state->address, remoteAddress)) { OIC_LOG(DEBUG, TAG, "[EDR][Native] check whether it is connected or not"); return state->state; } } return STATE_DISCONNECTED; }
void ca_thread_pool_free(ca_thread_pool_t thread_pool) { OIC_LOG(DEBUG, TAG, "IN"); if(!thread_pool) { OIC_LOG(ERROR, TAG, "Invalid parameter thread_pool was NULL"); return; } ca_mutex_lock(thread_pool->details->list_lock); for(uint32_t i = 0; i<u_arraylist_length(thread_pool->details->threads_list); ++i) { pthread_t tid = (pthread_t)u_arraylist_get(thread_pool->details->threads_list, i); int joinres = pthread_join(tid, NULL); if(0 != joinres) { OIC_LOG_V(ERROR, TAG, "Failed to join thread at index %u with error %d", i, joinres); } } CAResult_t freeres = u_arraylist_free(&(thread_pool->details->threads_list)); if(CA_STATUS_OK != freeres) { OIC_LOG_V(ERROR, TAG, "Failed to free array list, error was: %d", freeres); } ca_mutex_unlock(thread_pool->details->list_lock); ca_mutex_free(thread_pool->details->list_lock); OICFree(thread_pool->details); OICFree(thread_pool); OIC_LOG(DEBUG, TAG, "OUT"); }
jobject CAEDRNativeGetDeviceSocket(uint32_t idx) { OIC_LOG(DEBUG, TAG, "CAEDRNativeGetDeviceSocket"); if(idx < 0) { OIC_LOG(DEBUG, TAG, "[EDR][Native] index is not available"); return NULL; } if(!g_deviceObjectList) { OIC_LOG(ERROR, TAG, "[EDR][Native] gdeviceObjectList is null"); return NULL; } jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, idx); if(!jarrayObj) { OIC_LOG(ERROR, TAG, "[EDR][Native] jarrayObj is not available"); return NULL; } return jarrayObj; }
CAResult_t CARemoveNetworkType(CATransportAdapter_t transportType) { OIC_LOG(DEBUG, TAG, "IN"); if (NULL == g_selectedNetworkList) { OIC_LOG(ERROR, TAG, "SelectedNetwork list is NULL"); return CA_STATUS_FAILED; } uint32_t selectedNetworkLength = u_arraylist_length(g_selectedNetworkList); for (uint32_t index = 0; index < selectedNetworkLength; index++) { void* ptrType = u_arraylist_get(g_selectedNetworkList, index); if (NULL == ptrType) { continue; } CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType; if (transportType == connType) { switch (transportType) { case CA_ADAPTER_IP: #ifndef IP_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(IP) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(IP)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* IP_ADAPTER */ break; case CA_ADAPTER_RFCOMM_BTEDR: #ifndef EDR_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(EDR) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(EDR)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* EDR_ADAPTER */ break; case CA_ADAPTER_GATT_BTLE: #ifndef LE_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(LE) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(LE)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* LE_ADAPTER */ break; default: break; } // stop selected interface adapter CAStopAdapter(connType); return CA_STATUS_OK; } } return CA_STATUS_FAILED; }
CAInterface_t *CAFindInterfaceChange() { CAInterface_t *foundNewInterface = NULL; #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); int ifiIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(ifiIndex); if ((!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))) { bool isFound = CACmpNetworkList(ifiIndex); if (isFound) { CARemoveNetworkMonitorList(ifiIndex); if (g_networkChangeCallback) { g_networkChangeCallback(CA_ADAPTER_IP ,CA_INTERFACE_DOWN); } } continue; } if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return NULL; } uint32_t listLength = u_arraylist_length(iflist); for (uint32_t i = 0; i < listLength; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((int)ifitem->index != ifiIndex) { continue; } foundNewInterface = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family, ifitem->ipv4addr, ifitem->flags); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif return foundNewInterface; }
void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus) { OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN"); ca_mutex_lock(g_stopNetworkMonitorMutex); if (g_stopNetworkMonitor) { OIC_LOG(DEBUG, IP_MONITOR_TAG, "Stop Network Monitor Thread is called"); ca_mutex_unlock(g_stopNetworkMonitorMutex); return; } ca_mutex_unlock(g_stopNetworkMonitorMutex); ca_mutex_lock(g_networkMonitorContextMutex); if (!g_networkMonitorContext) { OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is NULL"); ca_mutex_unlock(g_networkMonitorContextMutex); return; } if (!g_networkMonitorContext->networkChangeCb) { OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext->networkChangeCb is NULL"); ca_mutex_unlock(g_networkMonitorContextMutex); return; } ca_mutex_unlock(g_networkMonitorContextMutex); u_arraylist_t *netInterfaceList = u_arraylist_create(); VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "memory allocation failed for netInterfaceList"); // if network status is changed CAResult_t ret = CAIPUpdateInterfaceInformation(&netInterfaceList); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, IP_MONITOR_TAG, "could not update interface information"); } ca_mutex_lock(g_networkMonitorContextMutex); if (!g_networkMonitorContext->netInterfaceList) { OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed. Network Monitor thread stopped"); CAClearNetInterfaceInfoList(netInterfaceList); ca_mutex_unlock(g_networkMonitorContextMutex); return; } uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList); for (uint32_t listIndex = 0; listIndex < listLength;) { CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get( g_networkMonitorContext->netInterfaceList, listIndex); if (!info) { listIndex++; continue; } bool ret = CACheckIsAnyInterfaceDown(netInterfaceList, info); if (ret) { OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down"); if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, listIndex)) { OIC_LOG(DEBUG, IP_MONITOR_TAG, "u_arraylist_remove success"); if (g_networkMonitorContext->networkChangeCb) { g_networkMonitorContext->networkChangeCb(info->ipAddress, CA_INTERFACE_DOWN); } OICFree(info); listLength--; } else { OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); break; } } else { listIndex++; } } ca_mutex_unlock(g_networkMonitorContextMutex); listLength = u_arraylist_length(netInterfaceList); for (uint32_t listIndex = 0; listIndex < listLength; listIndex++) { CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex); if (!info) { continue; } bool ret = CACheckIsInterfaceInfoChanged(info); if (ret) { OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true"); } } CAClearNetInterfaceInfoList(netInterfaceList); OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT"); }
void ProcessKeepAlive() { if (!g_isKeepAliveInitialized) { OIC_LOG(ERROR, TAG, "KeepAlive not initialized"); return; } uint32_t len = u_arraylist_length(g_keepAliveConnectionTable); for (uint32_t i = 0; i < len; i++) { KeepAliveEntry_t *entry = (KeepAliveEntry_t *)u_arraylist_get(g_keepAliveConnectionTable, i); if (NULL == entry) { continue; } uint64_t currentTime = OICGetCurrentTime(TIME_IN_US); if (OC_CLIENT == entry->mode) { if (entry->sentPingMsg) { /* * If an OIC Client does not receive the response within 1 minutes, * terminate the connection. * In this case the timeStamp means last time sent ping message. */ if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp) { OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes."); // Send message to disconnect session. SendDisconnectMessage(entry); } } else { if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp) { // Increase interval value. IncreaseInterval(entry); OCStackResult result = SendPingMessage(entry); if (OC_STACK_OK != result) { OIC_LOG(ERROR, TAG, "Failed to send ping request"); continue; } } } } else if (OC_SERVER == entry->mode) { /* * If an OIC Server does not receive a PUT request to ping resource * within the specified interval time, terminate the connection. * In this case the timeStamp means last time received ping message. */ if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp) { OIC_LOG(DEBUG, TAG, "Server does not receive a PUT request."); SendDisconnectMessage(entry); } } } }
static void CAFindReadyMessage() { fd_set readFds; struct timeval timeout = { .tv_sec = caglobals.tcp.selectTimeout }; FD_ZERO(&readFds); if (-1 != g_acceptServerFD) { FD_SET(g_acceptServerFD, &readFds); } if (-1 != caglobals.tcp.shutdownFds[0]) { FD_SET(caglobals.tcp.shutdownFds[0], &readFds); } if (-1 != caglobals.tcp.connectionFds[0]) { FD_SET(caglobals.tcp.connectionFds[0], &readFds); } uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); for (size_t i = 0; i < length; i++) { CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem && 0 <= svritem->fd) { FD_SET(svritem->fd, &readFds); } } int ret = select(caglobals.tcp.maxfd + 1, &readFds, NULL, NULL, &timeout); if (caglobals.tcp.terminate) { OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received."); return; } if (0 >= ret) { if (0 > ret) { OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno)); } return; } CASelectReturned(&readFds, ret); } static void CASelectReturned(fd_set *readFds, int ret) { (void)ret; if (g_acceptServerFD != -1 && FD_ISSET(g_acceptServerFD, readFds)) { CAAcceptConnection(); return; } else if (-1 != caglobals.tcp.connectionFds[0] && FD_ISSET(caglobals.tcp.connectionFds[0], readFds)) { // new connection was created from remote device. // exit the function to update read file descriptor. char buf[MAX_ADDR_STR_SIZE_CA] = {0}; ssize_t len = read(caglobals.tcp.connectionFds[0], buf, sizeof (buf)); if (-1 == len) { return; } OIC_LOG_V(DEBUG, TAG, "Received new connection event with [%s]", buf); FD_CLR(caglobals.tcp.connectionFds[0], readFds); return; } else { uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); for (size_t i = 0; i < length; i++) { CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem && svritem->fd >= 0) { if (FD_ISSET(svritem->fd, readFds)) { CAReceiveMessage(svritem->fd); FD_CLR(svritem->fd, readFds); } } } } }
CAResult_t CARemoveNetworkType(CAConnectivityType_t connectivityType) { OIC_LOG(DEBUG, TAG, "IN"); if (g_selectedNetworkList == NULL) { OIC_LOG(DEBUG, TAG, "Selected network not found"); return CA_STATUS_FAILED; } uint8_t index; for (index = 0; index < u_arraylist_length(g_selectedNetworkList); index++) { void* ptrType = u_arraylist_get(g_selectedNetworkList, index); if (NULL == ptrType) { continue; } CAConnectivityType_t connType = *(CAConnectivityType_t *) ptrType; if (connectivityType == connType) { switch (connectivityType) { case CA_ETHERNET: #ifndef ETHERNET_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(ETHERNET) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(ETHERNET)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* ETHERNET_ADAPTER */ break; case CA_WIFI: #ifndef WIFI_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(WIFI) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(WIFI)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* WIFI_ADAPTER */ break; case CA_EDR: #ifndef EDR_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(EDR) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(EDR)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* EDR_ADAPTER */ break; case CA_LE: #ifndef LE_ADAPTER OIC_LOG(DEBUG, TAG, "Remove network type(LE) - Not Supported"); return CA_NOT_SUPPORTED; #else OIC_LOG(DEBUG, TAG, "Remove network type(LE)"); u_arraylist_remove(g_selectedNetworkList, index); #endif /* LE_ADAPTER */ break; } // stop selected interface adapter CAStopAdapter(connType); } } return CA_STATUS_OK; }
CAResult_t CAManagerRemoveData(JNIEnv *env, jstring jaddress) { OIC_LOG(DEBUG, TAG, "IN-CAManagerRemoveData"); VERIFY_NON_NULL(env, TAG, "env"); VERIFY_NON_NULL(jaddress, TAG, "jaddress"); ca_mutex_lock(g_deviceACDataListMutex); const char* address = (*env)->GetStringUTFChars(env, jaddress, NULL); if (!address) { OIC_LOG(ERROR, TAG, "address is null"); ca_mutex_unlock(g_deviceACDataListMutex); return CA_STATUS_FAILED; } OIC_LOG_V(DEBUG, TAG, "(%s) will be removed", address); size_t length = u_arraylist_length(g_deviceACDataList); for (size_t idx = 0; idx < length; idx++) { CAManagerACData_t *curData = (CAManagerACData_t *) u_arraylist_get(g_deviceACDataList, idx); if (!curData) { OIC_LOG(ERROR, TAG, "curData is null"); (*env)->ReleaseStringUTFChars(env, jaddress, address); ca_mutex_unlock(g_deviceACDataListMutex); return CA_STATUS_FAILED; } const char* setAddress = (*env)->GetStringUTFChars(env, curData->address, NULL); if (!setAddress) { OIC_LOG(ERROR, TAG, "address is null"); (*env)->ReleaseStringUTFChars(env, jaddress, address); ca_mutex_unlock(g_deviceACDataListMutex); return CA_STATUS_FAILED; } if (!strcmp(setAddress, address)) { if (NULL == u_arraylist_remove(g_deviceACDataList, idx)) { OIC_LOG(ERROR, TAG, "removal has failed."); (*env)->ReleaseStringUTFChars(env, jaddress, address); (*env)->ReleaseStringUTFChars(env, curData->address, setAddress); ca_mutex_unlock(g_deviceACDataListMutex); return CA_STATUS_FAILED; } (*env)->ReleaseStringUTFChars(env, curData->address, setAddress); if (curData->address) { (*env)->DeleteGlobalRef(env, curData->address); } OICFree(curData); (*env)->ReleaseStringUTFChars(env, jaddress, address); ca_mutex_unlock(g_deviceACDataListMutex); OIC_LOG(DEBUG, TAG, "remove done"); return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, curData->address, setAddress); } (*env)->ReleaseStringUTFChars(env, jaddress, address); ca_mutex_unlock(g_deviceACDataListMutex); OIC_LOG(DEBUG, TAG, "OUT-CAManagerRemoveData"); return CA_STATUS_OK; }
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); }
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { if (desiredIndex < 0) { OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex); return NULL; } u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); return NULL; } struct ifaddrs *ifp = NULL; if (-1 == getifaddrs(&ifp)) { OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } OIC_LOG(DEBUG, TAG, "Got ifaddrs"); struct ifaddrs *ifa = NULL; for (ifa = ifp; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) { continue; } int family = ifa->ifa_addr->sa_family; if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) { continue; } int ifindex = if_nametoindex(ifa->ifa_name); if (desiredIndex && (ifindex != desiredIndex)) { continue; } int length = u_arraylist_length(iflist); int already = false; for (int i = length-1; i >= 0; i--) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (ifitem && (int)ifitem->index == ifindex && ifitem->family == (uint16_t)family) { already = true; break; } } if (already) { continue; } CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); if (!ifitem) { OIC_LOG(ERROR, TAG, "Malloc failed"); goto exit; } OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name); ifitem->index = ifindex; ifitem->family = family; ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; ifitem->flags = ifa->ifa_flags; bool result = u_arraylist_add(iflist, ifitem); if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, family); } freeifaddrs(ifp); return iflist; exit: freeifaddrs(ifp); u_arraylist_destroy(iflist); return NULL; }
static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) { return; } struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress, .imr_address = inaddr, .imr_ifindex = 0 }; if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) { struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface}; if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticastToInterface6(uint32_t interface) { if (!caglobals.ip.ipv6enabled) { return; } //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface); } CAResult_t CAIPStartListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; applyMulticastToInterface4(inaddr); OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name); } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } CAResult_t CAIPStopListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { close(caglobals.ip.m4.fd); close(caglobals.ip.m4s.fd); caglobals.ip.m4.fd = -1; caglobals.ip.m4s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name); } if (ifitem->family == AF_INET6) { close(caglobals.ip.m6.fd); close(caglobals.ip.m6s.fd); caglobals.ip.m6.fd = -1; caglobals.ip.m6s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } static void CAProcessNewInterface(CAInterface_t *ifitem) { if (!ifitem) { OIC_LOG(DEBUG, TAG, "ifitem is null"); return; } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); } if (ifitem->family == AF_INET) { struct in_addr inaddr = { .s_addr = ifitem->ipv4addr }; applyMulticastToInterface4(inaddr); } } void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) { g_packetReceivedCallback = callback; } void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback) { CAIPSetNetworkMonitorCallback(callback); } static void sendData(int fd, const CAEndpoint_t *endpoint, const void *data, uint32_t dlen, const char *cast, const char *fam) { OIC_LOG(DEBUG, TAG, "IN"); if (!endpoint) { OIC_LOG(DEBUG, TAG, "endpoint is null"); if (g_ipErrorHandler) { g_ipErrorHandler(endpoint, data, dlen, CA_STATUS_INVALID_PARAM); } return; } char *secure = (endpoint->flags & CA_SECURE) ? "secure " : ""; (void)secure; // eliminates release warning struct sockaddr_storage sock; CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock); socklen_t socklen; if (sock.ss_family == AF_INET6) { struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock; if (!sock6->sin6_scope_id) { sock6->sin6_scope_id = endpoint->interface; } socklen = sizeof(struct sockaddr_in6); } else { socklen = sizeof(struct sockaddr_in); } ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen); if (-1 == len) { // If logging is not defined/enabled. (void)cast; (void)fam; if (g_ipErrorHandler) { g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED); } OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno)); } else { OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len); } }
void CATerminateMessageHandler() { #ifndef SINGLE_THREAD CATransportAdapter_t connType; u_arraylist_t *list = CAGetSelectedNetworkList(); uint32_t length = u_arraylist_length(list); uint32_t i = 0; for (i = 0; i < length; i++) { void* ptrType = u_arraylist_get(list, i); if (NULL == ptrType) { continue; } connType = *(CATransportAdapter_t *)ptrType; CAStopAdapter(connType); } // stop retransmission if (NULL != g_retransmissionContext.threadMutex) { CARetransmissionStop(&g_retransmissionContext); } // stop thread // delete thread data if (NULL != g_sendThread.threadMutex) { CAQueueingThreadStop(&g_sendThread); } // stop thread // delete thread data if (NULL != g_receiveThread.threadMutex) { #ifndef SINGLE_HANDLE // This will be enabled when RI supports multi threading CAQueueingThreadStop(&g_receiveThread); #endif /* SINGLE_HANDLE */ } // destroy thread pool if (NULL != g_threadPoolHandle) { ca_thread_pool_free(g_threadPoolHandle); g_threadPoolHandle = NULL; } #ifdef WITH_BWT CATerminateBlockWiseTransfer(); #endif CARetransmissionDestroy(&g_retransmissionContext); CAQueueingThreadDestroy(&g_sendThread); CAQueueingThreadDestroy(&g_receiveThread); // terminate interface adapters by controller CATerminateAdapters(); #else // terminate interface adapters by controller CATerminateAdapters(); // stop retransmission CARetransmissionStop(&g_retransmissionContext); CARetransmissionDestroy(&g_retransmissionContext); #endif }
static void CAFindReadyMessage() { fd_set readFds; struct timeval timeout = { .tv_sec = caglobals.tcp.selectTimeout }; FD_ZERO(&readFds); if (-1 != g_acceptServerFD) { FD_SET(g_acceptServerFD, &readFds); } if (-1 != caglobals.tcp.shutdownFds[0]) { FD_SET(caglobals.tcp.shutdownFds[0], &readFds); } uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); for (size_t i = 0; i < length; i++) { CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem && 0 <= svritem->fd) { FD_SET(svritem->fd, &readFds); } } int ret = select(caglobals.tcp.maxfd + 1, &readFds, NULL, NULL, &timeout); if (caglobals.tcp.terminate) { OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received."); return; } if (0 >= ret) { if (0 > ret) { OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno)); } return; } CASelectReturned(&readFds, ret); } static void CASelectReturned(fd_set *readFds, int ret) { (void)ret; if (g_acceptServerFD != -1 && FD_ISSET(g_acceptServerFD, readFds)) { CAAcceptConnection(); return; } else { uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); for (size_t i = 0; i < length; i++) { CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i); if (svritem && svritem->fd >= 0) { if (FD_ISSET(svritem->fd, readFds)) { CAReceiveMessage(svritem->fd); FD_CLR(svritem->fd, readFds); } } } } }
CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size) { VERIFY_NON_NULL(info, TAG, "info is NULL"); VERIFY_NON_NULL(size, TAG, "size is NULL"); u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); uint32_t length = len; #ifdef __WITH_DTLS__ //If DTLS is supported, each interface can support secure port as well length = len * 2; #endif CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t)); if (!eps) { OIC_LOG(ERROR, TAG, "Malloc Failed"); u_arraylist_destroy(iflist); return CA_MEMORY_ALLOC_FAILED; } for (uint32_t i = 0, j = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if(!ifitem) { continue; } eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; if (ifitem->family == AF_INET6) { eps[j].flags = CA_IPV6; eps[j].port = caglobals.ip.u6.port; } else { eps[j].flags = CA_IPV4; eps[j].port = caglobals.ip.u4.port; inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA); } #ifdef __WITH_DTLS__ j++; eps[j].adapter = CA_ADAPTER_IP; eps[j].interface = 0; if (ifitem->family == AF_INET6) { eps[j].flags = CA_IPV6 | CA_SECURE; eps[j].port = caglobals.ip.u6s.port; } else { eps[j].flags = CA_IPV4 | CA_SECURE; eps[j].port = caglobals.ip.u4s.port; inet_ntop(AF_INET, &(ifitem->ipv4addr), eps[j].addr, MAX_ADDR_STR_SIZE_CA); } #endif j++; } *info = eps; *size = len; u_arraylist_destroy(iflist); 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"); }
static void sendMulticastData4(const u_arraylist_t *iflist, CAEndpoint_t *endpoint, const void *data, uint32_t datalen) { VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress, .imr_ifindex = 0 }; OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST); int fd = caglobals.ip.u4.fd; uint32_t len = u_arraylist_length(iflist); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family != AF_INET) { continue; } struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; mreq.imr_address = inaddr; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq))) { OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)", strerror(errno)); } sendData(fd, endpoint, data, datalen, "multicast", "ipv4"); } } void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen, bool isMulticast) { VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL"); VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); bool isSecure = (endpoint->flags & CA_SECURE) != 0; if (isMulticast) { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled) { sendMulticastData6(iflist, endpoint, data, datalen); } if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled) { sendMulticastData4(iflist, endpoint, data, datalen); } u_arraylist_destroy(iflist); } else { if (!endpoint->port) // unicast discovery { endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP; } int fd; if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6)) { fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u6.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv6"); } if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4)) { fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd; #ifndef __WITH_DTLS__ fd = caglobals.ip.u4.fd; #endif sendData(fd, endpoint, data, datalen, "unicast", "ipv4"); } } }
static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) { return; } struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress, .imr_address = inaddr, .imr_ifindex = 0 }; if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } if (setsockopt(caglobals.ip.m4s.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "secure IPv4 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) { struct ipv6_mreq mreq = {.ipv6mr_multiaddr = *addr, .ipv6mr_interface = interface}; if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno)); } } } static void applyMulticastToInterface6(uint32_t interface) { if (!caglobals.ip.ipv6enabled) { return; } //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, interface); applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, interface); //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, interface); } CAResult_t CAIPStartListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { struct in_addr inaddr; inaddr.s_addr = ifitem->ipv4addr; applyMulticastToInterface4(inaddr); OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name); } if (ifitem->family == AF_INET6) { applyMulticastToInterface6(ifitem->index); OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } CAResult_t CAIPStopListenServer() { u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); if (!iflist) { OIC_LOG_V(ERROR, TAG, "Get interface info failed: %s", strerror(errno)); return CA_STATUS_FAILED; } uint32_t len = u_arraylist_length(iflist); OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len); for (uint32_t i = 0; i < len; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { continue; } if (ifitem->family == AF_INET) { close(caglobals.ip.m4.fd); close(caglobals.ip.m4s.fd); caglobals.ip.m4.fd = -1; caglobals.ip.m4s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s cloed", ifitem->name); } if (ifitem->family == AF_INET6) { close(caglobals.ip.m6.fd); close(caglobals.ip.m6s.fd); caglobals.ip.m6.fd = -1; caglobals.ip.m6s.fd = -1; OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name); } } u_arraylist_destroy(iflist); return CA_STATUS_OK; } static void CAProcessNewInterface(CAInterface_t *ifitem) { if (!ifitem) { OIC_LOG(DEBUG, TAG, "ifitem is null"); return; } applyMulticastToInterface6(ifitem->index); struct in_addr inaddr = { .s_addr = ifitem->ipv4addr }; applyMulticastToInterface4(inaddr); } static void CAHandleNetlink() { #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; struct iovec iov = { buf, sizeof (buf) }; struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type != RTM_NEWLINK) { continue; } struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) { continue; } int newIndex = ifi->ifi_index; u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); if (!iflist) { OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); return; } uint32_t listLength = u_arraylist_length(iflist); for (uint32_t i = 0; i < listLength; i++) { CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); if (!ifitem) { continue; } if ((int)ifitem->index != newIndex) { continue; } CAProcessNewInterface(ifitem); break; // we found the one we were looking for } u_arraylist_destroy(iflist); } #endif // __linux__ } void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) { g_packetReceivedCallback = callback; } void CAIPSetExceptionCallback(CAIPExceptionCallback callback) { g_exceptionCallback = callback; } static void sendData(int fd, const CAEndpoint_t *endpoint, const void *data, uint32_t dlen, const char *cast, const char *fam) { OIC_LOG(DEBUG, TAG, "IN"); if (!endpoint) { OIC_LOG(DEBUG, TAG, "endpoint is null"); return; } char *secure = (endpoint->flags & CA_SECURE) ? "secure " : ""; (void)secure; // eliminates release warning struct sockaddr_storage sock; CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock); socklen_t socklen; if (sock.ss_family == AF_INET6) { struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock; if (!sock6->sin6_scope_id) { sock6->sin6_scope_id = endpoint->interface; } socklen = sizeof(struct sockaddr_in6); } else { socklen = sizeof(struct sockaddr_in); } ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen); if (-1 == len) { // If logging is not defined/enabled. (void)cast; (void)fam; OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno)); } else { OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len); } }
CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length) { OIC_LOG(DEBUG, TAG, "IN"); u_arraylist_t *list = CAGetSelectedNetworkList(); if (!list) { OIC_LOG(DEBUG, TAG, "No selected network"); return CA_SEND_FAILED; } CATransportFlags_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS; for (uint32_t i = 0; i < u_arraylist_length(list); i++) { void* ptrType = u_arraylist_get(list, i); if(ptrType == NULL) { continue; } CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType; if ((connType & requestedAdapter) == 0) { continue; } int index = CAGetAdapterIndex(connType); if (index == -1) { OIC_LOG(DEBUG, TAG, "unknown connectivity type!"); continue; } uint32_t sentDataLen = 0; if (g_adapterHandler[index].sendDataToAll != NULL) { void *payload = (void *) OICMalloc(length); if (!payload) { OIC_LOG(ERROR, TAG, "Out of memory!"); return CA_MEMORY_ALLOC_FAILED; } memcpy(payload, data, length); sentDataLen = g_adapterHandler[index].sendDataToAll(endpoint, payload, length); OICFree(payload); } if (sentDataLen != length) { OIC_LOG(ERROR, TAG, "sendDataToAll failed! Error will be reported from adapter"); #ifdef SINGLE_THREAD //in case of single thread, no error handler. Report error immediately return CA_SEND_FAILED; #endif } } OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; }
static bool CACheckIsInterfaceInfoChanged(const CANetInfo_t *info) { VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false); ca_mutex_lock(g_networkMonitorContextMutex); uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList); for (uint32_t list_index = 0; list_index < list_length; list_index++) { CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get( g_networkMonitorContext->netInterfaceList, list_index); if (!netInfo) { continue; } if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0) { if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0) { ca_mutex_unlock(g_networkMonitorContextMutex); return false; } else { OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network interface info changed"); if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index)) { if (g_networkMonitorContext->networkChangeCb) { g_networkMonitorContext->networkChangeCb(netInfo->ipAddress, CA_INTERFACE_DOWN); } OICFree(netInfo); } else { OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed"); } break; } } } CANetInfo_t *newNetInfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t)); if (!newNetInfo) { OIC_LOG(ERROR, IP_MONITOR_TAG, "newNetInfo malloc failed"); ca_mutex_unlock(g_networkMonitorContextMutex); return false; } *newNetInfo = *info; OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found"); CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList, (void *) newNetInfo); if (CA_STATUS_OK != result) { OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!"); OICFree(newNetInfo); ca_mutex_unlock(g_networkMonitorContextMutex); return false; } ca_mutex_unlock(g_networkMonitorContextMutex); /*Callback will be unset only at the time of termination. By that time, all the threads will be stopped gracefully. This callback is properly protected*/ if (g_networkMonitorContext->networkChangeCb) { g_networkMonitorContext->networkChangeCb(newNetInfo->ipAddress, CA_INTERFACE_UP); } return true; }