From 1fc84b9637c898dadf20bc6ae85167b2d2c3b599 Mon Sep 17 00:00:00 2001 From: "koushik.girijala" Date: Wed, 19 Aug 2015 17:07:21 +0530 Subject: [PATCH] [CA] Patch to make Tizen IP work on 0.9.2 branch for RC3 tag Patch to make Tizen IP work on 0.9.2 branch for RC3 tag Change-Id: Iff3a06456c8d51d3a302d06d31ef5b0a7e15bedd Signed-off-by: koushik.girijala --- resource/csdk/connectivity/api/cacommon.h | 15 +- resource/csdk/connectivity/inc/caipinterface.h | 36 +++ .../csdk/connectivity/src/ip_adapter/caipadapter.c | 7 +- .../csdk/connectivity/src/ip_adapter/caipserver.c | 38 +++- .../src/ip_adapter/tizen/caipnwmonitor.c | 241 ++++++++++++++++++--- 5 files changed, 289 insertions(+), 48 deletions(-) diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h index 00dac16..2f18e56 100644 --- a/resource/csdk/connectivity/api/cacommon.h +++ b/resource/csdk/connectivity/api/cacommon.h @@ -388,6 +388,11 @@ typedef struct typedef struct { + int32_t ifindex; +} CAIfItem_t; + +typedef struct +{ CATransportFlags_t clientFlags; CATransportFlags_t serverFlags; bool client; @@ -413,12 +418,18 @@ typedef struct bool terminate; // the IP adapter needs to stop bool ipv6enabled; // IPv6 enabled by OCInit flags bool ipv4enabled; // IPv4 enabled by OCInit flags + + struct networkmonitors + { + CAIfItem_t *ifitems;// current network interface index list + int numifitems; // number of current network interfaces + } nm; } ip; struct calayer { - CATransportFlags_t previousRequestFlags; // address family filtering - uint16_t previousRequestMessageId; // address family filtering + CATransportFlags_t previousRequestFlags;/**< address family filtering */ + uint16_t previousRequestMessageId; /**< address family filtering */ } ca; } CAGlobals_t; diff --git a/resource/csdk/connectivity/inc/caipinterface.h b/resource/csdk/connectivity/inc/caipinterface.h index a7afbd9..6737ff6 100644 --- a/resource/csdk/connectivity/inc/caipinterface.h +++ b/resource/csdk/connectivity/inc/caipinterface.h @@ -186,6 +186,42 @@ typedef struct u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex); /** + * @brief Find a new network interface + * + * @return Description of interface (or NULL if no change) + */ +CAInterface_t *CAFindInterfaceChange(); + +/** + * @brief Let the network monitor update the polling interval + * @param current polling interval + * + * @return desired polling interval + */ +int CAGetPollingInterval(int interval); + +/** + * @brief Tell the IP server an interface has been added + */ +void CAWakeUpForChange(); + +#ifdef __TIZEN__ +/** + * Initializes tizen network monitor. + * + * @return CA_STATUS_OK or Appropriate error code + */ +CAResult_t CAIPInitializeNetworkMonitor(); + +/** + * terminates tizen network monitor. + * + * @return CA_STATUS_OK or Appropriate error code + */ +CAResult_t CAIPTerminateNetworkMonitor(); +#endif + +/** * @brief Set callback for error handling * * @param ipErrorCallback [IN] callback to notify error to the ipadapter diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 3a320bd..f387139 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c @@ -303,6 +303,9 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, CAResult_t CAStartIP() { OIC_LOG(DEBUG, TAG, "IN"); +#ifdef __TIZEN__ + CAIPInitializeNetworkMonitor(); +#endif #ifdef SINGLE_THREAD uint16_t unicastPort = 55555; @@ -429,7 +432,9 @@ CAResult_t CAStopIP() CAIPDeinitializeQueueHandles(); #endif - +#ifdef __TIZEN__ + CAIPTerminateNetworkMonitor(); +#endif CAIPStopServer(); OIC_LOG(DEBUG, TAG, "OUT"); diff --git a/resource/csdk/connectivity/src/ip_adapter/caipserver.c b/resource/csdk/connectivity/src/ip_adapter/caipserver.c index 2818bc0..8f6d1f1 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipserver.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipserver.c @@ -20,13 +20,6 @@ #include "caipinterface.h" -#ifndef __APPLE__ -#include -#else - #ifndef IPV6_ADD_MEMBERSHIP - #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP - #endif -#endif #include #include #include @@ -106,6 +99,7 @@ static void CAHandleNetlink(); static void CAApplyInterfaces(); static void CAFindReadyMessage(); static void CASelectReturned(fd_set *readFds, int ret); +static void CAProcessNewInterface(CAInterface_t *ifchanged); static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags); #define SET(TYPE, FDS) \ @@ -201,6 +195,11 @@ static void CASelectReturned(fd_set *readFds, int ret) } else { + CAInterface_t *ifchanged = CAFindInterfaceChange(); + if (ifchanged) + { + CAProcessNewInterface(ifchanged); + } break; } @@ -468,6 +467,8 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool) // create source of network interface change notifications CAInitializeNetlink(); + caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout); + CAApplyInterfaces(); caglobals.ip.terminate = false; @@ -502,6 +503,14 @@ void CAIPStopServer() OIC_LOG(DEBUG, TAG, "OUT"); } +void CAWakeUpForChange() +{ + if (caglobals.ip.shutdownFds[1] != -1) + { + write(caglobals.ip.shutdownFds[1], "w", 1); + } +} + static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) @@ -532,7 +541,7 @@ static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) struct ipv6_mreq mreq; mreq.ipv6mr_multiaddr = *addr; mreq.ipv6mr_interface = interface; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) + if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { @@ -600,6 +609,14 @@ static void CAApplyInterfaces() u_arraylist_destroy(iflist); } +static void CAProcessNewInterface(CAInterface_t *ifitem) +{ + applyMulticastToInterface6(ifitem->index); + struct in_addr inaddr; + inaddr.s_addr = ifitem->ipv4addr; + applyMulticastToInterface4(inaddr); +} + static void CAHandleNetlink() { #ifdef __linux__ @@ -638,10 +655,7 @@ for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) continue; } - applyMulticastToInterface6(newIndex); - struct in_addr inaddr; - inaddr.s_addr = ifitem->ipv4addr; - applyMulticastToInterface4(inaddr); + CAProcessNewInterface(ifitem); break; // we found the one we were looking for } u_arraylist_destroy(iflist); diff --git a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c index 90e200f..6b80e61 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,6 +37,89 @@ #include "oic_string.h" #define TAG "IP_MONITOR" +#define MAX_INTERFACE_INFO_LENGTH (1024) + +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) +{ + return interval; +} + +CAInterface_t *CAFindInterfaceChange() +{ + return NULL; +} + +CAResult_t CAIPInitializeNetworkMonitor() +{ + 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 CAIPTerminateNetworkMonitor() +{ + 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) { @@ -45,66 +130,156 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) return NULL; } - struct ifaddrs *ifp = NULL; - if (-1 == getifaddrs(&ifp)) + char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; + struct ifconf ifc; + ifc.ifc_len = MAX_INTERFACE_INFO_LENGTH; + ifc.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 get ifaddrs: %s", strerror(errno)); + OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } - struct ifaddrs *ifa = NULL; - for (ifa = ifp; ifa; ifa = ifa->ifa_next) + struct ifreq* ifr = ifc.ifc_req; + int32_t interfaces = ifc.ifc_len / sizeof (struct ifreq); + + if (interfaces > caglobals.ip.nm.numifitems) { - int family = ifa->ifa_addr->sa_family; - if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family)) + int ifreqsiz = interfaces * sizeof (struct ifreq); + caglobals.ip.nm.numifitems = interfaces; + caglobals.ip.nm.ifitems = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifitems, ifreqsiz); + } + + for (int 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; } - - int ifindex = if_nametoindex(ifa->ifa_name); - int length = u_arraylist_length(iflist); - int already = false; - for (int i = length-1; i >= 0; i--) + int16_t flags = item->ifr_flags; + if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) { - CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); - if (ifitem->index == ifindex && ifitem->family == family) - { - already = true; - break; - } + continue; + } + if (ioctl(s, SIOCGIFINDEX, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); + continue; } - if (already) + int ifindex = item->ifr_ifindex; + if (desiredIndex && (ifindex != desiredIndex)) { continue; } + caglobals.ip.nm.ifitems[i].ifindex = ifindex; - CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t)); - if (!ifitem) + // Add IPv4 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); + if (CA_STATUS_OK != result) { - 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; - - CAResult_t result = u_arraylist_add(iflist, ifitem); + // Add IPv6 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; } } - - freeifaddrs(ifp); 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; + } + CAResult_t result = u_arraylist_add(iflist, ifitem); + if (CA_STATUS_OK != 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 is connected, then get the latest IP from the WIFI Interface + if (WIFI_CONNECTION_STATE_CONNECTED == state) + { + CAWakeUpForChange(); + } + else + { + // TODO : Remove Ip intercase case + } + + 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"); +} -- 2.7.4