[CA] Patch to make Tizen IP work on 0.9.2 branch for RC3 tag
authorkoushik.girijala <g.koushik@samsung.com>
Wed, 19 Aug 2015 11:37:21 +0000 (17:07 +0530)
committerYoungjae Shin <yj99.shin@samsung.com>
Mon, 31 Aug 2015 05:55:02 +0000 (14:55 +0900)
Patch to make Tizen IP work on 0.9.2 branch for RC3 tag

Change-Id: Iff3a06456c8d51d3a302d06d31ef5b0a7e15bedd
Signed-off-by: koushik.girijala <g.koushik@samsung.com>
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/inc/caipinterface.h
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c

index 00dac16..2f18e56 100644 (file)
@@ -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;
 
index a7afbd9..6737ff6 100644 (file)
@@ -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
index 3a320bd..f387139 100644 (file)
@@ -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");
index 2818bc0..8f6d1f1 100644 (file)
 
 #include "caipinterface.h"
 
-#ifndef __APPLE__
-#include <asm/types.h>
-#else
-    #ifndef IPV6_ADD_MEMBERSHIP
-        #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
-    #endif
-#endif
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <stdio.h>
@@ -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);
index 90e200f..6b80e61 100644 (file)
@@ -28,6 +28,8 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
+#include <wifi.h>
 
 #include "caadapterutils.h"
 #include "logger.h"
 #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");
+}