Imported Upstream version 1.0.0
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / tizen / caipnwmonitor.c
index 90e200f..88427f3 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)
 
-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");
+}