X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fip_adapter%2Ftizen%2Fcaipnwmonitor.c;h=88427f3b8ebbb579dd9ecd1c0a5d182b044c4742;hb=17c68b2fd1e74586f85e552eeab4e32dc121f8a0;hp=90e200fa7681426c12546de25282ba363abda4cb;hpb=8c01dff2c5bc5496f7dc1632c498943ec6ecb015;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c index 90e200f..88427f3 100644 --- a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "caadapterutils.h" #include "logger.h" @@ -35,76 +37,356 @@ #include "oic_string.h" #define TAG "IP_MONITOR" +#define MAX_INTERFACE_INFO_LENGTH (1024) -u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) +static CAInterface_t *CANewInterfaceItem(int index, char *name, int family, + uint32_t addr, int flags); + +static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, + char *name, int family, uint32_t addr, int flags); + +static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, + void *userData); + +static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData); + + +int CAGetPollingInterval(int interval) { - u_arraylist_t *iflist = u_arraylist_create(); - if (!iflist) + return interval; +} + +CAInterface_t *CAFindInterfaceChange() +{ + char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; + struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; + + int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); return NULL; } - struct ifaddrs *ifp = NULL; - if (-1 == getifaddrs(&ifp)) + CAInterface_t *foundNewInterface = NULL; + + struct ifreq* ifr = ifc.ifc_req; + size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); + size_t ifreqsize = ifc.ifc_len; + + CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize); + if (!previous) { - OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); - u_arraylist_destroy(iflist); + OIC_LOG(ERROR, TAG, "OICMalloc failed"); return NULL; } - struct ifaddrs *ifa = NULL; - for (ifa = ifp; ifa; ifa = ifa->ifa_next) + memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize); + size_t numprevious = caglobals.ip.nm.numIfItems; + + if (ifreqsize > caglobals.ip.nm.sizeIfItems) + { + + CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); + if (!items) + { + OIC_LOG(ERROR, TAG, "OICRealloc failed"); + OICFree(previous); + return NULL; + } + caglobals.ip.nm.ifItems = items; + caglobals.ip.nm.sizeIfItems = ifreqsize; + } + + caglobals.ip.nm.numIfItems = 0; + for (size_t i = 0; i < interfaces; i++) { - int family = ifa->ifa_addr->sa_family; - if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) + struct ifreq* item = &ifr[i]; + char *name = item->ifr_name; + struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; + uint32_t ipv4addr = sa4->sin_addr.s_addr; + + if (ioctl(s, SIOCGIFFLAGS, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); + continue; + } + int16_t flags = item->ifr_flags; + if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) { continue; } + if (ioctl(s, SIOCGIFINDEX, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); + continue; + } - int ifindex = if_nametoindex(ifa->ifa_name); - int length = u_arraylist_length(iflist); - int already = false; - for (int i = length-1; i >= 0; i--) + int ifIndex = item->ifr_ifindex; + caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list + caglobals.ip.nm.numIfItems++; + + if (foundNewInterface) { - CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); - if (ifitem->index == ifindex && ifitem->family == family) + continue; // continue updating interface list + } + + // see if this interface didn't previously exist + bool found = false; + for (size_t j = 0; j < numprevious; j++) + { + if (ifIndex == previous[j].ifIndex) { - already = true; + found = true; break; } } - if (already) + if (found) { + OIC_LOG_V(INFO, TAG, "Interface found: %s", name); continue; } - CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); - if (!ifitem) + foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags); + } + + OICFree(previous); + return foundNewInterface; +} + +CAResult_t CAIPStartNetworkMonitor() +{ + OIC_LOG(DEBUG, TAG, "IN"); + + // Initialize Wifi service + wifi_error_e ret = wifi_initialize(); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_initialize failed"); + return CA_STATUS_FAILED; + } + + // Set callback for receiving state changes + ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed"); + return CA_STATUS_FAILED; + } + + // Set callback for receiving connection state changes + ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed"); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +CAResult_t CAIPStopNetworkMonitor() +{ + OIC_LOG(DEBUG, TAG, "IN"); + + // Reset callback for receiving state changes + wifi_error_e ret = wifi_unset_device_state_changed_cb(); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed"); + } + + // Reset callback for receiving connection state changes + ret = wifi_unset_connection_state_changed_cb(); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb failed"); + } + + // Deinitialize Wifi service + ret = wifi_deinitialize(); + if (WIFI_ERROR_NONE != ret) + { + OIC_LOG(ERROR, TAG, "wifi_deinitialize failed"); + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) +{ + u_arraylist_t *iflist = u_arraylist_create(); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno)); + return NULL; + } + + char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; + struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; + + int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); + u_arraylist_destroy(iflist); + return NULL; + } + + struct ifreq* ifr = ifc.ifc_req; + size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); + size_t ifreqsize = ifc.ifc_len; + + if (ifreqsize > caglobals.ip.nm.sizeIfItems) + { + CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); + if (!items) { - OIC_LOG(ERROR, TAG, "Malloc failed"); + OIC_LOG(ERROR, TAG, "OICRealloc failed"); goto exit; } + caglobals.ip.nm.ifItems = items; + caglobals.ip.nm.sizeIfItems = ifreqsize; + } + + caglobals.ip.nm.numIfItems = 0; + for (size_t i = 0; i < interfaces; i++) + { + CAResult_t result = CA_STATUS_OK; + struct ifreq* item = &ifr[i]; + char *name = item->ifr_name; + struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; + uint32_t ipv4addr = sa4->sin_addr.s_addr; + + if (ioctl(s, SIOCGIFFLAGS, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); + continue; + } + int16_t flags = item->ifr_flags; + if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) + { + continue; + } + if (ioctl(s, SIOCGIFINDEX, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); + continue; + } - 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; + int ifindex = item->ifr_ifindex; + caglobals.ip.nm.ifItems[i].ifIndex = ifindex; + caglobals.ip.nm.numIfItems++; - CAResult_t result = u_arraylist_add(iflist, ifitem); + if (desiredIndex && (ifindex != desiredIndex)) + { + continue; + } + + // Add IPv4 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } - } - freeifaddrs(ifp); + // Add IPv6 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); + if (CA_STATUS_OK != result) + { + goto exit; + } + } return iflist; exit: - freeifaddrs(ifp); u_arraylist_destroy(iflist); return NULL; } + +static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, + char *name, int family, uint32_t addr, int flags) +{ + CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags); + if (!ifitem) + { + return CA_STATUS_FAILED; + } + bool result = u_arraylist_add(iflist, ifitem); + if (!result) + { + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + OICFree(ifitem); + return CA_STATUS_FAILED; + } + + return CA_STATUS_OK; +} + +static CAInterface_t *CANewInterfaceItem(int index, char *name, int family, + uint32_t addr, int flags) +{ + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t)); + if (!ifitem) + { + OIC_LOG(ERROR, TAG, "Malloc failed"); + return NULL; + } + + OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name); + ifitem->index = index; + ifitem->family = family; + ifitem->ipv4addr = addr; + ifitem->flags = flags; + + return ifitem; +} + +void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, + void *userData) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + if (WIFI_CONNECTION_STATE_ASSOCIATION == state + || WIFI_CONNECTION_STATE_CONFIGURATION == state) + { + OIC_LOG(DEBUG, TAG, "Connection is in Association State"); + return; + } + + if (WIFI_CONNECTION_STATE_CONNECTED == state) + { + CAWakeUpForChange(); + } + else + { + u_arraylist_t *iflist = CAIPGetInterfaceInformation(0); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "get interface info failed"); + return; + } + u_arraylist_destroy(iflist); + } + + OIC_LOG(DEBUG, TAG, "OUT"); +} + +void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + if (WIFI_DEVICE_STATE_ACTIVATED == state) + { + OIC_LOG(DEBUG, TAG, "Wifi is in Activated State"); + } + else + { + CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL); + OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State"); + } + + OIC_LOG(DEBUG, TAG, "OUT"); +}