New IP Adapter supports IPv6
authorJohn Light <john.j.light@intel.com>
Sat, 20 Jun 2015 23:48:52 +0000 (16:48 -0700)
committerErich Keane <erich.keane@intel.com>
Fri, 17 Jul 2015 23:21:18 +0000 (23:21 +0000)
builds on Linux
tested on Linux
IPv6 is now experimental
missing: testing on Android, build and test on Tizen

Change-Id: I4912317111dcc26712aec036715925905bd35eb9
Signed-off-by: John Light <john.j.light@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1724
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Erich Keane <erich.keane@intel.com>
39 files changed:
auto_build.sh
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/api/cainterface.h
resource/csdk/connectivity/common/inc/uarraylist.h
resource/csdk/connectivity/common/src/uarraylist.c
resource/csdk/connectivity/inc/caadapternetdtls.h
resource/csdk/connectivity/inc/caadapterutils.h
resource/csdk/connectivity/inc/caipinterface.h
resource/csdk/connectivity/inc/ifaddrs.h [new file with mode: 0644]
resource/csdk/connectivity/samples/arduino/casample.cpp
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
resource/csdk/connectivity/src/adapter_util/caadapterutils.c
resource/csdk/connectivity/src/adapter_util/ifaddrs.c [new file with mode: 0644]
resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c [new file with mode: 0644]
resource/csdk/connectivity/src/caconnectivitymanager.c
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/src/ip_adapter/SConscript
resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_eth.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipclient_wifi.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipclient.c [deleted file]
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c
resource/csdk/connectivity/test/ca_api_unittest.cpp
resource/csdk/stack/include/internal/ocresourcehandler.h
resource/csdk/stack/include/internal/ocserverrequest.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocobserve.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c

index 3b73da1..adb514d 100755 (executable)
@@ -48,10 +48,10 @@ function build()
        scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$3
 
        echo "*********** Build for Tizen CA lib and sample *************"
-       scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true RELEASE=$3
+    #scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true RELEASE=$3
 
        echo "*********** Build for Tizen CA lib and sample with Security *************"
-       scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true SECURED=1 RELEASE=$3
+    #scons -f resource/csdk/connectivity/build/tizen/SConscript TARGET_OS=tizen TARGET_TRANSPORT=IP LOGGING=true SECURED=1 RELEASE=$3
 
        if [ $(uname -s) = "Darwin" ]
        then
index 3970fc5..e8a59e2 100644 (file)
@@ -134,6 +134,8 @@ typedef enum
     // IPv4 & IPv6 autoselection is the default
     CA_IPV6            = (1 << 5),   // IP adapter only
     CA_IPV4            = (1 << 6),   // IP adapter only
+    // Indication that a message was received by multicast.
+    CA_MULTICAST       = (1 << 7),
     // Link-Local multicast is the default multicast scope for IPv6.
     // These correspond in both value and position to the IPv6 address bits.
     CA_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope
@@ -145,6 +147,9 @@ typedef enum
     CA_SCOPE_GLOBAL    = 0xE, // IPv6 Global scope
 } CATransportFlags_t;
 
+#define CA_IPFAMILY_MASK (CA_IPV6|CA_IPV4)
+#define CA_SCOPE_MASK 0xf     // mask scope bits above
+
 /**
  * @enum CANetworkStatus_t
  * @brief Information about the network status.
@@ -348,8 +353,44 @@ typedef struct
  */
 typedef struct
 {
-    CATransportFlags_t serverFlags;
+    int fd;
+    uint16_t port;
+} CASocket_t;
+
+typedef struct
+{
     CATransportFlags_t clientFlags;
+    CATransportFlags_t serverFlags;
+    bool client;
+    bool server;
+
+    struct sockets
+    {
+        void *threadpool;   // threadpool between Initialize and Start
+        CASocket_t u6;      // unicast   IPv6
+        CASocket_t u6s;     // unicast   IPv6 secure
+        CASocket_t u4;      // unicast   IPv4
+        CASocket_t u4s;     // unicast   IPv4 secure
+        CASocket_t m6;      // multicast IPv6
+        CASocket_t m6s;     // multicast IPv6 secure
+        CASocket_t m4;      // multicast IPv4
+        CASocket_t m4s;     // multicast IPv4 secure
+        int netlinkFd;      // netlink
+        int shutdownFds[2]; // shutdown pipe
+        int selectTimeout;  // in seconds
+        int maxfd;          // highest fd (for select)
+        int numInterfaces;  // number of active interfaces
+        bool started;       // the IP adapter has started
+        bool terminate;     // the IP adapter needs to stop
+        bool ipv6enabled;   // IPv6 enabled by OCInit flags
+        bool ipv4enabled;   // IPv4 enabled by OCInit flags
+    } ip;
+
+    struct calayer
+    {
+        CATransportFlags_t previousRequestFlags; // address family filtering
+        uint16_t previousRequestMessageId;       // address family filtering
+    } ca;
 } CAGlobals_t;
 
 extern CAGlobals_t caglobals;
index 90aeb67..5a65ee0 100644 (file)
@@ -220,14 +220,14 @@ CAResult_t CASendNotification(const CAEndpoint_t *object,
  * @param   interestedNetwork   [IN] Connectivity Type enum
  * @return  #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED or #CA_NOT_SUPPORTED
  */
-CAResult_t CASelectNetwork(const uint32_t interestedNetwork);
+CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork);
 
 /**
  * @brief   Select network to unuse
  * @param   nonInterestedNetwork    [IN] Connectivity Type enum
  * @return  #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED
  */
-CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork);
+CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork);
 
 /**
  * @brief   Get network information
index 17edead..7fa6200 100644 (file)
@@ -105,6 +105,13 @@ uint32_t u_arraylist_length(const u_arraylist_t *list);
  */
 bool u_arraylist_contains(const u_arraylist_t *list,const void *data);
 
+/**
+ * @brief Destroys array list and elements (assuming elements are shallow)
+ * @param list
+ *    [IN] pointer of array list
+ */
+void u_arraylist_destroy(u_arraylist_t *list);
+
 #ifdef __cplusplus
 }
 #endif
index 7c569d4..be897be 100644 (file)
@@ -178,4 +178,17 @@ bool u_arraylist_contains(const u_arraylist_t *list,const void *data)
     return false;
 }
 
-
+// Assumes elements are shallow (have no pointers to allocated memory)
+void u_arraylist_destroy(u_arraylist_t *list)
+{
+    if (!list)
+    {
+        return;
+    }
+    uint32_t len = u_arraylist_length(list);
+    for (uint32_t i = 0; i < len; i++)
+    {
+        OICFree(u_arraylist_get(list, i));
+    }
+    (void)u_arraylist_free(&list);
+}
index 402c746..c1d5349 100644 (file)
@@ -41,7 +41,7 @@ extern void OCGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
 typedef void (*CAPacketReceivedCallback)(const CAEndpoint_t *endpoint,
                                          const void *data, uint32_t dataLength);
 
-typedef uint32_t (*CAPacketSendCallback)(const CAEndpoint_t *endpoint,
+typedef void (*CAPacketSendCallback)(CAEndpoint_t *endpoint,
                                          const void *data, uint32_t dataLength);
 
 /**
index 9d7a587..197cc97 100644 (file)
@@ -87,8 +87,9 @@ extern "C"
  */
 #define IPV4_ADDR_ONE_OCTECT_LEN 4
 
+#ifdef SINGLE_THREAD
 /**
- * @brief Network Interface Information.
+ * @brief Network Interface Information. Only needed for Arduino.
  */
 typedef struct
 {
@@ -96,6 +97,7 @@ typedef struct
     char subnetMask[CA_IPADDR_SIZE];            /**< Maintains interface subnetmask **/
     char interfaceName[CA_INTERFACE_NAME_SIZE]; /**< Interface  name**/
 } CANetInfo_t;
+#endif
 
 /**
  * @brief unicast and multicast server information.
index 085169f..a7afbd9 100644 (file)
@@ -84,7 +84,7 @@ typedef void (*CAIPErrorHandleCallback)(const CAEndpoint_t *endpoint, const void
 typedef void (*CAIPExceptionCallback)(CAAdapterServerType_t type);
 
 /**
- * @brief  Initialize IP server
+ * @brief  Start IP server
  *
  * @param   threadPool  [IN] Thread pool for managing Unicast/Multicast server threads.
  *
@@ -93,118 +93,17 @@ typedef void (*CAIPExceptionCallback)(CAAdapterServerType_t type);
  * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
  * @retval  #CA_STATUS_FAILED Initialization failed
  */
-CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool);
+#ifdef SINGLE_THREAD
+CAResult_t CAIPStartServer();
+#else
+CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool);
+#endif
 
 /**
- * @brief  Terminate IP server
+ * @brief  Stop IP server
  * @return NONE
  */
-void CAIPTerminateServer();
-
-/**
- * @brief  Start multicast server for specified multicast address and port
- *
- * @param   localAddress        [IN]      Local adapter address to which server to be binded.
- * @param   multicastAddress    [IN]      Multicast group address.
- * @param   multicastPort       [IN,OUT]  Port number on which server will be running. If binding
- *                                        the port failed, server starts in the next available port.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_SERVER_STARTED_ALREADY Multicast server is already started and running.
- * @retval  #CA_STATUS_FAILED Operation failed
- */
-CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
-                                    uint16_t multicastPort);
-
-/**
- * @brief  Start unicast server for specified local address and port
- *
- * @param  localAddress [IN]      Local adapter address to which server to be binded.
- * @param  port         [IN,OUT]  Port number on which server will be running. If binding
- *                                the port failed, server starts in the next available port.
- * @param  secured      [IN]      True if the secure server to be started, otherwise false.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_SERVER_STARTED_ALREADY Unicast server is already started and running.
- * @retval  #CA_STATUS_FAILED Operation failed
- */
-CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port, bool secured);
-
-/**
- * @brief  Stop servers that are running in particular interface address.
- *
- * @param   interfaceAddress  [IN] interface address in which servers are running.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_FAILED Operation failed
- */
-CAResult_t CAIPStopServer(const char *interfaceAddress);
-
-/**
- * @brief  Used to stop all unicast and multicast servers.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_FAILED Operation failed
- */
-CAResult_t CAIPStopAllServers();
-
-/**
- * @brief  Used to get the socket fd based on index value of server info list.
- *
- * @param   index      [IN] Index where we need socket fd value.
- * @param   isSecured  [IN] For secured unicast server or normal server.
- *
- * @return  positive value on success and -1 on error.
- */
-int CAGetSocketFdFromUnicastIPServerbyIndex(int16_t index, bool isSecured);
-
-/**
- * @brief  Used to get the number of unicast server currently running.
- *
- * @param   isSecured  [IN] To identify whether its secured unicast server or normal server.
- *
- * @return  positive value on success and -1 on error.
- */
-int16_t CAGetNumberOfUnicastIPServers(bool isSecured);
-
-/**
- * @brief  Used to get the stored socket fd for corresponding ipAddress.
- *
- * @param   ipAddress    [IN] IpAddress of server.
- * @param   isSecured    [IN] Used to check the server is secured or not.
- * @param   isMulticast  [IN] To identify whether its for multicast or unicast.
- *
- * @return  socket fd on success and -1 on error.
- */
-int CAGetSocketFdFromUnicastIPServer(const char *ipAddress, bool isSecured, bool isMulticast);
-
-/**
- * @brief  Used to get the port number to the corresponding ip for giving interface info.
- *
- * @param   ipAddress  [IN] IpAddress of server.
- * @param   isSecured  [IN] Used to check the server is secured or not.
- *
- * @return  port number on success and -1 on error.
- */
-uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured);
-
-/**
- * @brief  Used to get the port number for corresponding ipAddress.
- *
- * @param   serverInfoList  [OUT] ServerInfoList holds unicast and multicast server informations.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_STATUS_FAILED Initialization failed
- */
-CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList);
+void CAIPStopServer();
 
 /**
  * @brief  Set this callback for receiving data packets from peer devices.
@@ -247,61 +146,18 @@ void CAIPSetUnicastPort(uint16_t port);
  * @param  data             [IN] Data to be send.
  * @param  dataLength       [IN] Length of data in bytes
  * @param  isMulticast      [IN] Whether data needs to be sent to multicast ip
- *
- * @return  The number of bytes sent on the network. Returns 0 on error.
- * @remarks isSecure will be ignored when isMulticast is true.
- */
-uint32_t CAIPSendData(const CAEndpoint_t *endpoint,
-                      const void *data,
-                      uint32_t dataLength,
-                      bool isMulticast);
-
-/**
- * @brief  Callback to be notified when IP adapter connection state changes.
- *
- * @param  ipAddress    [IN] IP address of remote OIC device.
- * @param  status       [IN] Connection status either #CA_INTERFACE_UP or #CA_INTERFACE_DOWN.
- * @return  NONE
- * @pre  Callback must be registered using CAIPSetConnectionStateChangeCallback()
- */
-typedef void (*CAIPConnectionStateChangeCallback)(const char *ipAddress,
-                                                  CANetworkStatus_t status);
-
-/**
- * @brief Initialize IP network monitor
- *
- * @param  threadPool [IN] Thread pool for managing network monitor thread.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_STATUS_FAILED Initialization failed
- */
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool);
-
-/**
- * @brief Terminate IP network monitor by removing interface list.
- * @return  NONE
  */
-void CAIPTerminateNetworkMonitor();
+void CAIPSendData(CAEndpoint_t *endpoint,
+                  const void *data,
+                  uint32_t dataLength,
+                  bool isMulticast);
 
 /**
- * @brief  Start network monitoring process. It will start the monitor thread.
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_FAILED Operation failed
- */
-CAResult_t CAIPStartNetworkMonitor();
-
-/**
- * @brief  Stop network monitoring process. It will stop the monitor thread.
+ * @brief  Get IP adapter connection state.
  *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_FAILED Operation failed
+ * @return  True if IP adapter is connected, otherwise false
  */
-CAResult_t CAIPStopNetworkMonitor();
+bool CAIPIsConnected();
 
 /**
  * @brief  Pull the Received Data
@@ -309,47 +165,25 @@ CAResult_t CAIPStopNetworkMonitor();
  */
 void CAIPPullData();
 
-/**
- * @brief  Get local adapter network information.
- *
- * @param  netInterfaceList [OUT] network interface information list
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_STATUS_FAILED Operation failed
- * @remarks  interfaceName and ipAddress must be freed using free().
- */
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList);
+#define CA_COAP        5683
+#define CA_SECURE_COAP 5684
+#define INTERFACE_NAME_MAX 16
 
-/**
- * @brief  Get local adapter network subnet mask.
- *
- * @param  ipAddress  [IN]  IpAddress which is used for getting subnet mask.
- * @param  subnetMask [OUT] Local adapter interface subnet mask
- *
- * @return  #CA_STATUS_OK or Appropriate error code
- * @retval  #CA_STATUS_OK  Successful
- * @retval  #CA_STATUS_INVALID_PARAM Invalid input data
- * @retval  #CA_STATUS_FAILED Operation failed
- * @remarks subnetMask must be freed using free().
- */
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask);
-
-/**
- * @brief  Get IP adapter connection state.
- *
- * @return  True if IP adapter is connected, otherwise false
- */
- bool CAIPIsConnected();
+typedef struct
+{
+    char name[INTERFACE_NAME_MAX];
+    uint32_t index;
+    uint32_t flags;
+    uint16_t family;
+    uint32_t ipv4addr;        // used for IPv4 only
+} CAInterface_t;
 
 /**
- * @brief  Set callback for receiving local IP adapter connection status.
+ * @brief  Get a list of CAInterface_t items
  *
- * @param  callback [IN] Callback to be notified when IP adapter connection state changes.
- * @return NONE
+ * @return  List of CAInterface_t items
  */
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback);
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex);
 
 /**
  * @brief  Set callback for error handling
diff --git a/resource/csdk/connectivity/inc/ifaddrs.h b/resource/csdk/connectivity/inc/ifaddrs.h
new file mode 100644 (file)
index 0000000..9cd19fe
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1995, 1999
+ *     Berkeley Software Design, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
+ */
+
+#ifndef        _IFADDRS_H_
+#define        _IFADDRS_H_
+
+struct ifaddrs {
+       struct ifaddrs  *ifa_next;
+       char            *ifa_name;
+       unsigned int     ifa_flags;
+       struct sockaddr *ifa_addr;
+       struct sockaddr *ifa_netmask;
+       struct sockaddr *ifa_dstaddr;
+       void            *ifa_data;
+};
+
+/*
+ * This may have been defined in <net/if.h>.  Note that if <net/if.h> is
+ * to be included it must be included before this header file.
+ */
+#ifndef        ifa_broadaddr
+#define        ifa_broadaddr   ifa_dstaddr     /* broadcast address interface */
+#endif
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int getifaddrs(struct ifaddrs **ifap);
+extern void freeifaddrs(struct ifaddrs *ifa);
+__END_DECLS
+
+#endif
index a254ec4..165796e 100644 (file)
@@ -622,7 +622,7 @@ void UnselectNetwork()
     {
         g_isLeSelected = false;
     }
-    CAUnSelectNetwork(1 << number);
+    CAUnSelectNetwork((CATransportAdapter_t)(1 << number));
     Serial.println("Terminate");
     CATerminate();
     Serial.println("============");
index 31ba920..f1ca463 100755 (executable)
@@ -45,7 +45,8 @@ env.AppendUnique(CA_SRC = [os.path.join(ca_path,
                                         'adapter_util/caadapterutils.c')])
 env.AppendUnique(CA_SRC = [os.path.join(ca_path,
                                         'adapter_util/cafragmentation.c')])
-
+if ca_os in ['android', 'tizen']:
+       env.AppendUnique(CA_SRC=[os.path.join(ca_path, 'adapter_util/ifaddrs.c')])
 if env.get('SECURED') == '1':
        env.AppendUnique(CA_SRC = [os.path.join(ca_path,
                                                 'adapter_util/caadapternetdtls.c')])
index f49e3d5..92b40c2 100644 (file)
@@ -436,24 +436,20 @@ static int32_t CASendSecureData(dtls_context_t *dtlsContext,
     int type = 0;
 
     //Mutex is not required for g_caDtlsContext. It will be called in same thread.
-    int32_t sentLen = 0;
     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
         (NULL != g_caDtlsContext->adapterCallbacks[type].sendCallback))
     {
-        sentLen = g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
+        g_caDtlsContext->adapterCallbacks[type].sendCallback(&endpoint, buf, bufLen);
     }
     else
     {
         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "send Callback or adapter type is wrong [%d]", type );
     }
 
-    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "sent buffer length [%d]", sentLen);
-
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
-    return sentLen;
+    return bufLen;
 }
 
-
 static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext,
                                    session_t *session,
                                    dtls_alert_level_t level,
index 80ac0cc..2094a6e 100644 (file)
@@ -66,6 +66,7 @@ void CALogPDUData(coap_pdu_t *pdu)
     OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - token : %s", pdu->hdr->token);
 }
 
+#ifdef WITH_ARDUINO
 CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
                                    size_t ipAddrLen, uint16_t *port)
 {
@@ -130,243 +131,7 @@ CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
     return CA_STATUS_FAILED;
 }
 
-bool CAAdapterIsSameSubnet(const char *ipAddress1, const char *ipAddress2, const char *netMask)
-{
-    VERIFY_NON_NULL_RET(ipAddress1, CA_ADAPTER_UTILS_TAG, "First address", false);
-    VERIFY_NON_NULL_RET(ipAddress2, CA_ADAPTER_UTILS_TAG, "Second address", false);
-    VERIFY_NON_NULL_RET(netMask, CA_ADAPTER_UTILS_TAG, "netMask", false);
-
-    uint8_t ipList1[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
-    uint8_t ipList2[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
-    uint8_t maskList[IPV4_ADDR_ONE_OCTECT_LEN] = { 0 };
-    CAResult_t ret = CA_STATUS_OK;
-
-    /* Local Loopback Address */
-    if (0 == strncmp(ipAddress1, "127.", 4) || 0 == strncmp(ipAddress2, "127.", 4))
-    {
-        return true;
-    }
-
-    uint16_t parsedPort = 0;
-    ret = CAParseIPv4AddressInternal(ipAddress1, ipList1, sizeof(ipList1), &parsedPort);
-    if (ret != CA_STATUS_OK)
-    {
-        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "First ip address parse fail %d", ret);
-        return false;
-    }
-
-    ret = CAParseIPv4AddressInternal(ipAddress2, ipList2, sizeof(ipList2), &parsedPort);
-    if (ret != CA_STATUS_OK)
-    {
-        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Second ip address parse fail %d", ret);
-        return false;
-    }
-
-    ret = CAParseIPv4AddressInternal(netMask, maskList, sizeof(maskList), &parsedPort);
-    if (ret != CA_STATUS_OK)
-    {
-        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "Net mask parse fail %d", ret);
-        return false;
-    }
-
-    return ((ipList1[0] & maskList[0]) == (ipList2[0] & maskList[0])) && ((ipList1[1] & maskList[1])
-            == (ipList2[1] & maskList[1]))
-           && ((ipList1[2] & maskList[2]) == (ipList2[2] & maskList[2]))
-           && ((ipList1[3] & maskList[3]) == (ipList2[3] & maskList[3]));
-}
-
-bool CAIsMulticastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress,
-                                const char *multicastAddress, uint16_t port)
-{
-    VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false);
-    VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false);
-    VERIFY_NON_NULL_RET(multicastAddress, CA_ADAPTER_UTILS_TAG, "multicastAddress is null", false);
-
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!info)
-        {
-            OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Info is NULL");
-            return false;
-        }
-
-        if (info->isMulticastServer && (strncmp(info->endpoint.addr, multicastAddress,
-                                                strlen(multicastAddress)) == 0)
-            && (info->endpoint.port == port) && (strncmp(info->ifAddr, ipAddress, strlen(ipAddress)) == 0))
-        {
-            return info->isServerStarted;
-        }
-    }
-    return false;
-}
-
-bool CAIsUnicastServerStarted(const u_arraylist_t *serverInfoList, const char *ipAddress,
-                              uint16_t port)
-{
-    VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", false);
-    VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", false);
-
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (!info->isMulticastServer && (strncmp(info->endpoint.addr, ipAddress,
-                                                 strlen(ipAddress)) == 0)
-            && (info->endpoint.port == port))
-        {
-            return info->isServerStarted;
-        }
-    }
-    return false;
-}
-
-uint16_t CAGetServerPort(const u_arraylist_t *serverInfoList, const char *ipAddress, bool isSecured)
-{
-    VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", 0);
-    VERIFY_NON_NULL_RET(ipAddress, CA_ADAPTER_UTILS_TAG, "ipAddress is null", 0);
-
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!info)
-        {
-            continue;
-        }
-        bool ifSecured = info->endpoint.flags & CA_SECURE;
-        if ((strncmp(info->endpoint.addr, ipAddress, strlen(ipAddress)) == 0) &&
-                    (ifSecured == isSecured))
-        {
-            return info->endpoint.port;
-        }
-    }
-
-    return 0;
-}
-
-int CAGetSocketFdForUnicastServer(const u_arraylist_t *serverInfoList,
-                                bool isMulticast, const CAEndpoint_t *endpoint)
-{
-    VERIFY_NON_NULL_RET(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null", -1);
-    VERIFY_NON_NULL_RET(endpoint, CA_ADAPTER_UTILS_TAG, "endpoint is null", -1);
-
-    bool isSecured = (endpoint->flags & CA_SECURE) != 0;
-
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (!CAAdapterIsSameSubnet(info->endpoint.addr, endpoint->addr, info->subNetMask))
-        {
-            continue;
-        }
-
-        bool ifSecured = info->endpoint.flags & CA_SECURE;
-        if (!info->isMulticastServer && (ifSecured == isSecured))
-        {
-            OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG,
-                      "CAGetSocketFdForServer found socket [%d]", info->socketFd);
-            return info->socketFd;
-        }
-
-    }
-
-    OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG,
-            "CAGetSocketFdForServer socket fd is not found");
-    return -1;
-}
-
-CAResult_t CAAddServerInfo(u_arraylist_t *serverInfoList, CAServerInfo_t *info)
-{
-    VERIFY_NON_NULL(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null");
-    VERIFY_NON_NULL(info, CA_ADAPTER_UTILS_TAG, "info is null");
-
-    CAResult_t result = u_arraylist_add(serverInfoList, (void *) info);
-    if (CA_STATUS_OK != result)
-    {
-        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_add failed!");
-    }
-    return result;
-}
-
-void CARemoveServerInfo(u_arraylist_t *serverInfoList, int sockFd)
-{
-    VERIFY_NON_NULL_VOID(serverInfoList, CA_ADAPTER_UTILS_TAG, "serverInfoList is null");
-
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-    for (uint32_t listIndex = 0; listIndex < listLength;)
-    {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!info)
-        {
-            listIndex++;
-            continue;
-        }
-
-        if (info->socketFd == sockFd)
-        {
-            if (u_arraylist_remove(serverInfoList, listIndex))
-            {
-                OICFree(info);
-                listLength--;
-            }
-            else
-            {
-                OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "u_arraylist_remove failed!");
-                break;
-            }
-        }
-        else
-        {
-            listIndex++;
-        }
-    }
-}
-
-void CAClearNetInterfaceInfoList(u_arraylist_t *infoList)
-{
-    uint32_t listLength = u_arraylist_length(infoList);
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(infoList, listIndex);
-        if (!netInfo)
-        {
-            continue;
-        }
-        OICFree(netInfo);
-    }
-    u_arraylist_free(&infoList);
-}
-
-void CAClearServerInfoList(u_arraylist_t *serverInfoList)
-{
-    uint32_t listLength = u_arraylist_length(serverInfoList);
-    for (uint32_t listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CAServerInfo_t *serverInfo = (CAServerInfo_t *) u_arraylist_get(serverInfoList, listIndex);
-        if (!serverInfo)
-        {
-            continue;
-        }
-        OICFree(serverInfo);
-    }
-    u_arraylist_free(&serverInfoList);
-}
-
-#ifndef WITH_ARDUINO
+#else // not with_arduino
 /*
  * These two conversion functions return void because errors can't happen
  * (because of NI_NUMERIC), and there's nothing to do if they do happen.
@@ -379,7 +144,7 @@ void CAConvertAddrToName(const struct sockaddr_storage *sockAddr, char *host, ui
 
     int r = getnameinfo((struct sockaddr *)sockAddr,
                         sizeof (struct sockaddr_storage),
-                        host, CA_IPADDR_SIZE,
+                        host, MAX_ADDR_STR_SIZE_CA,
                         NULL, 0,
                         NI_NUMERICHOST|NI_NUMERICSERV);
     if (r)
diff --git a/resource/csdk/connectivity/src/adapter_util/ifaddrs.c b/resource/csdk/connectivity/src/adapter_util/ifaddrs.c
new file mode 100644 (file)
index 0000000..9176a32
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+Copyright (c) 2013, Kenneth MacKay
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "ifaddrs.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+typedef struct NetlinkList
+{
+    struct NetlinkList *m_next;
+    struct nlmsghdr *m_data;
+    unsigned int m_size;
+} NetlinkList;
+
+static int netlink_socket(void)
+{
+    int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if(l_socket < 0)
+    {
+        return -1;
+    }
+
+    struct sockaddr_nl l_addr;
+    memset(&l_addr, 0, sizeof(l_addr));
+    l_addr.nl_family = AF_NETLINK;
+    if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
+    {
+        close(l_socket);
+        return -1;
+    }
+
+    return l_socket;
+}
+
+static int netlink_send(int p_socket, int p_request)
+{
+    struct
+    {
+        struct nlmsghdr m_hdr;
+        struct rtgenmsg m_msg;
+    } l_data;
+
+    memset(&l_data, 0, sizeof(l_data));
+
+    l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+    l_data.m_hdr.nlmsg_type = p_request;
+    l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+    l_data.m_hdr.nlmsg_pid = 0;
+    l_data.m_hdr.nlmsg_seq = p_socket;
+    l_data.m_msg.rtgen_family = AF_UNSPEC;
+
+    struct sockaddr_nl l_addr;
+    memset(&l_addr, 0, sizeof(l_addr));
+    l_addr.nl_family = AF_NETLINK;
+    return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
+}
+
+static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
+{
+    struct msghdr l_msg;
+    struct iovec l_iov = { p_buffer, p_len };
+    struct sockaddr_nl l_addr;
+
+    for(;;)
+    {
+        l_msg.msg_name = (void *)&l_addr;
+        l_msg.msg_namelen = sizeof(l_addr);
+        l_msg.msg_iov = &l_iov;
+        l_msg.msg_iovlen = 1;
+        l_msg.msg_control = NULL;
+        l_msg.msg_controllen = 0;
+        l_msg.msg_flags = 0;
+        int l_result = recvmsg(p_socket, &l_msg, 0);
+
+        if(l_result < 0)
+        {
+            if(errno == EINTR)
+            {
+                continue;
+            }
+            return -2;
+        }
+
+        if(l_msg.msg_flags & MSG_TRUNC)
+        { // buffer was too small
+            return -1;
+        }
+        return l_result;
+    }
+}
+
+static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
+{
+    size_t l_size = 4096;
+    void *l_buffer = NULL;
+
+    for(;;)
+    {
+        free(l_buffer);
+        l_buffer = malloc(l_size);
+        if (l_buffer == NULL)
+        {
+            return NULL;
+        }
+
+        int l_read = netlink_recv(p_socket, l_buffer, l_size);
+        *p_size = l_read;
+        if(l_read == -2)
+        {
+            free(l_buffer);
+            return NULL;
+        }
+        if(l_read >= 0)
+        {
+            pid_t l_pid = getpid();
+            struct nlmsghdr *l_hdr;
+            for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
+            {
+                if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+                {
+                    continue;
+                }
+
+                if(l_hdr->nlmsg_type == NLMSG_DONE)
+                {
+                    *p_done = 1;
+                    break;
+                }
+
+                if(l_hdr->nlmsg_type == NLMSG_ERROR)
+                {
+                    free(l_buffer);
+                    return NULL;
+                }
+            }
+            return l_buffer;
+        }
+
+        l_size *= 2;
+    }
+}
+
+static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
+{
+    NetlinkList *l_item = malloc(sizeof(NetlinkList));
+    if (l_item == NULL)
+    {
+        return NULL;
+    }
+
+    l_item->m_next = NULL;
+    l_item->m_data = p_data;
+    l_item->m_size = p_size;
+    return l_item;
+}
+
+static void freeResultList(NetlinkList *p_list)
+{
+    NetlinkList *l_cur;
+    while(p_list)
+    {
+        l_cur = p_list;
+        p_list = p_list->m_next;
+        free(l_cur->m_data);
+        free(l_cur);
+    }
+}
+
+static NetlinkList *getResultList(int p_socket, int p_request)
+{
+    if(netlink_send(p_socket, p_request) < 0)
+    {
+        return NULL;
+    }
+
+    NetlinkList *l_list = NULL;
+    NetlinkList *l_end = NULL;
+    int l_size;
+    int l_done = 0;
+    while(!l_done)
+    {
+        struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
+        if(!l_hdr)
+        { // error
+            freeResultList(l_list);
+            return NULL;
+        }
+
+        NetlinkList *l_item = newListItem(l_hdr, l_size);
+        if (!l_item)
+        {
+            freeResultList(l_list);
+            return NULL;
+        }
+        if(!l_list)
+        {
+            l_list = l_item;
+        }
+        else
+        {
+            l_end->m_next = l_item;
+        }
+        l_end = l_item;
+    }
+    return l_list;
+}
+
+static size_t maxSize(size_t a, size_t b)
+{
+    return (a > b ? a : b);
+}
+
+static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
+{
+    switch(p_family)
+    {
+        case AF_INET:
+            return sizeof(struct sockaddr_in);
+        case AF_INET6:
+            return sizeof(struct sockaddr_in6);
+        case AF_PACKET:
+            return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
+        default:
+            return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
+    }
+}
+
+static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
+{
+    switch(p_family)
+    {
+        case AF_INET:
+            memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
+            break;
+        case AF_INET6:
+            memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
+            break;
+        case AF_PACKET:
+            memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
+            ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
+            break;
+        default:
+            memcpy(p_dest->sa_data, p_data, p_size);
+            break;
+    }
+    p_dest->sa_family = p_family;
+}
+
+static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
+{
+    if(!*p_resultList)
+    {
+        *p_resultList = p_entry;
+    }
+    else
+    {
+        struct ifaddrs *l_cur = *p_resultList;
+        while(l_cur->ifa_next)
+        {
+            l_cur = l_cur->ifa_next;
+        }
+        l_cur->ifa_next = p_entry;
+    }
+}
+
+static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
+{
+    struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
+
+    size_t l_nameSize = 0;
+    size_t l_addrSize = 0;
+    size_t l_dataSize = 0;
+
+    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
+    struct rtattr *l_rta;
+    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+    {
+        //void *l_rtaData = RTA_DATA(l_rta);
+        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+        switch(l_rta->rta_type)
+        {
+            case IFLA_ADDRESS:
+            case IFLA_BROADCAST:
+                l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
+                break;
+            case IFLA_IFNAME:
+                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
+                break;
+            case IFLA_STATS:
+                l_dataSize += NLMSG_ALIGN(l_rtaSize);
+                break;
+            default:
+                break;
+        }
+    }
+
+    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
+    if (l_entry == NULL)
+    {
+        return -1;
+    }
+    memset(l_entry, 0, sizeof(struct ifaddrs));
+    l_entry->ifa_name = "";
+
+    char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
+    char *l_name = l_index + sizeof(int);
+    char *l_addr = l_name + l_nameSize;
+    char *l_data = l_addr + l_addrSize;
+
+    // save the interface index so we can look it up when handling the addresses.
+    memcpy(l_index, &l_info->ifi_index, sizeof(int));
+
+    l_entry->ifa_flags = l_info->ifi_flags;
+
+    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
+    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+    {
+        void *l_rtaData = RTA_DATA(l_rta);
+        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+        switch(l_rta->rta_type)
+        {
+            case IFLA_ADDRESS:
+            case IFLA_BROADCAST:
+            {
+                size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
+                makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
+                ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
+                ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
+                if(l_rta->rta_type == IFLA_ADDRESS)
+                {
+                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
+                }
+                else
+                {
+                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
+                }
+                l_addr += NLMSG_ALIGN(l_addrLen);
+                break;
+            }
+            case IFLA_IFNAME:
+                strncpy(l_name, l_rtaData, l_rtaDataSize);
+                l_name[l_rtaDataSize] = '\0';
+                l_entry->ifa_name = l_name;
+                break;
+            case IFLA_STATS:
+                memcpy(l_data, l_rtaData, l_rtaDataSize);
+                l_entry->ifa_data = l_data;
+                break;
+            default:
+                break;
+        }
+    }
+
+    addToEnd(p_resultList, l_entry);
+    return 0;
+}
+
+static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
+{
+    int l_num = 0;
+    struct ifaddrs *l_cur = *p_links;
+    while(l_cur && l_num < p_numLinks)
+    {
+        char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
+        int l_index;
+        memcpy(&l_index, l_indexPtr, sizeof(int));
+        if(l_index == p_index)
+        {
+            return l_cur;
+        }
+
+        l_cur = l_cur->ifa_next;
+        ++l_num;
+    }
+    return NULL;
+}
+
+static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
+{
+    struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
+    struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
+
+    if(l_info->ifa_family == AF_PACKET)
+    {
+        return 0;
+    }
+
+    size_t l_nameSize = 0;
+    size_t l_addrSize = 0;
+
+    int l_addedNetmask = 0;
+
+    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
+    struct rtattr *l_rta;
+    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+    {
+        //void *l_rtaData = RTA_DATA(l_rta);
+        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+
+        switch(l_rta->rta_type)
+        {
+            case IFA_ADDRESS:
+            case IFA_LOCAL:
+                if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
+                { // make room for netmask
+                    l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
+                    l_addedNetmask = 1;
+                }
+            case IFA_BROADCAST:
+                l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
+                break;
+            case IFA_LABEL:
+                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
+                break;
+            default:
+                break;
+        }
+    }
+
+    struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
+    if (l_entry == NULL)
+    {
+        return -1;
+    }
+    memset(l_entry, 0, sizeof(struct ifaddrs));
+    l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
+
+    char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
+    char *l_addr = l_name + l_nameSize;
+
+    l_entry->ifa_flags = l_info->ifa_flags;
+    if(l_interface)
+    {
+        l_entry->ifa_flags |= l_interface->ifa_flags;
+    }
+
+    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
+    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+    {
+        void *l_rtaData = RTA_DATA(l_rta);
+        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
+        switch(l_rta->rta_type)
+        {
+            case IFA_ADDRESS:
+            case IFA_BROADCAST:
+            case IFA_LOCAL:
+            {
+                size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
+                makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
+                if(l_info->ifa_family == AF_INET6)
+                {
+                    if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
+                    {
+                        ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
+                    }
+                }
+
+                if(l_rta->rta_type == IFA_ADDRESS)
+                { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
+                    if(l_entry->ifa_addr)
+                    {
+                        l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
+                    }
+                    else
+                    {
+                        l_entry->ifa_addr = (struct sockaddr *)l_addr;
+                    }
+                }
+                else if(l_rta->rta_type == IFA_LOCAL)
+                {
+                    if(l_entry->ifa_addr)
+                    {
+                        l_entry->ifa_dstaddr = l_entry->ifa_addr;
+                    }
+                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
+                }
+                else
+                {
+                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
+                }
+                l_addr += NLMSG_ALIGN(l_addrLen);
+                break;
+            }
+            case IFA_LABEL:
+                strncpy(l_name, l_rtaData, l_rtaDataSize);
+                l_name[l_rtaDataSize] = '\0';
+                l_entry->ifa_name = l_name;
+                break;
+            default:
+                break;
+        }
+    }
+
+    if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
+    {
+        unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
+        unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
+        char l_mask[16] = {0};
+        unsigned i;
+        for(i=0; i<(l_prefix/8); ++i)
+        {
+            l_mask[i] = 0xff;
+        }
+        if(l_prefix % 8)
+        {
+            l_mask[i] = 0xff << (8 - (l_prefix % 8));
+        }
+
+        makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
+        l_entry->ifa_netmask = (struct sockaddr *)l_addr;
+    }
+
+    addToEnd(p_resultList, l_entry);
+    return 0;
+}
+
+static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
+{
+    int l_numLinks = 0;
+    pid_t l_pid = getpid();
+    for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
+    {
+        unsigned int l_nlsize = p_netlinkList->m_size;
+        struct nlmsghdr *l_hdr;
+        for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
+        {
+            if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+            {
+                continue;
+            }
+
+            if(l_hdr->nlmsg_type == NLMSG_DONE)
+            {
+                break;
+            }
+
+            if(l_hdr->nlmsg_type == RTM_NEWLINK)
+            {
+                if(interpretLink(l_hdr, p_resultList) == -1)
+                {
+                    return -1;
+                }
+                ++l_numLinks;
+            }
+        }
+    }
+    return l_numLinks;
+}
+
+static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
+{
+    pid_t l_pid = getpid();
+    for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
+    {
+        unsigned int l_nlsize = p_netlinkList->m_size;
+        struct nlmsghdr *l_hdr;
+        for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
+        {
+            if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+            {
+                continue;
+            }
+
+            if(l_hdr->nlmsg_type == NLMSG_DONE)
+            {
+                break;
+            }
+
+            if(l_hdr->nlmsg_type == RTM_NEWADDR)
+            {
+                if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
+                {
+                    return -1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+int getifaddrs(struct ifaddrs **ifap)
+{
+    if(!ifap)
+    {
+        return -1;
+    }
+    *ifap = NULL;
+
+    int l_socket = netlink_socket();
+    if(l_socket < 0)
+    {
+        return -1;
+    }
+
+    NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
+    if(!l_linkResults)
+    {
+        close(l_socket);
+        return -1;
+    }
+
+    NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
+    if(!l_addrResults)
+    {
+        close(l_socket);
+        freeResultList(l_linkResults);
+        return -1;
+    }
+
+    int l_result = 0;
+    int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
+    if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
+    {
+        l_result = -1;
+    }
+
+    freeResultList(l_linkResults);
+    freeResultList(l_addrResults);
+    close(l_socket);
+    return l_result;
+}
+
+void freeifaddrs(struct ifaddrs *ifa)
+{
+    struct ifaddrs *l_cur;
+    while(ifa)
+    {
+        l_cur = ifa;
+        ifa = ifa->ifa_next;
+        free(l_cur);
+    }
+}
+
+
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+//#include <string.h>
+//#include <unistd.h>
+//#include <linux/sockios.h>
+//#include <net/if.h>
+//#include <sys/socket.h>
+//#include <sys/ioctl.h>
+
+/*
+ * Map an interface name into its corresponding index.
+ * Returns 0 on error, as 0 is not a valid index.
+ */
+unsigned int if_nametoindex(const char *ifname)
+{
+    int index;
+    int ctl_sock;
+    struct ifreq ifr;
+
+    memset(&ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+    ifr.ifr_name[IFNAMSIZ - 1] = 0;
+
+    index = 0;
+    if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
+        if (ioctl(ctl_sock, SIOCGIFINDEX, &ifr) >= 0) {
+            index = ifr.ifr_ifindex;
+        }
+        close(ctl_sock);
+    }
+    return index;
+}
diff --git a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter_singlethread.c
new file mode 100644 (file)
index 0000000..cdedbbd
--- /dev/null
@@ -0,0 +1,427 @@
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+#include "caleadapter_singlethread.h"
+
+#include "caleinterface_singlethread.h"
+#include "cableserver.h"
+#include "logger.h"
+#include "caadapterutils.h"
+#include "cafragmentation.h"
+
+#define TAG "LAD"
+
+/**
+ * @def MAX_EVENT_COUNT
+ * @brief Maximum number of tries to get the event on BLE Shield address.
+ */
+#define MAX_EVENT_COUNT 20
+
+static CANetworkChangeCallback g_networkCallback = NULL;
+static bool g_serverRunning = false;
+static CANetworkPacketReceivedCallback g_respCallback;
+static char *g_coapBuffer = NULL;
+static uint32_t g_dataLen = 0;
+static uint32_t g_packetDataLen = 0;
+
+/**
+ * @brief API to register for BLE network notification.
+ * @param net_callback - network notification callback.
+ * @return - Error Code
+ */
+CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback);
+
+/**
+ * @brief API to send received data to upper layer.
+ * @param[in] data - data received from BLE characteristics.
+ * @param[in] dataLen - received data Length.
+ * @param[in] senderAdrs - sender Address.
+ * @param[in] senderPort - sender port.
+ * @return - Error Code
+ */
+void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs,
+                      int32_t senderPort);
+
+/**
+ * @brief API to read the data from characteristics and invoke notifyCallback.
+ * @return - void
+ */
+void CACheckData();
+
+/**
+ * @brief API to Send the data.
+ * @return - Number of bytes sent. -1 on error.
+ */
+int32_t CASendLEData(const void *data, uint32_t dataLen);
+
+CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
+                          CANetworkPacketReceivedCallback reqRespCallback,
+                          CANetworkChangeCallback netCallback)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    if (NULL == registerCallback || NULL == reqRespCallback || NULL == netCallback)
+    {
+        OIC_LOG(ERROR, TAG, "i/p null");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    CAResult_t result = CALEInitializeNetworkMonitor();
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, TAG, "n/w init fail: %d", result);
+        return CA_STATUS_FAILED;
+    }
+
+    g_respCallback = reqRespCallback;
+    LERegisterNetworkNotifications(netCallback);
+    CAConnectivityHandler_t connHandler;
+    connHandler.startAdapter = CAStartLE;
+    connHandler.startListenServer = CAStartLEListeningServer;
+    connHandler.startDiscoveryServer = CAStartLEDiscoveryServer;
+    connHandler.sendData = CASendLEUnicastData;
+    connHandler.sendDataToAll = CASendLEMulticastData;
+    connHandler.GetnetInfo = CAGetLEInterfaceInformation;
+    connHandler.readData = CAReadLEData;
+    connHandler.stopAdapter = CAStopLE;
+    connHandler.terminate = CATerminateLE;
+    registerCallback(connHandler, CA_ADAPTER_GATT_BTLE);
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStartLE()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStartLEListeningServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    CAResult_t result = CAInitializeBle();
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, TAG, "ble init fail: %d", result);
+        return CA_STATUS_FAILED;
+    }
+    /**
+     * Below for loop is to process the BLE Events received from BLE Shield.
+     * BLE Events includes BLE Shield Address Added as a patch to RBL Library.
+     */
+    for (int iter = 0; iter < MAX_EVENT_COUNT; iter++)
+    {
+        CACheckData();
+    }
+
+    g_serverRunning = true;
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStartLEDiscoveryServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStartLENotifyServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+uint32_t CASendLENotification(const CAEndpoint_t *endpoint, const void *data,
+                              uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return 1;
+}
+
+int32_t CASendLEUnicastData(const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    if (NULL == remoteEndpoint || NULL == data || dataLen == 0)
+    {
+        OIC_LOG(ERROR, TAG, "i/p null");
+        return -1;
+    }
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CASendLEData(data, dataLen);
+}
+
+int32_t CASendLEMulticastData(const void *data, uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    if (NULL == data || 0 == dataLen)
+    {
+        OIC_LOG(ERROR, TAG, "i/p null");
+        return -1;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CASendLEData(data, dataLen);
+}
+
+CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    if (NULL == info || NULL == size)
+    {
+        OIC_LOG(ERROR, TAG, "i/p null");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    char *leAddress = NULL;
+    CAResult_t res = CAGetLEAddress(&leAddress);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "CAGetLEAddress has failed");
+        return res;
+    }
+
+    if (NULL == leAddress)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to get Le addr");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "leAddress = %s", leAddress);
+
+    /**
+     * Create local endpoint using util function
+     */
+    (*info) = CAAdapterCreateEndpoint(CA_DEFAULT_FLAGS, CA_ADAPTER_GATT_BTLE, leAddress, 0);
+    if (NULL == (*info))
+    {
+        OIC_LOG(ERROR, TAG, "malloc fail");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    (*size) = 1;
+    if (*leAddress)
+    {
+        OICFree(leAddress);
+    }
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAReadLEData()
+{
+    if (true == g_serverRunning)
+    {
+        CACheckData();
+    }
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStopLE()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    CAStopBleGattServer();
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+void CATerminateLE()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    g_respCallback = NULL;
+    LERegisterNetworkNotifications(NULL);
+    CAResult_t result = CATerminateBle();
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, TAG, "ble terminate fail");
+        return;
+    }
+
+    CALETerminateNetworkMonitor();
+    g_serverRunning = false;
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return;
+}
+
+CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    g_networkCallback = netCallback;
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStartBleGattServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    // Done at time of setup i.e. in initializeBle api
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStopBleGattServer()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    // There is no server running to stop.
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs, int32_t senderPort)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    if (g_respCallback)
+    {
+
+        /* Cannot get Address as of now */
+        CAEndpoint_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_IPV4, CA_ADAPTER_GATT_BTLE,
+                                                                   senderAdrs, senderPort);
+
+        g_respCallback(localEndpoint, data, dataLen);
+    }
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CACheckData()
+{
+    CABleDoEvents();
+
+    if (CAIsBleDataAvailable())
+    {
+        // Allocate Memory for COAP Buffer and do ParseHeader
+        if (NULL == g_coapBuffer)
+        {
+            OIC_LOG(DEBUG, TAG, "IN");
+            char headerArray[CA_HEADER_LENGTH] = "";
+            while (CAIsBleDataAvailable() && g_dataLen < CA_HEADER_LENGTH)
+            {
+                headerArray[g_dataLen++] = CAReadBleData();
+            }
+
+            g_packetDataLen = CAParseHeader(headerArray);
+
+            if (g_packetDataLen > COAP_MAX_PDU_SIZE)
+            {
+                OIC_LOG(ERROR, TAG, "len > pdu_size");
+                return;
+            }
+
+            g_coapBuffer = (char *)OICCalloc((size_t)g_packetDataLen, sizeof(char));
+            if (NULL == g_coapBuffer)
+            {
+                OIC_LOG(ERROR, TAG, "malloc");
+                return;
+            }
+
+            OIC_LOG(DEBUG, TAG, "OUT");
+            g_dataLen = 0;
+        }
+
+        OIC_LOG(DEBUG, TAG, "IN");
+        while (CAIsBleDataAvailable())
+        {
+            OIC_LOG(DEBUG, TAG, "In While loop");
+            g_coapBuffer[g_dataLen++] = CAReadBleData();
+            if (g_dataLen == g_packetDataLen)
+            {
+                OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
+                g_coapBuffer[g_dataLen] = '\0';
+                if (g_dataLen > 0)
+                {
+                    OIC_LOG_V(DEBUG, TAG, "recv dataLen=%d", g_dataLen);
+                    CANotifyCallback((void *)g_coapBuffer, g_dataLen, "", 0);
+                }
+                g_dataLen = 0;
+                OICFree(g_coapBuffer);
+                g_coapBuffer = NULL;
+                break;
+            }
+        }
+        OIC_LOG(DEBUG, TAG, "OUT");
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "NoData");
+    }
+    return;
+}
+
+int32_t CASendLEData(const void *data, uint32_t dataLen)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    char header[CA_HEADER_LENGTH] = {0};
+
+    CAResult_t result = CAGenerateHeader(header, dataLen);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, TAG, "Generate header failed");
+        return -1;
+    }
+
+    if (!CAIsBleConnected())
+    {
+        OIC_LOG(ERROR, TAG, "le not conn");
+        return -1;
+    }
+
+    result = CAUpdateCharacteristicsToAllGattClients(header, CA_HEADER_LENGTH);
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, TAG, "Update characteristics failed");
+        return -1;
+    }
+
+    int32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE;
+    for (int32_t iter = 0; iter < dataLimit; iter++)
+    {
+        result = CAUpdateCharacteristicsToAllGattClients((data +
+                                                         (iter * CA_SUPPORTED_BLE_MTU_SIZE)),
+                                                         CA_SUPPORTED_BLE_MTU_SIZE);
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG(ERROR, TAG, "Update characteristics failed");
+            return -1;
+        }
+        CABleDoEvents();
+    }
+
+    uint8_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE;
+    if(remainingLen)
+    {
+        result = CAUpdateCharacteristicsToAllGattClients((data +
+                                                         (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE)),
+                                                         remainingLen);
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG(ERROR, TAG, "Update characteristics failed");
+            return -1;
+        }
+        CABleDoEvents();
+    }
+
+    OIC_LOG(DEBUG, TAG, "writebytes done");
+    OIC_LOG(DEBUG, TAG, "OUT");
+    // Arduino BLEWrite doesnot return value. So, Return the received DataLength
+    return dataLen;
+}
+
index 910d167..b8e9f42 100644 (file)
@@ -34,7 +34,7 @@
 #include "caadapternetdtls.h"
 #endif
 
-CAGlobals_t caglobals;
+CAGlobals_t caglobals = { 0 };
 
 #define TAG "CA_CONN_MGR"
 
@@ -227,7 +227,7 @@ CAResult_t CASendResponse(const CAEndpoint_t *object, const CAResponseInfo_t *re
 
 }
 
-CAResult_t CASelectNetwork(const uint32_t interestedNetwork)
+CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork)
 {
     OIC_LOG_V(DEBUG, TAG, "Selected network : %d", interestedNetwork);
 
@@ -261,7 +261,7 @@ CAResult_t CASelectNetwork(const uint32_t interestedNetwork)
     return res;
 }
 
-CAResult_t CAUnSelectNetwork(const uint32_t nonInterestedNetwork)
+CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork)
 {
     OIC_LOG_V(DEBUG, TAG, "unselected network : %d", nonInterestedNetwork);
 
index aada31e..9695e2f 100644 (file)
@@ -340,6 +340,46 @@ static void CASendThreadProcess(void *threadData)
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
+/*
+ * If a second message arrives with the same token and the other address
+ * family, drop it.  Typically, IPv6 beats IPv4, so the IPv4 message is dropped.
+ * This can be made more robust (for instance, another message could arrive
+ * in between), but it is good enough for now.
+ */
+static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId)
+{
+    if (!endpoint)
+    {
+        return true;
+    }
+    if (endpoint->adapter != CA_ADAPTER_IP)
+    {
+        return false;
+    }
+
+    bool ret = false;
+    CATransportFlags_t familyFlags = endpoint->flags & CA_IPFAMILY_MASK;
+
+    if (messageId == caglobals.ca.previousRequestMessageId)
+    {
+        if ((familyFlags ^ caglobals.ca.previousRequestFlags) == CA_IPFAMILY_MASK)
+        {
+            if (familyFlags & CA_IPV6)
+            {
+                OIC_LOG(INFO, TAG, PCF("IPv6 duplicate response ignored"));
+            }
+            else
+            {
+                OIC_LOG(INFO, TAG, PCF("IPv4 duplicate response ignored"));
+            }
+            ret = true;
+        }
+    }
+    caglobals.ca.previousRequestFlags = familyFlags;
+    caglobals.ca.previousRequestMessageId = messageId;
+    return ret;
+}
+
 static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, uint32_t dataLen)
 {
     OIC_LOG(DEBUG, TAG, "IN");
@@ -375,6 +415,13 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, void *data, u
             return;
         }
 
+        if (CADropSecondRequest(endpoint, ReqInfo->info.messageId))
+        {
+            OICFree(ReqInfo);
+            coap_delete_pdu(pdu);
+            return;
+        }
+
         if (NULL != ReqInfo->info.options)
         {
             uint32_t i;
index db06815..5cc3798 100644 (file)
@@ -21,7 +21,6 @@ if target_os == 'arduino':
 else:
     common_files = [
         os.path.join(src_dir, 'caipadapter.c'),
-       os.path.join(src_dir, 'caipclient.c'),
        os.path.join(src_dir, 'caipserver.c') ]
 
 # Get list of target-specific source file base names, i.e. no parent
@@ -52,5 +51,3 @@ if target_os in ['linux','darwin','ios']:
 # The list of BLE adapter source files is a combination of both the
 # common and target-specific source file lists.
 env.AppendUnique(CA_SRC = common_files + target_files)
-
-
index ef3a5f7..2f4b5d5 100644 (file)
 /******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
 
 #include "caipinterface.h"
 
-#include <string.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <linux/if.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <sys/socket.h>
 #include <netdb.h>
+#include <string.h>
 #include <errno.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
+#include <linux/if.h>
+
 #include "caadapterutils.h"
-#include "camutex.h"
 #include "logger.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
-#include "org_iotivity_ca_CaIpInterface.h"
-
-#define IP_MONITOR_TAG "IP_MONITOR"
-#define MAX_INTERFACE_INFO_LENGTH (1024)
-
-/**
- * @var g_stopNetworkMonitor
- * @brief  Used to stop the network monitor thread.
- */
-static bool g_stopNetworkMonitor = false;
-
-/**
- * @var g_stopNetworkMonitorMutex
- * @brief  Mutex for synchronizing access to g_stopNetworkMonitor flag.
- */
-static ca_mutex g_stopNetworkMonitorMutex = NULL;
-
-/**
- * @struct CAIPNwMonitorContext
- * @brief  Used for storing network monitor context information.
- */
-typedef struct
-{
-    u_arraylist_t *netInterfaceList;
-    ca_thread_pool_t threadPool;
-    CANetworkStatus_t nwConnectivityStatus;
-    CAIPConnectionStateChangeCallback networkChangeCb;
-} CAIPNetworkMonitorContext;
-
-/**
- * @var g_networkMonitorContext
- * @brief  network monitor context.
- */
-static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
-
-/**
- * @var g_networkMonitorContextMutex
- * @brief  Mutex for synchronizing access to cached interface and IP address information.
- */
-static ca_mutex g_networkMonitorContextMutex = NULL;
-
-/**
- * @var g_jvm
- * @brief pointer to store JavaVM
- */
-static JavaVM *g_jvm = NULL;
-
-/**
- * @var g_context
- * @brief pointer to store Application Context
- */
-static jobject g_context = NULL;
-
-/**
- * @fn CAIPUpdateInterfaceInformation
- * @brief This methods gets local interface name and IP address information.
- */
-static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList);
-/**
- * @fn CACreateIPJNIInterfaceObject
- * @brief creates new instance of CaIpInterface through JNI
- */
-static CAResult_t CACreateIPJNIInterfaceObject(jobject context);
-
-/**
- * @fn CAIPSendNetworkChangeCallback
- * @brief updates network status to IP adapter
- */
-static void CAIPSendNetworkChangeCallback(CANetworkStatus_t currNetworkStatus);
-
-CAResult_t CAIPJniInit()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniInit");
-    g_jvm = CANativeJNIGetJavaVM();
-
-    if (!g_jvm)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "JNI initialize error");
-        return CA_STATUS_FAILED;
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPJniSetContext()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPJniSetContext");
-    g_context = (jobject) CANativeJNIGetContext();
-
-    if (!g_context)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to get application context");
-        return CA_STATUS_FAILED;
-    }
-
-    return CA_STATUS_OK;
-}
-
-CAResult_t CACreateIPJNIInterfaceObject(jobject context)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACreateIPJNIInterfaceObject");
-
-    VERIFY_NON_NULL(context, IP_MONITOR_TAG, "context");
-
-    JNIEnv* env;
-
-    if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get JNIEnv pointer");
-        return CA_STATUS_FAILED;
-    }
-
-    //getApplicationContext
-    jclass contextClass = (*env)->FindClass(env, "android/content/Context");
-    if (!contextClass)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get context object class");
-        return CA_STATUS_FAILED;
-    }
-
-    jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
-                                                                "getApplicationContext",
-                                                                "()Landroid/content/Context;");
-    if (!getApplicationContextMethod)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext method");
-        return CA_STATUS_FAILED;
-    }
-
-    jobject gApplicationContext = (*env)->CallObjectMethod(env, context,
-                                                           getApplicationContextMethod);
-    if (!getApplicationContextMethod)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get getApplicationContext");
-        return CA_STATUS_FAILED;
-    }
-
-    //Create CaIpInterface jni instance
-    jclass IPJniInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface");
-    if (!IPJniInterface)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get CaIpInterface class");
-        return CA_STATUS_FAILED;
-    }
-
-    jmethodID IPInterfaceConstructorMethod = (*env)->GetMethodID(env, IPJniInterface, "<init>",
-                                                                   "(Landroid/content/Context;)V");
-    if (!IPInterfaceConstructorMethod)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Could not get CaIpInterface constructor method");
-        return CA_STATUS_FAILED;
-    }
 
-    (*env)->NewObject(env, IPJniInterface, IPInterfaceConstructorMethod, gApplicationContext);
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "Create CaIpInterface instance, success");
+#define TAG "IP_MONITOR"
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-static CAResult_t CAIPUpdateInterfaceInformation(u_arraylist_t **netInterfaceList)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
-    /* Get a socket handle. */
-    int sck = -1;
-#ifdef SOCK_CLOEXEC
-    sck = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
-#endif
-
-    if ( -1 == sck)
-    {
-        sck=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-    }
+char *getHostIPAddress(const char *ifa_name) {
+    static char address[INET_ADDRSTRLEN] = {};
+    memset(&address, 0, INET_ADDRSTRLEN);
+    struct ifreq ifr;
+    int sck, status, len = sizeof(ifr.ifr_name) - 1;
+    char *ip;
 
-    if (sck < 0)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Error in socket creation");
-        return CA_STATUS_FAILED;
+    if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+        return NULL;
     }
 
-    char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
-    struct ifconf ifc;
-
-    /* Query available interfaces. */
-    ifc.ifc_len = MAX_INTERFACE_INFO_LENGTH;
-    ifc.ifc_buf = buf;
-
-    if (ioctl(sck, SIOCGIFCONF, &ifc) < 0)
-    {
+    strncpy(ifr.ifr_name, ifa_name, len);
+    ifr.ifr_name[len] = '\0';
+    if ((status = ioctl(sck, SIOCGIFADDR, &ifr)) < 0) {
         close(sck);
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get interface info");
-        return CA_STATUS_FAILED;
-    }
-
-    /* Iterate through the list of interfaces. */
-    struct ifreq* ifr = ifc.ifc_req;
-    int32_t interfaces = ifc.ifc_len / sizeof(struct ifreq);
-
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPUpdateInterfaceInformation : %d", interfaces);
-
-    if(0 == interfaces)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "no interfaces");
-        return CA_STATUS_FAILED;
-    }
-
-    for (int32_t i = 0; i < interfaces; i++)
-    {
-        struct ifreq temp_ifr = { 0 };
-        struct ifreq* item = &ifr[i];
-
-        char interfaceAddress[CA_IPADDR_SIZE] = { 0 };
-        char interfaceSubnetMask[CA_IPADDR_SIZE] = { 0 };
-        socklen_t len = sizeof(struct sockaddr_in);
-
-        OICStrcpy(temp_ifr.ifr_name, sizeof(temp_ifr.ifr_name), item->ifr_name);
-
-        if (ioctl(sck, SIOCGIFFLAGS, &temp_ifr))
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG,
-                    "CAIPUpdateInterfaceInformation, SIOCGIFFLAGS Failed");
-            close(sck);
-            return CA_STATUS_FAILED;
-        }
-
-        if ((temp_ifr.ifr_flags & IFF_LOOPBACK)
-            || !(temp_ifr.ifr_flags & IFF_UP) || !(temp_ifr.ifr_flags & IFF_RUNNING))
-        {
-            OIC_LOG_V(ERROR, IP_MONITOR_TAG,
-                      "interface is not up or not running or loopback = %x", temp_ifr.ifr_flags);
-            continue;
-        }
-
-        if (AF_INET != ((struct sockaddr_in*) &item->ifr_addr)->sin_family)
-        {
-            continue;
-        }
-
-        //get the interface ip address
-        if (0 != getnameinfo(&item->ifr_addr, len, interfaceAddress, sizeof(interfaceAddress),
-                             NULL, 0, NI_NUMERICHOST))
-        {
-            OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
-                    strerror(errno));
-            close(sck);
-            return CA_STATUS_FAILED;
-        }
-
-        if (ioctl((int) sck, SIOCGIFNETMASK, item) < 0)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG,
-                    "CAIPUpdateInterfaceInformation, SIOCGIFNETMASK Failed");
-            close(sck);
-            return CA_STATUS_FAILED;
-        }
-
-        // get the interface subnet mask
-        if (0 != getnameinfo(&item->ifr_netmask, len, interfaceSubnetMask,
-                             sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
-        {
-            OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
-                    strerror(errno));
-            close(sck);
-            return CA_STATUS_FAILED;
-        }
-
-        CANetInfo_t *netInfo = (CANetInfo_t *) OICCalloc(1, sizeof(CANetInfo_t));
-        if (!netInfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-            close(sck);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-
-        // set interface name
-        OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), item->ifr_name);
-
-        // set local ip address
-        OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), interfaceAddress);
-
-        // set subnet mask
-        OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), interfaceSubnetMask);
-
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) netInfo);
-        if (CA_STATUS_OK != result)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
-            close(sck);
-            return CA_STATUS_FAILED;
-        }
-
-        OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "ipAddress : %s, interfaceName : %s, subnetmask : %s",
-                netInfo->ipAddress, netInfo->interfaceName, netInfo->subnetMask);
+        return NULL;
     }
-
     close(sck);
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
+    ip = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr);
+    len = sizeof(address) - 1;
+    strncpy(address, ip, len);
+    address[len] = '\0';
+    return address;
 }
 
-static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
-                                      const CANetInfo_t *info)
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 {
-    VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
-    VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
-
-    uint32_t list_length = u_arraylist_length(netInterfaceList);
-    for (uint32_t list_index = 0; list_index < list_length; list_index++)
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
     {
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, list_index);
-        if (!netInfo)
-        {
-            continue;
-        }
-        if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
-        {
-            return false;
-        }
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
     }
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
-    return true;
-}
-
-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++)
+    char* ipAddr = getHostIPAddress("wlan0");
+    if (NULL == ipAddr)
     {
-        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;
-            }
-        }
-    }
+        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+        u_arraylist_destroy(iflist);
+        return NULL;
+    } 
+    OIC_LOG_V(DEBUG, TAG, "Got ifaddrs:: %s", ipAddr);
 
-    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;
+    struct in_addr inaddr;
+    inet_pton(AF_INET, ipAddr, &(inaddr));
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "New Interface found");
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));;
+    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "wlan0");
+    ifitem->index = 0; //if_nametoindex("wlan0");
+    ifitem->family = AF_INET; //we support ipv4 only
+    ifitem->ipv4addr = inaddr.s_addr;
+    ifitem->flags = IFF_UP|IFF_RUNNING;
 
-    CAResult_t result = u_arraylist_add(g_networkMonitorContext->netInterfaceList,
-                                        (void *) newNetInfo);
+    CAResult_t result = u_arraylist_add(iflist, ifitem);
     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;
-}
-
-static CAResult_t CAInitializeNetworkMonitorMutexes()
-{
-    if (!g_networkMonitorContextMutex)
-    {
-        g_networkMonitorContextMutex = ca_mutex_new();
-        if (!g_networkMonitorContextMutex)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-
-    if (!g_stopNetworkMonitorMutex)
-    {
-        g_stopNetworkMonitorMutex = ca_mutex_new();
-        if (!g_stopNetworkMonitorMutex)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc  failed");
-            ca_mutex_free(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-    return CA_STATUS_OK;
-}
-
-static void CADestroyNetworkMonitorMutexes()
-{
-    ca_mutex_free(g_networkMonitorContextMutex);
-    g_networkMonitorContextMutex = NULL;
-
-    ca_mutex_free(g_stopNetworkMonitorMutex);
-    g_stopNetworkMonitorMutex = NULL;
-}
-
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPInitializeNetworkMonitor IN");
-
-    VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
-
-    CAResult_t ret = CAIPJniInit();
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Initialization failed");
-        return ret;
-    }
-
-    ret = CAIPJniSetContext();
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPJniSetContext failed");
-        return ret;
-    }
-
-    ret = CACreateIPJNIInterfaceObject(g_context);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "unable to create CaIpInterface instance");
-        return ret;
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        goto exit;
     }
 
-    ret = CAInitializeNetworkMonitorMutexes();
+    OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
 
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
-        return CA_STATUS_FAILED;
-    }
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-    g_networkMonitorContext = (CAIPNetworkMonitorContext *) OICCalloc(
-            1, sizeof(*g_networkMonitorContext));
-    if (!g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-    g_networkMonitorContext->threadPool = threadPool;
-
-    g_networkMonitorContext->netInterfaceList = u_arraylist_create();
-    if (!g_networkMonitorContext->netInterfaceList)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
-        OICFree(g_networkMonitorContext);
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    CAIPUpdateInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
-
-    if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
-    {
-        g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
-    }
-    else
-    {
-        g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAIPTerminateNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    g_networkMonitorContext->threadPool = NULL;
-
-    CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
-
-    g_networkMonitorContext->netInterfaceList = NULL;
-    g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    g_networkMonitorContext->networkChangeCb = NULL;
-    g_networkMonitorContext->threadPool = NULL;
-
-    OICFree(g_networkMonitorContext);
-    g_networkMonitorContext = NULL;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-    g_stopNetworkMonitor = true;
-    ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
-    CADestroyNetworkMonitorMutexes();
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-CAResult_t CAIPStartNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-    g_stopNetworkMonitor = false;
-    ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStopNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_STATUS_FAILED;
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-    if (!g_stopNetworkMonitor)
-    {
-        g_stopNetworkMonitor = true;
-    }
-    else
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
-    }
-    ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
-            list_length);
-    for (uint32_t list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
-                g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
-        {
-            continue;
-        }
-        OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
-                  info->ipAddress);
-        CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
-        if (!newNetinfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-
-        *newNetinfo = *info;
-
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *) newNetinfo);
-        if (CA_STATUS_OK != result)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_STATUS_FAILED;
-        }
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
-    VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG, "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
-    for (uint32_t list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *) u_arraylist_get(
-                g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
-        {
-            OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
-                      "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
-            *subnetMask = OICStrdup(info->subnetMask);
-            break;
-        }
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-bool CAIPIsConnected()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
-        return false;
-    }
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return false;
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return true;
-}
-
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
-        return;
-    }
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-    g_networkMonitorContext->networkChangeCb = callback;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-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");
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class)
-{
-    CANetworkStatus_t currNetworkStatus = CA_INTERFACE_UP;
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "caIpStateEnabled");
-
-    CAIPSendNetworkChangeCallback(currNetworkStatus);
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class)
-{
-    CANetworkStatus_t currNetworkStatus = CA_INTERFACE_DOWN;
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "caIpStateDisabled");
+    return iflist;
 
-    CAIPSendNetworkChangeCallback(currNetworkStatus);
+exit:
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
 
index 3c997ad..3e234df 100644 (file)
@@ -68,16 +68,16 @@ void CAIPSetUnicastPort(uint16_t port)
     return;
 }
 
-uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf,
-                      uint32_t bufLen, bool isMulticast)
+void CAIPSendData(CAEndpoint_t *endpoint, const void *buf,
+                  uint32_t bufLen, bool isMulticast)
 {
     if (!isMulticast && 0 == g_unicastPort)
     {
         OIC_LOG(ERROR, TAG, "port 0");
-        return 0;
+        return;
     }
 
-    VERIFY_NON_NULL(endpoint, TAG, "endpoint");
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint");
 
     int socketID = 0;
     uint16_t port = endpoint->port;
@@ -87,7 +87,7 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf,
                                             g_unicastPort, &socketID) != CA_STATUS_OK)
         {
             OIC_LOG(ERROR, TAG, "init mcast err");
-            return 0;
+            return;
         }
         OIC_LOG_V(DEBUG, TAG, "MPORT:%d", port);
         OIC_LOG_V(DEBUG, TAG, "LPORT:%d", g_unicastPort);
@@ -100,7 +100,7 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf,
             if (CAArduinoInitUdpSocket(&port, &socketID) != CA_STATUS_OK)
             {
                 OIC_LOG(ERROR, TAG, "init ucast err");
-                return 0;
+                return;
             }
         }
         else
@@ -116,23 +116,26 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *buf,
                                    &parsedPort) != CA_STATUS_OK)
     {
         OIC_LOG(ERROR, TAG, "parse fail");
-        return 0;
+        return;
     }
 
     if (bufLen > 65535) // Max value for uint16_t
     {
         // This will never happen as max buffer size we are dealing with is COAP_MAX_PDU_SIZE
         OIC_LOG(ERROR, TAG, "Size exceeded");
-        return 0;
+        return;
     }
 
     ret = sendto(socketID, (const uint8_t *)buf, (uint16_t)bufLen, ipAddr, port);
+    if (ret <= 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "SendData failed: %d", ret);
+    }
     if (g_sockID != socketID)
     {
         close(socketID);
     }
 
     OIC_LOG(DEBUG, TAG, "OUT");
-    return ret;
 }
 
index 724bcdc..9dda5aa 100644 (file)
@@ -49,13 +49,13 @@ void CAIPSetUnicastPort(uint16_t port)
 
 }
 
-uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data,
-                      uint32_t dataLength, bool isMulticast)
+void CAIPSendData(CAEndpoint_t *endpoint,
+                  const void *data, uint32_t dataLength, bool isMulticast)
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
-    VERIFY_NON_NULL_RET(data, TAG, "data", 0);
-    VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", 0);
+    VERIFY_NON_NULL_VOID(data, TAG, "data");
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint");
 
     OIC_LOG_V(DEBUG, TAG, "remoteip: %s", endpoint->addr);
     OIC_LOG_V(DEBUG, TAG, "port: %d", endpoint->port);
@@ -67,14 +67,14 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data,
     if (res != CA_STATUS_OK)
     {
         OIC_LOG_V(ERROR, TAG, "Remote adrs parse fail %d", res);
-        return 0;
+        return;
     }
 
     IPAddress remoteIp(ip);
     Udp.beginPacket(remoteIp, endpoint->port);
 
     uint32_t bytesWritten = 0;
-    while(bytesWritten < dataLength)
+    while (bytesWritten < dataLength)
     {
         // get remaining bytes
         size_t writeCount = dataLength - bytesWritten;
@@ -94,9 +94,9 @@ uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data,
     if (Udp.endPacket() == 0)
     {
         OIC_LOG(ERROR, TAG, "Failed to send");
-        return 0;
+        return;
     }
     OIC_LOG(DEBUG, TAG, "OUT");
-    return bytesWritten;
+    return;
 }
 
index 61da510..1e8c208 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file caipnwmonitor.cpp
  * @brief This file is to keep design in sync with other platforms.  Right now there is no
- *        api for network monitioring in arduino.
+ *        api for network monitoring in arduino.
  */
 
 #include "caipinterface.h"
 #include "caipadapter.h"
 #include "caadapterutils.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
 #define TAG "IPNW"
 
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStartNetworkMonitor(void)
-{
-    return CA_STATUS_OK;
-}
+// Since the CA abstraction expects a value for "family", AF_INET will be
+// defined & used (as-is defined in the linux socket headers).
+#define AF_INET (2)
 
-void CAIPGetSubnetMask(char *subnetMask, int32_t addrLen)
+/// Retrieves the IP address assigned to Arduino Ethernet shield
+void CAArduinoGetInterfaceAddress(uint32_t *address)
 {
     OIC_LOG(DEBUG, TAG, "IN");
-    VERIFY_NON_NULL_VOID(subnetMask, TAG, "subnetMask");
+    VERIFY_NON_NULL_VOID(address, TAG, "address");
 
     //TODO : Fix this for scenarios when this API is invoked when device is not connected
     uint8_t rawIPAddr[4];
-    if (addrLen < CA_IPADDR_SIZE)
-    {
-        OIC_LOG(ERROR, TAG, "Invalid addrLen");
-        return;
-    }
-
-    W5100.getSubnetMask(rawIPAddr);
-    snprintf(subnetMask, addrLen, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2],
-             rawIPAddr[3]);
+    W5100.getIPAddress(rawIPAddr);
+    *address = (uint32_t) rawIPAddr;
 
-    OIC_LOG_V(DEBUG, TAG, "subnetMask:%s", subnetMask);
+    OIC_LOG_V(DEBUG, TAG, "address:%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1],
+              rawIPAddr[2], rawIPAddr[3]);
     OIC_LOG(DEBUG, TAG, "OUT");
     return;
 }
 
-/// Retrieves the IP address assigned to Arduino Ethernet shield
-void CAArduinoGetInterfaceAddress(char *address, int32_t addrLen)
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 {
-    OIC_LOG(DEBUG, TAG, "IN");
-    VERIFY_NON_NULL_VOID(address, TAG, "address");
+    CAResult_t result;
 
-    //TODO : Fix this for scenarios when this API is invoked when device is not connected
-    uint8_t rawIPAddr[4];
-    if (addrLen < CA_IPADDR_SIZE)
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
     {
-        OIC_LOG(ERROR, TAG, "Invalid addrLen");
-        return;
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
     }
 
-    W5100.getIPAddress(rawIPAddr);
-    snprintf(address, addrLen, "%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2],
-             rawIPAddr[3]);
-
-    OIC_LOG_V(DEBUG, TAG, "address:%s", address);
-    OIC_LOG(DEBUG, TAG, "OUT");
-    return;
-}
-
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-    if (!netInfo)
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+    if (!ifitem)
     {
         OIC_LOG(ERROR, TAG, "Malloc failed");
-        return CA_STATUS_FAILED;
+        goto exit;
     }
 
-    CAArduinoGetInterfaceAddress(netInfo->ipAddress, CA_IPADDR_SIZE);
+    // Since Arduino currently only supports one interface, the next 4 lines are sufficient.
+    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "ETH");
+    ifitem->index = 1;
+    ifitem->family = AF_INET;
+    ifitem->flags = 0;
+    CAArduinoGetInterfaceAddress(&ifitem->ipv4addr);
 
-    CAIPGetSubnetMask(netInfo->subnetMask, CA_IPADDR_SIZE);
-
-    // set interface name
-    strncpy(netInfo->interfaceName, "ETH", strlen(netInfo->interfaceName));
-
-    CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
+    result = u_arraylist_add(iflist, ifitem);
     if (CA_STATUS_OK != result)
     {
-        OIC_LOG(ERROR, TAG, "u_arraylist_add failed");
-        return result;
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        goto exit;
     }
-    return CA_STATUS_OK;
-}
 
-bool CAIPIsConnected(void)
-{
-    return true;
-}
+    OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
 
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
-    return;
-}
+    return iflist;
 
-CAResult_t CAIPStopNetworkMonitor(void)
-{
-    return CA_STATUS_OK;
+exit:
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
 
-void CAIPTerminateNetworkMonitor(void)
-{
-    return;
-}
index 3268b6c..cc79fc9 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file caipnwmonitor.cpp
  * @brief This file is to keep design in sync with other platforms.  Right now there is no
- *        api for network monitioring in arduino.
+ *        api for network monitoring in arduino.
  */
 
 #include "caipinterface.h"
 #include "caipadapter.h"
 #include "caadapterutils.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
 #define TAG "IPNW"
 
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStartNetworkMonitor(void)
-{
-    return CA_STATUS_OK;
-}
+// Since the CA abstraction expects a value for "family", AF_INET will be
+// defined & used (as-is defined in the linux socket headers).
+#define AF_INET (2)
 
-void CAIPGetSubnetMask(char *subnetMaskAddr, int32_t addrLen)
+/// Retrieves the IP address assigned to Arduino WiFi shield
+void CAArduinoGetInterfaceAddress(uint32_t *address)
 {
     OIC_LOG(DEBUG, TAG, "IN");
     if (WiFi.status() != WL_CONNECTED)
@@ -60,87 +56,54 @@ void CAIPGetSubnetMask(char *subnetMaskAddr, int32_t addrLen)
         return;
     }
 
-    VERIFY_NON_NULL_VOID(subnetMaskAddr, TAG, "Invalid Input");
-    if (addrLen < CA_IPADDR_SIZE)
-    {
-        OIC_LOG_V(ERROR, TAG, "AddrLen MUST be atleast %d", CA_IPADDR_SIZE);
-        return;
-    }
+    VERIFY_NON_NULL_VOID(address, TAG, "Invalid address");
 
-    IPAddress ip = WiFi.subnetMask();
-    snprintf((char *)subnetMaskAddr, addrLen, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+    IPAddress ip = WiFi.localIP();
+    *address = (uint32_t) ip;
 
-    OIC_LOG_V(DEBUG, TAG, "Wifi shield subnet mask is: %s", subnetMaskAddr);
+    OIC_LOG_V(DEBUG, TAG, "Wifi shield address is: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
     OIC_LOG(DEBUG, TAG, "OUT");
     return;
 }
 
-/// Retrieves the IP address assigned to Arduino WiFi shield
-void CAArduinoGetInterfaceAddress(char *address, int32_t addrLen)
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 {
-    OIC_LOG(DEBUG, TAG, "IN");
-    if (WiFi.status() != WL_CONNECTED)
-    {
-        OIC_LOG(DEBUG, TAG, "No WIFI");
-        return;
-    }
+    CAResult_t result = CA_STATUS_OK;
 
-    VERIFY_NON_NULL_VOID(address, TAG, "Invalid address");
-    if (addrLen < CA_IPADDR_SIZE)
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
     {
-        OIC_LOG_V(ERROR, TAG, "AddrLen MUST be atleast %d", CA_IPADDR_SIZE);
-        return;
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
     }
 
-    IPAddress ip = WiFi.localIP();
-    snprintf((char *)address, addrLen, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-
-    OIC_LOG_V(DEBUG, TAG, "Wifi shield address is: %s", address);
-    OIC_LOG(DEBUG, TAG, "OUT");
-    return;
-}
-
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-    if (!netInfo)
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+    if (!ifitem)
     {
         OIC_LOG(ERROR, TAG, "Malloc failed");
-        return CA_STATUS_FAILED;
+        goto exit;
     }
 
-    CAArduinoGetInterfaceAddress(netInfo->ipAddress, CA_IPADDR_SIZE);
-
-    CAIPGetSubnetMask(netInfo->subnetMask, CA_IPADDR_SIZE);
+    // Since Arduino currently only supports one interface, the next 4 lines are sufficient.
+    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "WIFI");
+    ifitem->index = 1;
+    ifitem->family = AF_INET;
+    ifitem->flags = 0;
+    CAArduinoGetInterfaceAddress(&ifitem->ipv4addr);
 
-    // set interface name
-    strncpy(netInfo->interfaceName, "WIFI", strlen(netInfo->interfaceName));
-
-    CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
+    result = u_arraylist_add(iflist, ifitem);
     if (CA_STATUS_OK != result)
     {
-        OIC_LOG(ERROR, TAG, "u_arraylist_add failed");
-        return result;
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        goto exit;
     }
-    return CA_STATUS_OK;
-}
 
-bool CAIPIsConnected(void)
-{
-    return true;
-}
+    OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
 
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
-    return;
-}
+    return iflist;
 
-CAResult_t CAIPStopNetworkMonitor(void)
-{
-    return CA_STATUS_OK;
+exit:
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
 
-void CAIPTerminateNetworkMonitor(void)
-{
-    return;
-}
index a698260..5adb1a2 100644 (file)
@@ -35,6 +35,7 @@
 #include "caipadapterutils_eth.h"
 #include "caadapterutils.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
 #define TAG "IPS"
 
@@ -132,6 +133,23 @@ CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multic
     return CA_STATUS_OK;
 }
 
+CAResult_t CAIPStartServer()
+{
+    uint16_t unicastPort = 55555;
+
+    CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret);
+    }
+    ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret);
+    }
+    return ret;
+}
+
 CAResult_t CAIPStopUnicastServer()
 {
     OIC_LOG(DEBUG, TAG, "IN");
@@ -150,20 +168,14 @@ CAResult_t CAIPStopMulticastServer()
     return CA_STATUS_OK;
 }
 
-CAResult_t CAIPStopServer(const char *interfaceAddress)
-{
-    /* For arduino, Server will be running in only one interface */
-    return CAIPStopAllServers();
-}
-
-CAResult_t CAIPStopAllServers()
+void CAIPStopServer()
 {
     OIC_LOG(DEBUG, TAG, "IN");
     CAResult_t result = CAIPStopUnicastServer();
     if (CA_STATUS_OK != result)
     {
         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
-        return result;
+        return;
     }
     CAIPSetUnicastSocket(-1);
     CAIPSetUnicastPort(0);
@@ -174,7 +186,6 @@ CAResult_t CAIPStopAllServers()
         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
     }
     OIC_LOG(DEBUG, TAG, "OUT");
-    return result;
 }
 
 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
@@ -290,3 +301,49 @@ void CAIPPullData()
 {
     CAArduinoCheckData();
 }
+
+CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    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);
+
+    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, 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);
+
+        OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
+        eps[j].flags = CA_IPV4;
+        eps[j].adapter = CA_ADAPTER_IP;
+        eps[j].interface = 0;
+        eps[j].port = 0;
+        j++;
+    }
+
+    *info = eps;
+    *size = len;
+
+    u_arraylist_destroy(iflist);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
index 5c31cf9..3b982a5 100644 (file)
@@ -35,6 +35,7 @@
 #include "caipadapter.h"
 #include "caadapterutils.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
 #define TAG "IPS"
 
@@ -122,6 +123,23 @@ CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multic
     return CA_NOT_SUPPORTED;
 }
 
+CAResult_t CAIPStartServer()
+{
+    uint16_t unicastPort = 55555;
+
+    CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret);
+    }
+    ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret);
+    }
+    return ret;
+}
+
 CAResult_t CAIPStopUnicastServer()
 {
     OIC_LOG(DEBUG, TAG, "IN");
@@ -137,20 +155,14 @@ CAResult_t CAIPStopMulticastServer()
     return CAIPStopUnicastServer();
 }
 
-CAResult_t CAIPStopServer(const char *interfaceAddress)
-{
-    /* For arduino, Server will be running in only one interface */
-    return CAIPStopAllServers();
-}
-
-CAResult_t CAIPStopAllServers()
+void CAIPStopServer()
 {
     OIC_LOG(DEBUG, TAG, "IN");
     CAResult_t result = CAIPStopUnicastServer();
     if (CA_STATUS_OK != result)
     {
         OIC_LOG_V(ERROR, TAG, "stop ucast srv fail:%d", result);
-        return result;
+        return;
     }
     CAIPSetUnicastSocket(-1);
     CAIPSetUnicastPort(0);
@@ -161,7 +173,6 @@ CAResult_t CAIPStopAllServers()
         OIC_LOG_V(ERROR, TAG, "stop mcast srv fail:%d", result);
     }
     OIC_LOG(DEBUG, TAG, "OUT");
-    return result;
 }
 
 void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port,
@@ -234,3 +245,49 @@ void CAIPPullData()
 {
     CAArduinoCheckData();
 }
+
+CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    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);
+
+    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, 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);
+
+        OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
+        eps[j].flags = CA_IPV4;
+        eps[j].adapter = CA_ADAPTER_IP;
+        eps[j].interface = 0;
+        eps[j].port = 0;
+        j++;
+    }
+
+    *info = eps;
+    *size = len;
+
+    u_arraylist_destroy(iflist);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
index 48905f6..3a320bd 100644 (file)
 #include "oic_string.h"
 
 /**
- * @def IP_ADAPTER_TAG
+ * @def TAG
  * @brief Logging tag for module name
  */
-#define IP_ADAPTER_TAG "IPAD"
-
-/**
- * @def CA_PORT
- * @brief Port to listen for incoming data
- */
-#ifdef ARDUINO
-#define CA_PORT   55555
-#else
-#define CA_PORT   0
-#endif
-
-/**
- * @def CA_SECURE_PORT
- * @brief Secured (unicast) port number as defined in COAP Specification, RFC-7252.
- */
-#define CA_SECURE_PORT   5684
-
-/**
- * @def CA_MCAST_PORT
- * @brief Multicast port number as defined in COAP Specification, RFC-7252.
- */
-#define CA_MCAST_PORT   5683
-
-/**
- * @def CA_MULTICAST_IP
- * @brief Multicast IP Address as defined in COAP Specification, RFC-7252.
- */
-#define CA_MULTICAST_IP "224.0.1.187"
+#define TAG "IP_ADAP"
 
 #ifndef SINGLE_THREAD
 /**
@@ -109,28 +81,13 @@ static CANetworkChangeCallback g_networkChangeCallback = NULL;
  */
 static CAErrorHandleCallback g_errorCallback = NULL;
 
-/**
- * @var g_threadPool
- * @brief ThreadPool for storing ca_thread_pool_t handle passed from CA
- */
-static ca_thread_pool_t g_threadPool = NULL;
-
-static void CAIPNotifyNetworkChange(const char *address, uint16_t port,
-                                    CANetworkStatus_t status);
-
-static void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status);
-
 static void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint,
                                  const void *data, uint32_t dataLength);
-static void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
-                             uint32_t dataLength, CAResult_t result);
 #ifdef __WITH_DTLS__
-static uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint,
-                                 const void *data, uint32_t dataLength);
+static void CAIPPacketSendCB(CAEndpoint_t *endpoint,
+                             const void *data, uint32_t dataLength);
 #endif
 
-static CAResult_t CAIPStopServers();
-
 #ifndef SINGLE_THREAD
 
 static CAResult_t CAIPInitializeQueueHandles();
@@ -140,19 +97,20 @@ static void CAIPDeinitializeQueueHandles();
 static void CAIPSendDataThread(void *threadData);
 
 static CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
-                                const void *data, uint32_t dataLength, bool isMulticast);
+                                const void *data, uint32_t dataLength,
+                                bool isMulticast);
 void CAFreeIPData(CAIPData *ipData);
 
 static void CADataDestroyer(void *data, uint32_t size);
 
 CAResult_t CAIPInitializeQueueHandles()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
     // Check if the message queue is already initialized
     if (g_sendQueueHandle)
     {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "send queue handle is already initialized!");
+        OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
         return CA_STATUS_OK;
     }
 
@@ -160,261 +118,70 @@ CAResult_t CAIPInitializeQueueHandles()
     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
     if (!g_sendQueueHandle)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!");
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
         return CA_MEMORY_ALLOC_FAILED;
     }
 
-    if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, g_threadPool,
-                                                   CAIPSendDataThread, CADataDestroyer))
+    if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
+                                (const ca_thread_pool_t)caglobals.ip.threadpool,
+                                CAIPSendDataThread, CADataDestroyer))
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Initialize send queue thread");
+        OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
         OICFree(g_sendQueueHandle);
         g_sendQueueHandle = NULL;
         return CA_STATUS_FAILED;
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
 void CAIPDeinitializeQueueHandles()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
     CAQueueingThreadDestroy(g_sendQueueHandle);
     OICFree(g_sendQueueHandle);
     g_sendQueueHandle = NULL;
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
-
-void CAIPSendDataThread(void *threadData)
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    CAIPData *ipData = (CAIPData *) threadData;
-    uint32_t sentData = -1;
-
-    if (!ipData)
-    {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Invalid ip data!");
-        return;
-    }
-
-    if (ipData->isMulticast)
-    {
-        //Processing for sending multicast
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Multicast Data is called");
-        strncpy(ipData->remoteEndpoint->addr, CA_MULTICAST_IP, MAX_ADDR_STR_SIZE_CA);
-        ipData->remoteEndpoint->port = CA_MCAST_PORT;
-        sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true);
-    }
-    else
-    {
-        //Processing for sending unicast
-#ifdef __WITH_DTLS__
-        if (ipData->remoteEndpoint->flags & CA_SECURE)
-        {
-            OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!");
-            CAResult_t result = CAAdapterNetDtlsEncrypt(ipData->remoteEndpoint,
-                                               ipData->data, ipData->dataLen);
-            if (CA_STATUS_OK != result)
-            {
-                OIC_LOG(ERROR, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!");
-                sentData = 0;
-            }
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG,
-                      "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
-        }
-        else
-        {
-            OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Unicast Data is called");
-            sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
-        }
-#else
-        sentData = CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
-#endif
-    }
-
-    if (0 == sentData)
-    {
-        g_errorCallback(ipData->remoteEndpoint, ipData->data, ipData->dataLen,
-                        CA_SEND_FAILED);
-    }
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
-
-CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data,
-                         uint32_t dataLength, bool isMulticast)
-{
-    VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "IPData is NULL", NULL);
-
-    CAIPData *ipData = (CAIPData *) OICMalloc(sizeof(CAIPData));
-    if (!ipData)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!");
-        return NULL;
-    }
-
-    ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
-    ipData->data = (void *) OICMalloc(dataLength);
-    if (!ipData->data)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory allocation failed!");
-        CAFreeIPData(ipData);
-        return NULL;
-    }
-
-    memcpy(ipData->data, data, dataLength);
-    ipData->dataLen = dataLength;
-
-    ipData->isMulticast = isMulticast;
-
-    return ipData;
-}
-
-void CAFreeIPData(CAIPData *ipData)
-{
-    VERIFY_NON_NULL_VOID(ipData, IP_ADAPTER_TAG, "ipData is NULL");
-
-    CAFreeEndpoint(ipData->remoteEndpoint);
-    OICFree(ipData->data);
-    OICFree(ipData);
-}
-
-void CADataDestroyer(void *data, uint32_t size)
-{
-    CAIPData *etdata = (CAIPData *) data;
-
-    CAFreeIPData(etdata);
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
-#endif
 
-void CAIPNotifyNetworkChange(const char *address, uint16_t port, CANetworkStatus_t status)
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    VERIFY_NON_NULL_VOID(address, IP_ADAPTER_TAG, "address is NULL");
-
-    CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
-                                                         CA_ADAPTER_IP,
-                                                         address, port);
-    if (!localEndpoint)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "localEndpoint creation failed!");
-        return;
-    }
-
-    if (g_networkChangeCallback)
-    {
-        g_networkChangeCallback(localEndpoint, status);
-    }
-    else
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "g_networkChangeCallback is NULL");
-    }
-
-    CAFreeEndpoint(localEndpoint);
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
+#endif // SINGLE_THREAD
 
 void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    VERIFY_NON_NULL_VOID(ipAddress, IP_ADAPTER_TAG, "ipAddress is NULL");
-
-    if (CA_INTERFACE_UP == status)
-    {
-        uint16_t port = CA_PORT;
-        CAResult_t ret = CAIPStartUnicastServer(ipAddress, &port, false);
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Unicast server started on %d port", port);
-        }
-        else
-        {
-            OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start Unicast server port[%d]", ret);
-        }
-
-#ifdef __WITH_DTLS__
-        port = CA_SECURE_PORT;
-        ret = CAIPStartUnicastServer(ipAddress, &port, true);
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Secure Unicast server started on %d", port);
-        }
-        else
-        {
-            OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start secure Unicast server [%d]",
-                      ret);
-        }
-#endif
-        ret = CAIPStartMulticastServer(ipAddress, CA_MULTICAST_IP, CA_MCAST_PORT);
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Multicast server started on port[%d]",
-                      CA_MCAST_PORT);
-        }
-        else
-        {
-            OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start Multicast server port[%d]",
-                      ret);
-        }
-
-        // Notify network change to CA
-        CAIPNotifyNetworkChange(ipAddress, port, status);
-    }
-    else
-    {
-        CAIPNotifyNetworkChange(ipAddress, 0, status);
-
-        // Stop Unicast, Secured unicast and Multicast servers
-        CAIPStopServer(ipAddress);
-    }
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "IN");
 }
 
 #ifdef __WITH_DTLS__
-uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
+static void CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    VERIFY_NON_NULL_RET(endpoint, IP_ADAPTER_TAG, "endpoint is NULL", 0);
-    VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data is NULL", 0);
-
-    uint32_t sentLength = CAIPSendData(endpoint, data, dataLength, false);
-
-    if (sentLength == 0)
-    {
-        g_errorCallback(endpoint, data, dataLength, CA_SEND_FAILED);
-    }
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Successfully sent %d of encrypted data!", sentLength);
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    CAIPSendData(endpoint, data, dataLength, false);
 
-    return sentLength;
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
 #endif
 
 void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
                           uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "ipAddress is NULL");
-    VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL");
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
 
-    OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+    OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
 
     void *buf = OICCalloc(dataLength + 1, sizeof (char));
     if (!buf)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!");
+        OIC_LOG(ERROR, TAG, "Memory Allocation failed!");
         return;
     }
     memcpy(buf, data, dataLength);
@@ -427,22 +194,22 @@ void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
     {
         OICFree(buf);
     }
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
 
 void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data,
                        uint32_t dataLength, CAResult_t result)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "endpoint is NULL");
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
 
-    VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
 
     void *buf = (void*)OICMalloc(sizeof(char) * dataLength);
     if (!buf)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!");
+        OIC_LOG(ERROR, TAG, "Memory Allocation failed!");
         return;
     }
     memcpy(buf, data, dataLength);
@@ -455,48 +222,39 @@ void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data,
         OICFree(buf);
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-
-    return;
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-int32_t CAIPSendDataInternal(const CAEndpoint_t *remoteEndpoint, const void *data,
-                             uint32_t dataLength, bool isMulticast)
+static void CAInitializeIPGlobals()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-#ifdef SINGLE_THREAD
-
-    // If remoteEndpoint is NULL, its Multicast, else its Unicast.
-    if(!isMulticast)
-    {
-        CAIPSendData(remoteEndpoint, data, dataLength, false);
-    }
-    else
-    {
-        CAEndpoint_t ep = { 0 };
-        strcpy(ep.addr, CA_MULTICAST_IP);
-        ep.port = CA_MCAST_PORT;
-        CAIPSendData(&ep, data, dataLength, true);
-    }
-#else
-    VERIFY_NON_NULL_RET(g_sendQueueHandle, IP_ADAPTER_TAG, "sendQueueHandle", -1);
-
-    // Create IPData to add to queue
-    CAIPData *ipData = CACreateIPData(remoteEndpoint, data, dataLength, isMulticast);
-
-    if (!ipData)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to create ipData!");
-        return -1;
-    }
-    else
-    {
-        // Add message to send queue
-        CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData));
-    }
-#endif
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return dataLength;
+    caglobals.ip.u6.fd  = -1;
+    caglobals.ip.u6s.fd = -1;
+    caglobals.ip.u4.fd  = -1;
+    caglobals.ip.u4s.fd = -1;
+    caglobals.ip.m6.fd  = -1;
+    caglobals.ip.m6s.fd = -1;
+    caglobals.ip.m4.fd  = -1;
+    caglobals.ip.m4s.fd = -1;
+    caglobals.ip.u6.port  = 0;
+    caglobals.ip.u6s.port = 0;
+    caglobals.ip.u4.port  = 0;
+    caglobals.ip.u4s.port = 0;
+    caglobals.ip.m6.port  = CA_COAP;
+    caglobals.ip.m6s.port = CA_SECURE_COAP;
+    caglobals.ip.m4.port  = CA_COAP;
+    caglobals.ip.m4s.port = CA_SECURE_COAP;
+
+    CATransportFlags_t flags = 0;
+    if (caglobals.client)
+    {
+        flags |= caglobals.clientFlags;
+    }
+    if (caglobals.server)
+    {
+        flags |= caglobals.serverFlags;
+    }
+    caglobals.ip.ipv6enabled = flags & CA_IPV6;
+    caglobals.ip.ipv4enabled = flags & CA_IPV4;
 }
 
 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
@@ -504,37 +262,22 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
                           CANetworkChangeCallback netCallback,
                           CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-    VERIFY_NON_NULL(registerCallback, IP_ADAPTER_TAG, "registerCallback");
-    VERIFY_NON_NULL(networkPacketCallback, IP_ADAPTER_TAG, "networkPacketCallback");
-    VERIFY_NON_NULL(netCallback, IP_ADAPTER_TAG, "netCallback");
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
+    VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
+    VERIFY_NON_NULL(netCallback, TAG, "netCallback");
 #ifndef SINGLE_THREAD
-    VERIFY_NON_NULL(handle, IP_ADAPTER_TAG, "thread pool handle");
+    VERIFY_NON_NULL(handle, TAG, "thread pool handle");
 #endif
 
-    g_threadPool = handle;
     g_networkChangeCallback = netCallback;
     g_networkPacketCallback = networkPacketCallback;
     g_errorCallback = errorCallback;
 
-    CAResult_t ret = CAIPInitializeNetworkMonitor(g_threadPool);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to initialize n/w monitor[%d]", ret);
-        return ret;
-    }
-    CAIPSetConnectionStateChangeCallback(CAIPConnectionStateCB);
-
-    ret = CAIPInitializeServer(g_threadPool);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to initialize server![%d]", ret);
-        CATerminateIP();
-        return ret;
-    }
+    CAInitializeIPGlobals();
+    caglobals.ip.threadpool = handle;
 
     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
-    CAIPSetErrorHandleCallback(CAIPErrorHandler);
 #ifdef __WITH_DTLS__
     CAAdapterNetDtlsInit();
 
@@ -553,359 +296,259 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
     ipHandler.terminate = CATerminateIP;
     registerCallback(ipHandler, CA_ADAPTER_IP);
 
-#ifndef SINGLE_THREAD
-    if (CA_STATUS_OK != CAIPInitializeQueueHandles())
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Initialize Queue Handle");
-        CATerminateIP();
-        return CA_STATUS_FAILED;
-    }
-#endif
-    OIC_LOG(INFO, IP_ADAPTER_TAG, "OUT");
+    OIC_LOG(INFO, TAG, "OUT IntializeIP is Success");
     return CA_STATUS_OK;
 }
 
 CAResult_t CAStartIP()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    // Start monitoring IP network
-    CAResult_t ret = CAIPStartNetworkMonitor();
+#ifdef SINGLE_THREAD
+    uint16_t unicastPort = 55555;
+    // Address is hardcoded as we are using Single Interface
+    CAResult_t ret = CAIPStartServer();
     if (CA_STATUS_OK != ret)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Start n/w monitor");
+        OIC_LOG_V(DEBUG, TAG, "CAIPStartServer failed[%d]", ret);
         return ret;
     }
-
-#ifndef SINGLE_THREAD
-    // Start send queue thread
-    if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
+#else
+    if (CA_STATUS_OK != CAIPInitializeQueueHandles())
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Start Send Data Thread");
+        OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
+        CATerminateIP();
         return CA_STATUS_FAILED;
     }
-#endif
 
-    bool retVal = CAIPIsConnected();
-    if (false == retVal)
-    {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IP is not Connected");
-        return CA_STATUS_OK;
-    }
-
-#ifdef ARDUINO
-    uint16_t unicastPort = CA_PORT;
-    // Address is hardcoded as we are using Single Interface
-    ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
-    if (CA_STATUS_OK != ret)
+    // Start send queue thread
+    if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
     {
-        OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Start unicast serv failed[%d]", ret);
-
+        OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
+        return CA_STATUS_FAILED;
     }
-#else
-    u_arraylist_t *netInterfaceList = u_arraylist_create();
-
-    VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
 
-    ret = CAIPGetInterfaceInfo(&netInterfaceList);
+    CAResult_t ret = CAIPStartServer((const ca_thread_pool_t)caglobals.ip.threadpool);
     if (CA_STATUS_OK != ret)
     {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to get IP interface info [%d]", ret);
-        CAClearNetInterfaceInfoList(netInterfaceList);
+        OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
         return ret;
     }
 
-    uint32_t listIndex = 0;
-    uint32_t listLength = u_arraylist_length(netInterfaceList);
-    for (listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
-        if (!netInfo)
-        {
-            continue;
-        }
-        uint16_t unicastPort = CA_PORT;
-        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, false);
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Unicast server started on %d port",
-                      unicastPort);
-        }
-
-#ifdef __WITH_DTLS__
-        unicastPort = CA_SECURE_PORT;
-        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, true);
-
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG,
-                      "Secure Unicast server started on %d port", unicastPort);
-        }
-#endif
-    }
-    CAClearNetInterfaceInfoList(netInterfaceList);
 #endif
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return ret;
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
 CAResult_t CAStartIPListeningServer()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    CAResult_t ret = CA_STATUS_OK;
-    bool retVal = CAIPIsConnected();
-    if (false == retVal)
-    {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IP not Connected");
-        return ret;
-    }
-
-#ifdef ARDUINO
-    //uint16_t multicastPort = CA_MCAST_PORT;
-    ret = CAIPStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, CA_MCAST_PORT);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret);
-    }
-#else
-    u_arraylist_t *netInterfaceList = u_arraylist_create();
-
-    VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
-
-    ret = CAIPGetInterfaceInfo(&netInterfaceList);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to get IP interface info [%d]", ret);
-        CAClearNetInterfaceInfoList(netInterfaceList);
-        return ret;
-    }
-
-    uint32_t listIndex = 0;
-    uint32_t listLength = u_arraylist_length(netInterfaceList);
-    for (listIndex = 0; listIndex < listLength; listIndex++)
-    {
-
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
-        if (!netInfo)
-        {
-            continue;
-        }
-
-        OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Ip address for multicast interface %s",
-                  netInfo->ipAddress);
-        ret = CAIPStartMulticastServer(netInfo->ipAddress, CA_MULTICAST_IP, CA_MCAST_PORT);
-        if (CA_STATUS_OK == ret)
-        {
-            OIC_LOG(INFO, IP_ADAPTER_TAG, "Multicast Server is Started Successfully");
-        }
-    }
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    CAClearNetInterfaceInfoList(netInterfaceList);
-#endif
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return ret;
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
 CAResult_t CAStartIPDiscoveryServer()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-    /* Both listening and discovery server are same */
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    OIC_LOG(DEBUG, TAG, "IN");
     return CAStartIPListeningServer();
 }
 
-int32_t CASendIPUnicastData(const CAEndpoint_t *remoteEndpoint,
+static int32_t CAQueueIPData(bool isMulticast, const CAEndpoint_t *endpoint,
                             const void *data, uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
+    VERIFY_NON_NULL_RET(data, TAG, "data", -1);
 
-    VERIFY_NON_NULL_RET(remoteEndpoint, IP_ADAPTER_TAG, "remoteEndpoint", -1);
-    VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1);
     if (0 == dataLength)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length");
+        OIC_LOG(ERROR, TAG, "Invalid Data Length");
         return -1;
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CAIPSendDataInternal(remoteEndpoint, data, dataLength, false);
-}
+#ifdef SINGLE_THREAD
 
-int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    CAIPSendData(endpoint, data, dataLength, isMulticast);
 
-    VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1);
-    if (0 == dataLength)
+#else
+
+    VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
+    // Create IPData to add to queue
+    CAIPData *ipData = CACreateIPData(endpoint, data, dataLength, isMulticast);
+    if (!ipData)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length");
+        OIC_LOG(ERROR, TAG, "Failed to create ipData!");
         return -1;
     }
+    // Add message to send queue
+    CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData));
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return dataLength;
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CAIPSendDataInternal(endpoint, data, dataLength, true);
+#endif // SINGLE_THREAD
 }
 
-CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint,
+                            const void *data, uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
+    return CAQueueIPData(false, endpoint, data, dataLength);
+}
 
-    VERIFY_NON_NULL(info, IP_ADAPTER_TAG, "info is NULL");
-    VERIFY_NON_NULL(size, IP_ADAPTER_TAG, "size is NULL");
+int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    return CAQueueIPData(true, endpoint, data, dataLength);
+}
 
-    bool retVal = CAIPIsConnected();
-    if (false == retVal)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "IP not Connected");
-        return CA_ADAPTER_NOT_ENABLED;
-    }
+CAResult_t CAReadIPData()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    CAIPPullData();
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
 
-    u_arraylist_t *netInterfaceList = u_arraylist_create();
+CAResult_t CAStopIP()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
+#ifdef __WITH_DTLS__
+    CAAdapterNetDtlsDeInit();
+#endif
 
-    CAResult_t ret = CAIPGetInterfaceInfo(&netInterfaceList);
-    if (CA_STATUS_OK != ret)
+#ifndef SINGLE_THREAD
+    if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
     {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "CAIPGetInterfaceInfo failed:%d", ret);
-        CAClearNetInterfaceInfoList(netInterfaceList);
-        return ret;
+        CAQueueingThreadStop(g_sendQueueHandle);
     }
 
-    uint32_t listLength = u_arraylist_length(netInterfaceList);
-    uint32_t netInfoSize = listLength;
-
-#ifdef __WITH_DTLS__
-    if (listLength)
-    {
-        netInfoSize = listLength * 2;
-    }
+    CAIPDeinitializeQueueHandles();
 #endif
 
-    CAEndpoint_t *conInfo = (CAEndpoint_t *)OICCalloc(netInfoSize, sizeof (CAEndpoint_t));
-    if (!conInfo)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Malloc Failed");
-        CAClearNetInterfaceInfoList(netInterfaceList);
-        return CA_MEMORY_ALLOC_FAILED;
-    }
+    CAIPStopServer();
 
-    uint32_t listIndex = 0;
-    uint32_t count = 0;
-    for (listIndex = 0; listIndex < listLength; listIndex++)
-    {
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
-        if (!netInfo)
-        {
-            continue;
-        }
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
 
-        conInfo[count].adapter = CA_ADAPTER_IP;
-        conInfo[count].flags = 0;
-        conInfo[count].port = CAGetServerPortNum(netInfo->ipAddress, false);
-        OICStrcpy(conInfo[count].addr,
-                  sizeof(conInfo[count].addr),
-                  netInfo->ipAddress);
+void CATerminateIP()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
 
 #ifdef __WITH_DTLS__
-        // copy secure unicast server information
-        {
-            count ++;
-            conInfo[count].adapter = CA_ADAPTER_IP;
-            conInfo[count].flags = CA_SECURE;
-            conInfo[count].port = CAGetServerPortNum(netInfo->ipAddress, true);
-            OICStrcpy(conInfo[count].addr,
-                  sizeof(conInfo[count].addr),
-                  netInfo->ipAddress);
-        }
+    CADTLSSetAdapterCallbacks(NULL, NULL, 0);
 #endif
-        count ++;
-    }
-    *size = count;
-    *info = conInfo;
-    CAClearNetInterfaceInfoList(netInterfaceList);
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
+    CAIPSetPacketReceiveCallback(NULL);
 
-CAResult_t CAReadIPData()
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-    CAIPPullData();
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
+#ifndef SINGLE_THREAD
+    CAIPDeinitializeQueueHandles();
+#endif
+
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-CAResult_t CAIPStopServers()
+#ifndef SINGLE_THREAD
+
+void CAIPSendDataThread(void *threadData)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    // Stop all unicast and multicast servers.
-    if (CA_STATUS_OK == CAIPStopAllServers())
+    CAIPData *ipData = (CAIPData *) threadData;
+    if (!ipData)
     {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAIPStopAllServers success");
+        OIC_LOG(DEBUG, TAG, "Invalid ip data!");
+        return;
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAStopIP()
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
+    if (ipData->isMulticast)
+    {
+        //Processing for sending multicast
+        OIC_LOG(DEBUG, TAG, "Send Multicast Data is called");
+        CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true);
+    }
+    else
+    {
+        //Processing for sending unicast
 #ifdef __WITH_DTLS__
-    CAAdapterNetDtlsDeInit();
+        if (ipData->remoteEndpoint->flags & CA_SECURE)
+        {
+            OIC_LOG(DEBUG, TAG, "CAAdapterNetDtlsEncrypt called!");
+            CAResult_t result = CAAdapterNetDtlsEncrypt(ipData->remoteEndpoint,
+                                               ipData->data, ipData->dataLen);
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG(ERROR, TAG, "CAAdapterNetDtlsEncrypt failed!");
+            }
+            OIC_LOG_V(DEBUG, TAG,
+                      "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
+        }
+        else
+        {
+            OIC_LOG(DEBUG, TAG, "Send Unicast Data is called");
+            CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
+        }
+#else
+        CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
 #endif
+    }
 
-    // Stop IP network monitor
-    CAIPStopNetworkMonitor();
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+#endif
 
 #ifndef SINGLE_THREAD
-    // Stop send queue thread
-    if (g_sendQueueHandle)
+
+CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data,
+                                     uint32_t dataLength, bool isMulticast)
+{
+    VERIFY_NON_NULL_RET(data, TAG, "IPData is NULL", NULL);
+
+    CAIPData *ipData = (CAIPData *) OICMalloc(sizeof(CAIPData));
+    if (!ipData)
     {
-        CAQueueingThreadStop(g_sendQueueHandle);
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return NULL;
     }
-#endif
 
-    // Stop Unicast, Secured unicast and Multicast servers running
-    CAResult_t result = CAIPStopServers();
-    if (CA_STATUS_OK != result)
+    ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
+    ipData->data = (void *) OICMalloc(dataLength);
+    if (!ipData->data)
     {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "stop srv fail:%d", result);
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        CAFreeIPData(ipData);
+        return NULL;
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return result;
-}
+    memcpy(ipData->data, data, dataLength);
+    ipData->dataLen = dataLength;
 
-void CATerminateIP()
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    ipData->isMulticast = isMulticast;
 
-    // Stop IP adapter
-    CAStopIP();
+    return ipData;
+}
 
-#ifdef __WITH_DTLS__
-    CADTLSSetAdapterCallbacks(NULL, NULL, 0);
-#endif
+void CAFreeIPData(CAIPData *ipData)
+{
+    VERIFY_NON_NULL_VOID(ipData, TAG, "ipData is NULL");
 
-    CAIPSetPacketReceiveCallback(NULL);
+    CAFreeEndpoint(ipData->remoteEndpoint);
+    OICFree(ipData->data);
+    OICFree(ipData);
+}
 
-    // Terminate IP server
-    CAIPTerminateServer();
+void CADataDestroyer(void *data, uint32_t size)
+{
+    CAIPData *etdata = (CAIPData *) data;
 
-    // Terminate network monitor
-    CAIPSetConnectionStateChangeCallback(NULL);
-    CAIPTerminateNetworkMonitor();
+    CAFreeIPData(etdata);
+}
 
-#ifndef SINGLE_THREAD
-    // Terminate message queue handler
-    CAIPDeinitializeQueueHandles();
-#endif
+#endif // SINGLE_THREAD
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
diff --git a/resource/csdk/connectivity/src/ip_adapter/caipclient.c b/resource/csdk/connectivity/src/ip_adapter/caipclient.c
deleted file mode 100644 (file)
index 4d57e70..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-#include "caipinterface.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <errno.h>
-
-#include "caadapterutils.h"
-
-/**
- * @def IP_CLIENT_TAG
- * @brief Logging tag for module name
- */
-#define IP_CLIENT_TAG "IP_CLIENT"
-#define OC_MULTICAST_IP "224.0.1.187"
-
-static uint32_t CASendData(const CAEndpoint_t *endpoint, const void *data,
-                           uint32_t dataLength, int sockfd)
-{
-    OIC_LOG(DEBUG, IP_CLIENT_TAG, "IN");
-
-    VERIFY_NON_NULL_RET(endpoint, IP_CLIENT_TAG, "IP address is NULL", 0);
-    VERIFY_NON_NULL_RET(data, IP_CLIENT_TAG, "data is NULL", 0);
-
-    if (0 == dataLength)
-    {
-        OIC_LOG(ERROR, IP_CLIENT_TAG, "Data length is 0!");
-        return 0;
-    }
-
-    if (0 > sockfd)
-    {
-        OIC_LOG(ERROR, IP_CLIENT_TAG, "Unicast Server is not running!");
-        return 0;
-    }
-
-    struct sockaddr_in destAddr = { 0 };
-    destAddr.sin_family = AF_INET;
-    destAddr.sin_port = htons(endpoint->port);
-
-    int ret = inet_pton(AF_INET, endpoint->addr, &(destAddr.sin_addr));
-    if (1 != ret)
-    {
-        OIC_LOG(ERROR, IP_CLIENT_TAG, "inet_pton failed!");
-        return 0;
-    }
-
-    ssize_t sendDataLength = sendto(sockfd, data, dataLength, 0, (struct sockaddr *) &destAddr,
-                                    sizeof(destAddr));
-    if (-1 == sendDataLength)
-    {
-        OIC_LOG_V(ERROR, IP_CLIENT_TAG, "sendto failed, Error code: %s",
-                  strerror(errno));
-        return 0;
-    }
-
-    OIC_LOG_V(INFO, IP_CLIENT_TAG, "Sending data is successful, sent bytes[%d] to ip[%s:%d]",
-              sendDataLength, endpoint->addr, endpoint->port);
-    OIC_LOG(DEBUG, IP_CLIENT_TAG, "OUT");
-    return sendDataLength;
-}
-
-uint32_t CAIPSendData(const CAEndpoint_t *endpoint, const void *data,
-                            uint32_t dataLength, bool isMulticast)
-{
-    u_arraylist_t *tempServerInfoList = u_arraylist_create();
-    if (!tempServerInfoList)
-    {
-        OIC_LOG(ERROR, IP_CLIENT_TAG, "u_arraylist_create failed");
-        return 0;
-    }
-
-    CAResult_t res = CAGetIPServerInfoList(&tempServerInfoList);
-    if (CA_STATUS_OK != res)
-    {
-        OIC_LOG(ERROR, IP_CLIENT_TAG, "CAGetIPServerInfoList failed");
-        CAClearServerInfoList(tempServerInfoList);
-        return 0;
-    }
-
-    uint32_t len = 0;
-    if (isMulticast || strcmp(endpoint->addr, OC_MULTICAST_IP) == 0)
-    {
-        uint32_t listIndex = 0;
-        uint32_t listLength = u_arraylist_length(tempServerInfoList);
-        for (listIndex = 0; listIndex < listLength; listIndex++)
-        {
-            CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList,
-                                                                      listIndex);
-            if (!info || info->isMulticastServer || (info->endpoint.flags & CA_SECURE))
-            {
-                continue;
-            }
-
-            if (info->socketFd < 0)
-            {
-                OIC_LOG(ERROR, IP_CLIENT_TAG, "Invalid Socket Fd");
-                continue;
-            }
-
-            OIC_LOG_V(DEBUG, IP_CLIENT_TAG,
-                    "CA IP Multicast SendData with src ip %s port %d sockFd %d",
-                    info->endpoint.addr, info->endpoint.port, info->socketFd);
-            len = CASendData(endpoint, data, dataLength, info->socketFd);
-        }
-    }
-    else
-    {
-        int sockFd = CAGetSocketFdForUnicastServer(tempServerInfoList, isMulticast, endpoint);
-        if (sockFd < 0)
-        {
-            OIC_LOG(ERROR, IP_CLIENT_TAG, "Invalid Socket Fd");
-            CAClearServerInfoList(tempServerInfoList);
-            return 0;
-        }
-
-        OIC_LOG_V(DEBUG, IP_CLIENT_TAG, "IP unicast SendData sockFd %d", sockFd);
-
-        len = CASendData(endpoint, data, dataLength, sockFd);
-
-    }
-    CAClearServerInfoList(tempServerInfoList);
-    return len;
-}
-
index 9c0712f..404d4a8 100644 (file)
@@ -1,4 +1,4 @@
-/******************************************************************
+/*****************************************************************j
  *
  * Copyright 2014 Samsung Electronics All Rights Reserved.
  *
 
 #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>
 #include <unistd.h>
+#include <sys/types.h>
 #include <fcntl.h>
 #include <sys/select.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <net/if.h>
 #include <errno.h>
+#ifdef __linux__
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#endif
 
 #include "pdu.h"
 #include "caadapterutils.h"
 #include "oic_string.h"
 
 /**
- * @def IP_SERVER_TAG
+ * @def TAG
  * @brief Logging tag for module name
  */
-#define IP_SERVER_TAG "IP_SERVER"
-
-/**
- * @def CA_UDP_BIND_RETRY_COUNT
- * @brief Retry count in case of socket bind failure.
- */
-#define CA_UDP_BIND_RETRY_COUNT 10
-
-/**
- * @def IPNAMESIZE
- * @brief Max length for ip address.
- */
-#define IPNAMESIZE 16
-
-/**
- * @def SOCKETOPTION
- * @brief Socket option.
- */
-#define SOCKETOPTION 1
-
-/**
- * @var g_packetHandlerStopFlag
- * @brief Flag for stopping packet handler thread.
- */
-static bool g_packetHandlerStopFlag = false;
+#define TAG "IP_SERVER"
+
+#define SELECT_TIMEOUT 1     // select() seconds (and termination latency)
+
+#define IPv4_MULTICAST     "224.0.1.187"
+static struct in_addr IPv4MulticastAddress = { 0 };
+
+#define IPv6_DOMAINS       16
+#define IPv6_MULTICAST_INT "ff01::fd"
+static struct in6_addr IPv6MulticastAddressInt;
+#define IPv6_MULTICAST_LNK "ff02::fd"
+static struct in6_addr IPv6MulticastAddressLnk;
+#define IPv6_MULTICAST_RLM "ff03::fd"
+static struct in6_addr IPv6MulticastAddressRlm;
+#define IPv6_MULTICAST_ADM "ff04::fd"
+static struct in6_addr IPv6MulticastAddressAdm;
+#define IPv6_MULTICAST_SIT "ff05::fd"
+static struct in6_addr IPv6MulticastAddressSit;
+#define IPv6_MULTICAST_ORG "ff08::fd"
+static struct in6_addr IPv6MulticastAddressOrg;
+#define IPv6_MULTICAST_GLB "ff0e::fd"
+static struct in6_addr IPv6MulticastAddressGlb;
+
+static char *ipv6mcnames[IPv6_DOMAINS] = {
+    NULL,
+    IPv6_MULTICAST_INT,
+    IPv6_MULTICAST_LNK,
+    IPv6_MULTICAST_RLM,
+    IPv6_MULTICAST_ADM,
+    IPv6_MULTICAST_SIT,
+    NULL,
+    NULL,
+    IPv6_MULTICAST_ORG,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    IPv6_MULTICAST_GLB,
+    NULL
+};
+
+static CAIPExceptionCallback g_exceptionCallback;
+
+static CAIPPacketReceivedCallback g_packetReceivedCallback;
+
+static void CAHandleNetlink();
+static void CAApplyInterfaces();
+static void CAFindReadyMessage();
+static void CASelectReturned(fd_set *readFds, int ret);
+static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags);
+
+#define SET(TYPE, FDS) \
+    if (caglobals.ip.TYPE.fd != -1) \
+    { \
+        FD_SET(caglobals.ip.TYPE.fd, FDS); \
+    }
+
+#define ISSET(TYPE, FDS, FLAGS) \
+    if (caglobals.ip.TYPE.fd != -1 && FD_ISSET(caglobals.ip.TYPE.fd, FDS)) \
+    { \
+        fd = caglobals.ip.TYPE.fd; \
+        flags = FLAGS; \
+    }
 
-/**
- * @var CAAdapterIPServerContext_t
- * @brief Thread context information for callbacks and threadpool.
- */
-typedef struct
+static void CAReceiveHandler(void *data)
 {
-    ca_thread_pool_t threadPool;
-    CAIPPacketReceivedCallback packetReceivedCallback;
-    CAIPExceptionCallback exceptionCallback;
-    CAIPErrorHandleCallback IPErrorCallback;
-} CAAdapterIPServerContext_t;
-
-/**
- * @var g_serverInfoList
- * @brief Mutex to synchronize ethenet adapter context.
- */
-static u_arraylist_t *g_serverInfoList = NULL;
-
-/**
- * @var g_mutexServerInfoList
- * @brief Mutex to synchronize Server Information.
- */
-static ca_mutex g_mutexServerInfoList = NULL;
+    OIC_LOG(DEBUG, TAG, "IN");
 
-/**
- * @var g_adapterIPServerContext
- * @brief Mutex to synchronize ethenet adapter context.
- */
-static CAAdapterIPServerContext_t *g_adapterIPServerContext = NULL;
+    while (!caglobals.ip.terminate)
+    {
+        CAFindReadyMessage();
+    }
 
-/**
- * @var g_mutexAdapterServerContext
- * @brief Mutex to synchronize unicast server
- */
-static ca_mutex g_mutexAdapterServerContext = NULL;
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
 
-static void CAReceiveHandler(void *data)
+static void CAFindReadyMessage()
 {
-    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 = caglobals.ip.selectTimeout;
+    timeout.tv_usec = 0;
+    struct timeval *tv = caglobals.ip.selectTimeout == -1 ? NULL : &timeout;
+
+    FD_ZERO(&readFds);
+    SET(u6,  &readFds)
+    SET(u6s, &readFds)
+    SET(u4,  &readFds)
+    SET(u4s, &readFds)
+    SET(m6,  &readFds)
+    SET(m6s, &readFds)
+    SET(m4,  &readFds)
+    SET(m4s, &readFds)
+    if (caglobals.ip.shutdownFds[0] != -1)
     {
-        timeout.tv_sec = 1;
-        timeout.tv_usec = 0;
-        FD_ZERO(&readFds);
+        FD_SET(caglobals.ip.shutdownFds[0], &readFds);
+    }
+    if (caglobals.ip.netlinkFd != -1)
+    {
+        FD_SET(caglobals.ip.netlinkFd, &readFds);
+    }
 
-        ca_mutex_lock(g_mutexServerInfoList);
-        uint32_t listIndex = 0;
-        uint32_t listLength = u_arraylist_length(g_serverInfoList);
+    int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv);
 
-        u_arraylist_t *tempServerInfoList = u_arraylist_create();
-        if (!tempServerInfoList)
+    if (caglobals.ip.terminate)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received.");
+        return;
+    }
+    if (ret <= 0)
+    {
+        if (ret < 0)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return;
+            OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno));
         }
+        return;
+    }
 
-        for (listIndex = 0; listIndex < listLength; listIndex++)
-        {
-            CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
-            if (!info)
-            {
-                listIndex++;
-                continue;
-            }
+    CASelectReturned(&readFds, ret);
+}
 
-            int sd = info->socketFd;
-            //if valid socket descriptor then add to read list
-            if (sd > 0)
-            {
-                FD_SET(sd, &readFds);
-            }
+static void CASelectReturned(fd_set *readFds, int ret)
+{
+    int fd = -1;
+    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+
+    while (!caglobals.ip.terminate)
+    {
+        ISSET(u6,  readFds, CA_IPV6)
+        else ISSET(u6s, readFds, CA_IPV6 | CA_SECURE)
+        else ISSET(u4,  readFds, CA_IPV4)
+        else ISSET(u4s, readFds, CA_IPV4 | CA_SECURE)
+        else ISSET(m6,  readFds, CA_MULTICAST | CA_IPV6)
+        else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE)
+        else ISSET(m4,  readFds, CA_MULTICAST | CA_IPV4)
+        else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
+        else if (FD_ISSET(caglobals.ip.netlinkFd, readFds))
+        {
+            CAHandleNetlink();
+            break;
+        }
+        else
+        {
+            break;
+        }
 
-            //highest file descriptor number, need it for the select function
-            if (sd > maxSd)
-            {
-                maxSd = sd;
-            }
+        (void)CAReceiveMessage(fd, flags);
+        FD_CLR(fd, readFds);
+    }
+}
 
-            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;
-            }
+static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags)
+{
+    char recvBuffer[COAP_MAX_PDU_SIZE];
 
-            *newInfo = *info;
+    struct sockaddr_storage srcAddr;
+    socklen_t srcAddrLen = sizeof (srcAddr);
 
-            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;
-            }
-        }
+    ssize_t recvLen = recvfrom(fd,
+                               recvBuffer,
+                               sizeof (recvBuffer),
+                               0,
+                               (struct sockaddr *)&srcAddr,
+                               &srcAddrLen);
+    if (-1 == recvLen)
+    {
+        OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
+        return CA_STATUS_FAILED;
+    }
 
-        ca_mutex_unlock(g_mutexServerInfoList);
+    CAEndpoint_t ep = { CA_ADAPTER_IP, flags };
 
-        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;
-            }
+    if (flags & CA_IPV6)
+    {
+        ep.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
+        ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;
+    }
+    CAConvertAddrToName(&srcAddr, ep.addr, &ep.port);
 
-            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;
-                ep.adapter = CA_ADAPTER_IP;
-
-                if (info->endpoint.flags & CA_SECURE)
-                {
+    if (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);
+        int ret = CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen);
+        OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
+#else
+        OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
 #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);
-                }
-            }
+    }
+    else
+    {
+        if (g_packetReceivedCallback)
+        {
+            g_packetReceivedCallback(&ep, recvBuffer, recvLen);
         }
-        CAClearServerInfoList(tempServerInfoList);
     }
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
+
+    return CA_STATUS_OK;
 }
 
-static CAResult_t CACreateSocket(int *socketFD, const char *localIp, uint16_t *port, bool isSecured)
+void CAIPPullData()
 {
-    VERIFY_NON_NULL(socketFD, IP_SERVER_TAG, "socketFD is NULL");
-    VERIFY_NON_NULL(localIp, IP_SERVER_TAG, "localIp is NULL");
-    VERIFY_NON_NULL(port, IP_SERVER_TAG, "port is NULL");
-    // Create a UDP socket
-    int sock = -1;
-
-#ifdef SOCK_CLOEXEC
-    sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
-#endif
+    OIC_LOG(DEBUG, TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
 
-    if (-1 == sock)
+static int CACreateSocket(int family, uint16_t *port)
+{
+    int socktype = SOCK_DGRAM;
+    #ifdef SOCK_CLOEXEC
+    socktype |= SOCK_CLOEXEC;
+    #endif
+    int fd = socket(family, socktype, IPPROTO_UDP);
+    if (-1 == fd)
     {
-        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+        OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
+        return -1;
     }
 
-    if (-1 == sock)
+    #ifndef SOCK_CLOEXEC
+    int fl = fcntl(fd, F_GETFD);
+    if (-1 == fl || -1 == fcntl(fd, F_SETFD, fl|FD_CLOEXEC))
     {
-        OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to create Socket, Error code: %s",
-                  strerror(errno));
-        return CA_STATUS_FAILED;
+        OIC_LOG_V(ERROR, TAG, "set FD_CLOEXEC failed: %s", strerror(errno));
+        close(fd);
+        return -1;
     }
+    #endif
 
-    // Make the socket non-blocking
-    if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
+    struct sockaddr_storage sa = { family };
+    if (family == AF_INET6)
     {
-        OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
-                  strerror(errno));
-
-        close(sock);
-        return CA_STATUS_FAILED;
+        int on = 1;
+        if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
+        }
+        ((struct sockaddr_in6 *)&sa)->sin6_port = htons(*port);
+    }
+    else
+    {
+        ((struct sockaddr_in *)&sa)->sin_port = htons(*port);
     }
 
-    if (0 != *port && !isSecured)
+    if (*port)  // use the given port
     {
-        int setOptionOn = SOCKETOPTION;
-        if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &setOptionOn,
-                             sizeof(setOptionOn)))
+        int on = 1;
+        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)))
         {
-            OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
-                      strerror(errno));
-            close(sock);
-            return CA_STATUS_FAILED;
+            OIC_LOG_V(ERROR, TAG, "SO_REUSEADDR failed: %s", strerror(errno));
+            close(fd);
+            return -1;
         }
     }
 
-    struct sockaddr_in sockAddr = { 0 };
-    uint16_t serverPort = *port;
-    sockAddr.sin_family = AF_INET;
-    sockAddr.sin_port = htons(serverPort);
-    if (localIp)
+    if (-1 == bind(fd, (struct sockaddr *)&sa, sizeof(sa)))
     {
-        sockAddr.sin_addr.s_addr = inet_addr(localIp);
+        OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
+        close(fd);
+        return -1;
     }
 
-    bool isBound = false;
-    if (-1 != bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)))
-    {
-        isBound = true;
-    }
-    else if (isSecured)
+    if (!*port)  // return the assigned port
     {
-        //if secure port 5684 is occupied, trying for another port
-        serverPort = 0;
-        sockAddr.sin_port = htons(serverPort);
-        if (-1 != bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)))
+        struct sockaddr_storage sa;
+        socklen_t socklen = sizeof (sa);
+        if (-1 == getsockname(fd, (struct sockaddr *)&sa, &socklen))
         {
-            isBound = true;
+            OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno));
+            close(fd);
+            return -1;
         }
+        *port = ntohs(family == AF_INET6 ?
+                      ((struct sockaddr_in6 *)&sa)->sin6_port :
+                      ((struct sockaddr_in *)&sa)->sin_port);
     }
 
-    if (true == isBound)
-    {
-        struct sockaddr_in sin;
-        socklen_t len = sizeof(sin);
+    return fd;
+}
+
+#define CHECKFD(FD) \
+    if (FD > caglobals.ip.maxfd) \
+        caglobals.ip.maxfd = FD;
+#define NEWSOCKET(FAMILY, NAME) \
+    caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port); \
+    CHECKFD(caglobals.ip.NAME.fd)
+
+static void CAInitializeNetlink()
+{
+#ifdef __linux__
+    // create NETLINK fd for interface change notifications
+    struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK };
 
-        if (-1 == getsockname(sock, (struct sockaddr *)&sin, &len))
+    caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
+    if (caglobals.ip.netlinkFd == -1)
+    {
+        OIC_LOG_V(ERROR, TAG, "netlink socket failed: %s", strerror(errno));
+    }
+    else
+    {
+        int r = bind(caglobals.ip.netlinkFd, (struct sockaddr *)&sa, sizeof (sa));
+        if (r)
         {
-            OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to get socket[%s]!",
-                      strerror(errno));
-            close(sock);
-            return CA_STATUS_FAILED;
+            OIC_LOG_V(ERROR, TAG, "netlink bind failed: %s", strerror(errno));
+            close(caglobals.ip.netlinkFd);
+            caglobals.ip.netlinkFd = -1;
         }
         else
         {
-            serverPort = (uint16_t) ntohs(sin.sin_port);
+            CHECKFD(caglobals.ip.netlinkFd);
         }
     }
-    else
-    {
-        OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]!", strerror(errno));
-        close(sock);
-        return CA_STATUS_FAILED;
-    }
-
-    *port = serverPort;
-    *socketFD = sock;
-    return CA_STATUS_OK;
+#endif
 }
 
-static void CACloseSocket(int socketFD)
+static void CAInitializePipe()
 {
-    if (-1 == socketFD)
+    caglobals.ip.selectTimeout = -1;
+#ifdef HAVE_PIPE2
+    int ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
+#else
+    int ret = pipe(caglobals.ip.shutdownFds);
+    if (-1 != ret)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid Socket Fd");
-        return;
+        ret = fcntl(caglobals.ip.shutdownFds[0], F_GETFD);
+        if (-1 != ret)
+        {
+            ret = fcntl(caglobals.ip.shutdownFds[0], F_SETFD, ret|FD_CLOEXEC);
+        }
+        if (-1 != ret)
+        {
+            ret = fcntl(caglobals.ip.shutdownFds[1], F_GETFD);
+        }
+        if (-1 != ret)
+        {
+            ret = fcntl(caglobals.ip.shutdownFds[1], F_SETFD, ret|FD_CLOEXEC);
+        }
+        if (-1 == ret)
+        {
+            close(caglobals.ip.shutdownFds[1]);
+            close(caglobals.ip.shutdownFds[0]);
+            caglobals.ip.shutdownFds[0] = -1;
+            caglobals.ip.shutdownFds[1] = -1;
+        }
     }
-
-    // close the socket
-    if (-1 == close(socketFD))
+#endif
+    if (-1 == ret)
     {
-        OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
-                  strerror(errno));
+        OIC_LOG_V(ERROR, TAG, "pipe failed: %s", strerror(errno));
+        caglobals.ip.selectTimeout = SELECT_TIMEOUT; //poll needed for shutdown
     }
 }
 
-static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
-                                       bool isSecured, int *serverFD)
+CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    VERIFY_NON_NULL(serverFD, IP_SERVER_TAG, "serverFD");
-    VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
-    VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
+    CAResult_t res = CA_STATUS_OK;
 
-    CAResult_t ret = CACreateSocket(serverFD, localAddress, port, isSecured);
-    if (CA_STATUS_OK != ret)
+    if (caglobals.ip.started)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create unicast socket");
+        return res;
     }
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return ret;
-}
-
-static CAResult_t CAIPStartPacketReceiverHandler()
-{
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    ca_mutex_lock(g_mutexServerInfoList);
-
-    uint32_t listLength = u_arraylist_length(g_serverInfoList);
-
-    ca_mutex_unlock(g_mutexServerInfoList);
-
-    ca_mutex_lock(g_mutexAdapterServerContext);
+    if (!IPv4MulticastAddress.s_addr)
+    {
+        (void)inet_aton(IPv4_MULTICAST, &IPv4MulticastAddress);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_INT, &IPv6MulticastAddressInt);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_LNK, &IPv6MulticastAddressLnk);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_RLM, &IPv6MulticastAddressRlm);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_ADM, &IPv6MulticastAddressAdm);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_SIT, &IPv6MulticastAddressSit);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_ORG, &IPv6MulticastAddressOrg);
+        (void)inet_pton(AF_INET6, IPv6_MULTICAST_GLB, &IPv6MulticastAddressGlb);
+    }
 
-    if (!g_adapterIPServerContext)
+    if (!caglobals.ip.ipv6enabled && !caglobals.ip.ipv4enabled)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL");
-        ca_mutex_unlock(g_mutexAdapterServerContext);
-        return CA_STATUS_FAILED;
+        caglobals.ip.ipv4enabled = true;  // only needed to run CA tests
     }
 
-    if (1 == listLength) //Its first time.
+    if (caglobals.ip.ipv6enabled)
     {
-        g_packetHandlerStopFlag = false;
-        if (CA_STATUS_OK != ca_thread_pool_add_task(g_adapterIPServerContext->threadPool,
-                                                   CAReceiveHandler, NULL ))
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "thread_pool_add_task failed!");
-            ca_mutex_unlock(g_mutexAdapterServerContext);
-            return CA_STATUS_FAILED;
-        }
-        OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread started successfully.");
+        NEWSOCKET(AF_INET6, u6)
+        NEWSOCKET(AF_INET6, u6s)
+        NEWSOCKET(AF_INET6, m6)
+        NEWSOCKET(AF_INET6, m6s)
     }
-    else
+    if (caglobals.ip.ipv4enabled)
     {
-        OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread already is running");
+        NEWSOCKET(AF_INET, u4)
+        NEWSOCKET(AF_INET, u4s)
+        NEWSOCKET(AF_INET, m4)
+        NEWSOCKET(AF_INET, m4s)
     }
-    ca_mutex_unlock(g_mutexAdapterServerContext);
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
+    const char f[] = "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d";
+    OIC_LOG_V(DEBUG, TAG, f, caglobals.ip.u6.fd, caglobals.ip.u6s.fd,
+                             caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
+                             caglobals.ip.m6.fd, caglobals.ip.m6s.fd,
+                             caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
+    (void)f;    // eliminates release warning
 
-    return CA_STATUS_OK;
-}
+    // create pipe for fast shutdown
+    CAInitializePipe();
+    CHECKFD(caglobals.ip.shutdownFds[0]);
+    CHECKFD(caglobals.ip.shutdownFds[1]);
 
-static void CAIPServerDestroyMutex(void)
-{
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
+    // create source of network interface change notifications
+    CAInitializeNetlink();
 
-    if (g_mutexServerInfoList)
-    {
-        ca_mutex_free(g_mutexServerInfoList);
-        g_mutexServerInfoList = NULL;
-    }
+    CAApplyInterfaces();
 
-    if (g_mutexAdapterServerContext)
+    caglobals.ip.terminate = false;
+    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
+    if (CA_STATUS_OK != res)
     {
-        ca_mutex_free(g_mutexAdapterServerContext);
-        g_mutexAdapterServerContext = NULL;
+        OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+        return res;
     }
+    OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
+    caglobals.ip.started = true;
+    return CA_STATUS_OK;
 }
 
-static CAResult_t CAIPServerCreateMutex(void)
+void CAIPStopServer()
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    g_mutexServerInfoList = ca_mutex_new();
-    if (!g_mutexServerInfoList)
+    caglobals.ip.terminate = true;
+
+    if (caglobals.ip.shutdownFds[1] != -1)
     {
-        OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-        return CA_MEMORY_ALLOC_FAILED;
+        close(caglobals.ip.shutdownFds[1]);
+        // receive thread will stop immediately
     }
-
-    g_mutexAdapterServerContext = ca_mutex_new();
-    if (!g_mutexAdapterServerContext)
+    else
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to created mutex!");
-        ca_mutex_free(g_mutexServerInfoList);
-        g_mutexServerInfoList = NULL;
-        return CA_MEMORY_ALLOC_FAILED;
+        // receive thread will stop in SELECT_TIMEOUT seconds.
     }
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
+    OIC_LOG(DEBUG, TAG, "OUT");
 }
 
-CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
+static void applyMulticastToInterface4(struct in_addr inaddr)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(threadPool, IP_SERVER_TAG, "Thread pool handle is NULL");
-
-    // Initialize mutex
-    if (CA_STATUS_OK != CAIPServerCreateMutex())
+    if (!caglobals.ip.ipv4enabled)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create mutex!");
-        return CA_STATUS_FAILED;
+        return;
     }
 
-    ca_mutex_lock(g_mutexAdapterServerContext);
-    g_adapterIPServerContext = (CAAdapterIPServerContext_t *) OICCalloc(1,
-                                 sizeof(CAAdapterIPServerContext_t));
-
-    if (!g_adapterIPServerContext)
+    struct ip_mreq mreq = { IPv4MulticastAddress };
+    mreq.imr_interface = inaddr;
+    if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
-        ca_mutex_unlock(g_mutexAdapterServerContext);
-        return CA_MEMORY_ALLOC_FAILED;
+        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));
+        }
+    }
+}
 
-    g_adapterIPServerContext->threadPool = threadPool;
-
-    ca_mutex_unlock(g_mutexAdapterServerContext);
-
-    ca_mutex_lock(g_mutexServerInfoList);
-
-    g_serverInfoList = u_arraylist_create();
-    if (!g_serverInfoList)
+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)))
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
-        ca_mutex_unlock(g_mutexServerInfoList);
-        return CA_MEMORY_ALLOC_FAILED;
+        if (EADDRINUSE != errno)
+        {
+            OIC_LOG_V(ERROR, TAG, "IPv6 IP_ADD_MEMBERSHIP failed: %s", strerror(errno));
+        }
     }
-    ca_mutex_unlock(g_mutexServerInfoList);
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
 }
 
-void CAIPTerminateServer()
+static void applyMulticastToInterface6(uint32_t interface)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-    ca_mutex_lock(g_mutexAdapterServerContext);
-    if (!g_adapterIPServerContext)
+    if (!caglobals.ip.ipv6enabled)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL");
-        ca_mutex_unlock(g_mutexAdapterServerContext);
         return;
     }
-
-    OICFree(g_adapterIPServerContext);
-    g_adapterIPServerContext = NULL;
-
-    ca_mutex_unlock(g_mutexAdapterServerContext);
-
-    ca_mutex_lock(g_mutexServerInfoList);
-
-    CAClearServerInfoList(g_serverInfoList);
-    g_serverInfoList = NULL;
-
-    ca_mutex_unlock(g_mutexServerInfoList);
-    // Destroy mutex
-    CAIPServerDestroyMutex();
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-
+    //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 CAIPStartUnicastServer(const char *localAddress, uint16_t *port, bool isSecured)
+static void CAApplyInterfaces()
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
+    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+    if (!iflist)
+    {
+        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+        return;
+    }
 
-    // Input validation
-    VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
-    VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
+    uint32_t len = u_arraylist_length(iflist);
+    OIC_LOG_V(DEBUG, TAG, "IP network interfaces found: %d", len);
 
-    ca_mutex_lock(g_mutexServerInfoList);
-    bool isUnicastServerStarted = CAIsUnicastServerStarted(g_serverInfoList, localAddress, *port);
-    if (!isUnicastServerStarted)
+    for (uint32_t i = 0; i < len; i++)
     {
-        int unicastServerFd = -1;
-        if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, isSecured,
-                                                 &unicastServerFd))
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to start unicast server!");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_STATUS_FAILED;
-        }
-
-        CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
-        if (!info)
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
-            close(unicastServerFd);
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
+        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
 
-        char *netMask = NULL;
-        if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
+        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
+            continue;
         }
-        if (netMask)
+        if (ifitem->family == AF_INET)
         {
-            OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask);
-            OICFree(netMask);
+            struct in_addr inaddr;
+            inaddr.s_addr = ifitem->ipv4addr;
+            applyMulticastToInterface4(inaddr);
+            OIC_LOG_V(DEBUG, TAG, "IPv4 network interface: %s", ifitem->name);
         }
-        OICStrcpy(info->endpoint.addr, sizeof(info->endpoint.addr), localAddress);
-        info->endpoint.port = *port;
-        info->endpoint.flags = isSecured ? CA_SECURE : 0;
-        info->endpoint.adapter = CA_ADAPTER_IP;
-        info->socketFd = unicastServerFd;
-        info->isServerStarted = true;
-        info->isMulticastServer = false;
-        OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress);
-
-        CAResult_t res = CAAddServerInfo(g_serverInfoList, info);
-        if (CA_STATUS_OK != res)
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
-            close(unicastServerFd);
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return res;
-        }
-        ca_mutex_unlock(g_mutexServerInfoList);
-
-        res = CAIPStartPacketReceiverHandler();
-        if (CA_STATUS_OK != res)
+        if (ifitem->family == AF_INET6)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
-            close(unicastServerFd);
-            return res;
+            applyMulticastToInterface6(ifitem->index);
+            OIC_LOG_V(DEBUG, TAG, "IPv6 network interface: %s", ifitem->name);
         }
     }
-    else
-    {
-        OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Already Unicast Server Started ip [%s] port [%d]",
-                  localAddress, *port);
-        ca_mutex_unlock(g_mutexServerInfoList);
-    }
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
+    u_arraylist_destroy(iflist);
 }
 
-CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
-                                          uint16_t multicastPort)
+static void CAHandleNetlink()
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
-    VERIFY_NON_NULL(multicastAddress, IP_SERVER_TAG, "port");
-
-    uint16_t port = multicastPort;
-    if (0 >= port)
-    {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: Multicast port is invalid!");
-        return CA_STATUS_INVALID_PARAM;
-    }
-
-    ca_mutex_lock(g_mutexServerInfoList);
-    bool isMulticastServerStarted = CAIsMulticastServerStarted(g_serverInfoList, localAddress,
-                                                               multicastAddress, port);
-    if (!isMulticastServerStarted)
+#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 };
+
+int 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)
     {
-        int mulicastServerFd = -1;
-        CAResult_t ret = CACreateSocket(&mulicastServerFd, multicastAddress, &port, false);
-        if (ret != CA_STATUS_OK)
+        struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
+        if ((ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create multicast socket");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return ret;
+            continue;
         }
 
-        struct ip_mreq multicastMemberReq = {.imr_interface.s_addr = inet_addr(localAddress)};
-        inet_aton(multicastAddress, &multicastMemberReq.imr_multiaddr);
+        int newIndex = ifi->ifi_index;
 
-        if (-1 == setsockopt(mulicastServerFd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-                             (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
+        u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
+        if (!iflist)
         {
-            OIC_LOG_V(ERROR, IP_SERVER_TAG,
-                      "Failed to add to multicast group, Error code: %s\n", strerror(errno));
-            close(mulicastServerFd);
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_STATUS_FAILED;
+            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+            return;
         }
 
-        CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
-        if (!info)
+        uint32_t len = u_arraylist_length(iflist);
+        for (uint32_t i = 0; i < len; i++)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
-            close(mulicastServerFd);
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+            if (ifitem->index != newIndex)
+            {
+                continue;
+            }
 
-        char *netMask = NULL;
-        if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
-        }
-        if (netMask)
-        {
-            OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask);
-            OICFree(netMask);
+            applyMulticastToInterface6(newIndex);
+            struct in_addr inaddr;
+            inaddr.s_addr = ifitem->ipv4addr;
+            applyMulticastToInterface4(inaddr);
+            break;  // we found the one we were looking for
         }
+        u_arraylist_destroy(iflist);
+    }
+}
+#endif // __linux__
+}
 
-        OICStrcpy(info->endpoint.addr, sizeof(info->endpoint.addr), multicastAddress);
-        info->endpoint.port = multicastPort;
-        info->endpoint.flags = 0;
-        info->socketFd = mulicastServerFd;
-        info->isServerStarted = true;
-        info->isMulticastServer = true;
-        OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress);
+void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
+{
+OIC_LOG(DEBUG, TAG, "IN");
 
-        ret = CAAddServerInfo(g_serverInfoList, info);
+g_packetReceivedCallback = callback;
 
-        if (CA_STATUS_OK != ret)
-        {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
-            close(mulicastServerFd);
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return ret;
-        }
-        ca_mutex_unlock(g_mutexServerInfoList);
+OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
+{
+OIC_LOG(DEBUG, TAG, "IN");
+
+    g_exceptionCallback = callback;
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+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");
 
-        ret = CAIPStartPacketReceiverHandler();
-        if (CA_STATUS_OK != ret)
+    char *secure = (endpoint->flags & CA_SECURE) ? "secure " : "";
+    (void)secure;   // eliminates release warning
+    struct sockaddr_storage sock;
+    CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
+
+    if (sock.ss_family == AF_INET6)
+    {
+        struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
+        if (!sock6->sin6_scope_id)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
-            close(mulicastServerFd);
-            return ret;
+            sock6->sin6_scope_id = endpoint->interface;
         }
     }
+
+    ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, sizeof (sock));
+    if (-1 == len)
+    {
+        OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
+    }
     else
     {
-        OIC_LOG_V(DEBUG, IP_SERVER_TAG,
-                  "Multicast Server is already started on interface addr[%s]", localAddress);
-        ca_mutex_unlock(g_mutexServerInfoList);
+        OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %d bytes", secure, cast, fam, len);
     }
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
 }
 
-CAResult_t CAIPStopServer(const char *interfaceAddress)
+static void sendMulticastData6(const u_arraylist_t *iflist,
+                               CAEndpoint_t *endpoint,
+                               const void *data, uint32_t datalen)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    VERIFY_NON_NULL(interfaceAddress, IP_SERVER_TAG, "interfaceAddress is NULL");
-
-    ca_mutex_lock(g_mutexServerInfoList);
-    uint32_t listIndex = 0;
-    uint32_t listLength = u_arraylist_length(g_serverInfoList);
+    int scope = endpoint->flags & CA_SCOPE_MASK;
+    char *ipv6mcname = ipv6mcnames[scope];
+    if (!ipv6mcname)
+    {
+        OIC_LOG_V(INFO, TAG, "IPv6 multicast scope invalid: %d", scope);
+        return;
+    }
+    strncpy(endpoint->addr, ipv6mcname, MAX_ADDR_STR_SIZE_CA);
+    int fd = caglobals.ip.u6.fd;
 
-    for (listIndex = 0; listIndex < listLength;)
+    uint32_t len = u_arraylist_length(iflist);
+    for (uint32_t i = 0; i < len; i++)
     {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
-        if (!info)
+        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
         {
-            listIndex++;
             continue;
         }
-
-        if (info->isMulticastServer && strncmp(interfaceAddress, info->ifAddr, strlen(info->ifAddr))
-                == 0)
-        {
-            if (u_arraylist_remove(g_serverInfoList, listIndex))
-            {
-                struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
-
-                multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
-                inet_aton(info->endpoint.addr, &multicastMemberReq.imr_multiaddr);
-                if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
-                                     (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
-                {
-                    OIC_LOG_V(ERROR, IP_SERVER_TAG,
-                              "Failed to leave multicast group, Error code: %s", strerror(errno));
-                }
-                CACloseSocket(info->socketFd);
-                OICFree(info);
-                OIC_LOG(DEBUG, IP_SERVER_TAG, "Multicast server is stopped successfully.");
-                // Reduce list length by 1 as we removed one element.
-                listLength--;
-            }
-            else
-            {
-                OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
-                ca_mutex_unlock(g_mutexServerInfoList);
-                return CA_STATUS_FAILED;
-            }
-        }
-        else if (strncmp(interfaceAddress, info->endpoint.addr, strlen(info->endpoint.addr)) == 0)
+        if (ifitem->family != AF_INET6)
         {
-            if (u_arraylist_remove(g_serverInfoList, listIndex))
-            {
-                CACloseSocket(info->socketFd);
-                OICFree(info);
-                OIC_LOG(DEBUG, IP_SERVER_TAG, "Unicast server is stopped successfully.");
-                // Reduce list length by 1 as we removed one element.
-                listLength--;
-            }
-            else
-            {
-                OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
-                ca_mutex_unlock(g_mutexServerInfoList);
-                return CA_STATUS_FAILED;
-            }
+            continue;
         }
-        else
+
+        int index = ifitem->index;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof (index)))
         {
-            listIndex++;
+            OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", strerror(errno));
+            return;
         }
+        sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
     }
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    ca_mutex_unlock(g_mutexServerInfoList);
-    return CA_STATUS_OK;
 }
 
-CAResult_t CAIPStopAllServers()
+static void sendMulticastData4(const u_arraylist_t *iflist,
+                               CAEndpoint_t *endpoint,
+                               const void *data, uint32_t datalen)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    g_packetHandlerStopFlag = true;
+    struct ip_mreq mreq = { IPv4MulticastAddress };
+    strncpy(endpoint->addr, IPv4_MULTICAST, MAX_ADDR_STR_SIZE_CA);
+    int fd = caglobals.ip.u4.fd;
 
-    ca_mutex_lock(g_mutexServerInfoList);
-
-    uint32_t listIndex = 0;
-    uint32_t listLength = u_arraylist_length(g_serverInfoList);
-    for (listIndex = 0; listIndex < listLength;)
+    uint32_t len = u_arraylist_length(iflist);
+    for (uint32_t i = 0; i < len; i++)
     {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
-        if (!info)
+        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+        if ((ifitem->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
         {
-            listIndex++;
             continue;
         }
-        if (u_arraylist_remove(g_serverInfoList, listIndex))
+        if (ifitem->family != AF_INET)
         {
-            if (info->isMulticastServer)
-            {
-                struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
-
-                multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
-                inet_aton(info->endpoint.addr, &multicastMemberReq.imr_multiaddr);
-                if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
-                                     (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
-                {
-                    OIC_LOG_V(ERROR, IP_SERVER_TAG,
-                              "Failed to leave multicast group, Error code: %s", strerror(errno));
-                }
-            }
-            CACloseSocket(info->socketFd);
-            //Freeing server info.
-            OICFree(info);
-            // Reduce list length by 1 as we removed one element.
-            listLength--;
+            continue;
         }
-        else
+
+        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(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_STATUS_FAILED;
+            OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)", strerror(errno));
         }
+        sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
     }
-
-    ca_mutex_unlock(g_mutexServerInfoList);
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "All Server stopped successfully. OUT");
-    return CA_STATUS_OK;
 }
 
-void CAIPPullData()
+void CAIPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
+                                                            bool isMulticast)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-}
-
-uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
-{
-    ca_mutex_lock(g_mutexServerInfoList);
-
-    uint16_t port = CAGetServerPort(g_serverInfoList, ipAddress, isSecured);
-
-    ca_mutex_unlock(g_mutexServerInfoList);
+    VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+    VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
 
-    return port;
-}
-
-CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList)
-{
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-    ca_mutex_lock(g_mutexServerInfoList);
+    bool isSecure = (endpoint->flags & CA_SECURE) != 0;
 
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_serverInfoList);
-    for (list_index = 0; list_index < list_length; list_index++)
+    if (isMulticast)
     {
-        CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, list_index);
-        if (!info)
+        endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
+
+        u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+        if (!iflist)
         {
-            continue;
+            OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+            return;
         }
 
-        CAServerInfo_t *newNetinfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t));
-        if (!newNetinfo)
+        if ((endpoint->flags & CA_IPV6) && caglobals.ip.ipv6enabled)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_MEMORY_ALLOC_FAILED;
+            sendMulticastData6(iflist, endpoint, data, datalen);
         }
-
-        *newNetinfo = *info;
-
-        CAResult_t result = u_arraylist_add(*serverInfoList, (void *) newNetinfo);
-        if (CA_STATUS_OK != result)
+        if ((endpoint->flags & CA_IPV4) && caglobals.ip.ipv4enabled)
         {
-            OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_mutexServerInfoList);
-            return CA_STATUS_FAILED;
+            sendMulticastData4(iflist, endpoint, data, datalen);
         }
-    }
-    ca_mutex_unlock(g_mutexServerInfoList);
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
-{
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-
-    ca_mutex_lock(g_mutexAdapterServerContext);
 
-    if (g_adapterIPServerContext)
-    {
-        g_adapterIPServerContext->packetReceivedCallback = callback;
+        u_arraylist_destroy(iflist);
     }
     else
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL");
+        int fd;
+        if (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 (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");
+        }
     }
-
-    ca_mutex_unlock(g_mutexAdapterServerContext);
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
 }
 
-void CAIPSetErrorHandleCallback(CAIPErrorHandleCallback ipErrorCallback)
+CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
 {
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
+    OIC_LOG(DEBUG, TAG, "IN");
 
-    ca_mutex_lock(g_mutexAdapterServerContext);
+    VERIFY_NON_NULL(info, TAG, "info is NULL");
+    VERIFY_NON_NULL(size, TAG, "size is NULL");
 
-    if (g_adapterIPServerContext)
+    u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+    if (!iflist)
     {
-        g_adapterIPServerContext->IPErrorCallback = ipErrorCallback;
+        OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+        return CA_STATUS_FAILED;
     }
 
-    ca_mutex_unlock(g_mutexAdapterServerContext);
-
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
-}
+    uint32_t len = u_arraylist_length(iflist);
 
-void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
-{
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
-    ca_mutex_lock(g_mutexAdapterServerContext);
-
-    if (g_adapterIPServerContext)
+    CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
+    if (!eps)
     {
-        g_adapterIPServerContext->exceptionCallback = callback;
+        OIC_LOG(ERROR, TAG, "Malloc Failed");
+        u_arraylist_destroy(iflist);
+        return CA_MEMORY_ALLOC_FAILED;
     }
-    else
+
+    for (uint32_t i = 0, j = 0; i < len; i++)
     {
-        OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterIPServerContext NULL");
+        CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+
+        OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
+        eps[j].flags = ifitem->family == AF_INET6 ? CA_IPV6 : CA_IPV4;
+        eps[j].adapter = CA_ADAPTER_IP;
+        eps[j].interface = 0;
+        eps[j].port = 0;
+        j++;
     }
 
-    ca_mutex_unlock(g_mutexAdapterServerContext);
+    *info = eps;
+    *size = len;
 
-    OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
+    u_arraylist_destroy(iflist);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
index d9d8f3b..a04b1c7 100644 (file)
 #include <unistd.h>
 
 #include "caadapterutils.h"
-#include "camutex.h"
 #include "logger.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
-#define IP_MONITOR_TAG "IP_MONITOR"
+#define TAG "IP_MONITOR"
 
-/**
- * @var g_networkMonitorContextMutex
- * @brief  Mutex for synchronizing access to cached interface and IP address information.
- */
-static ca_mutex g_networkMonitorContextMutex = NULL;
-
-/**
- * @var g_stopNetworkMonitor
- * @brief  Used to stop the network monitor thread.
- */
-static bool g_stopNetworkMonitor = false;
-
-/**
- * @var g_stopNetworkMonitorMutex
- * @brief  Mutex for synchronizing access to g_stopNetworkMonitor flag.
- */
-static ca_mutex g_stopNetworkMonitorMutex = NULL;
-
-/**
- * @struct CAIPNwMonitorContext
- * @brief  Used for storing network monitor context information.
- */
-typedef struct
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
 {
-    u_arraylist_t  *netInterfaceList;
-    ca_thread_pool_t threadPool;
-    CANetworkStatus_t nwConnectivityStatus;
-    CAIPConnectionStateChangeCallback networkChangeCb;
-} CAIPNetworkMonitorContext;
-
-/**
- * @var g_networkMonitorContext
- * @brief  network monitor context.
- */
-static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
-
-static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
-{
-
-    VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is 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, IP_MONITOR_TAG, "Failed to get interface list!, Error code: %s",
-                  strerror(errno));
-        return;
+        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)
     {
-        char interfaceAddress[CA_IPADDR_SIZE] = {0};
-        char interfaceSubnetMask[CA_IPADDR_SIZE] = {0};
-        socklen_t len = sizeof(struct sockaddr_in);
-
-        if (!ifa->ifa_addr)
-        {
-            continue;
-        }
-
-        int type = ifa->ifa_addr->sa_family;
-        if (ifa->ifa_flags & IFF_LOOPBACK
-            || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING)))
+        int family = ifa->ifa_addr->sa_family;
+        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
         {
             continue;
         }
 
-        if (AF_INET != type)
+        int ifindex = if_nametoindex(ifa->ifa_name);
+        if (desiredIndex && (ifindex != desiredIndex))
         {
             continue;
         }
 
-        // get the interface ip address
-        if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress,
-                             sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST))
-        {
-            OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
-                      strerror(errno));
-            continue;
-        }
-
-        // get the interface subnet mask
-        if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask,
-                             sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
-        {
-            OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
-                      strerror(errno));
-            continue;
-        }
-
-        CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-        if (!netInfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-            freeifaddrs(ifp);
-            return;
-        }
-        // set interface name
-        OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), ifa->ifa_name);
-
-        // set local ip address
-        OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), interfaceAddress);
-
-        // set subnet mask
-        OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), interfaceSubnetMask);
-
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
-        if (CA_STATUS_OK != result)
+        int length = u_arraylist_length(iflist);
+        int already = false;
+        for (int i = length-1; i >= 0; i--)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!Thread exiting.");
-            freeifaddrs(ifp);
-            return;
-        }
-    }
-
-    freeifaddrs(ifp);
-}
-
-static bool CACheckIsAnyInterfaceDown(const u_arraylist_t *netInterfaceList,
-                                      const CANetInfo_t *info)
-{
-    VERIFY_NON_NULL_RET(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null", false);
-    VERIFY_NON_NULL_RET(info, IP_MONITOR_TAG, "info is null", false);
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(netInterfaceList);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(netInterfaceList,
-                               list_index);
-        if (!netInfo)
-        {
-            continue;
-        }
-        if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
-        {
-            return false;
-        }
-    }
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "Interface is down");
-    return true;
-}
-
-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_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    for (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)
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+            if (ifitem->index == ifindex && ifitem->family == family)
             {
-                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");
-                }
+                already = true;
                 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;
-}
-
-static void CANetworkMonitorThread(void *threadData)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    while (!g_stopNetworkMonitor)
-    {
-        u_arraylist_t  *netInterfaceList = u_arraylist_create();
-
-        VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
-        CAIPGetInterfaceInformation(&netInterfaceList);
-
-        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 listIndex = 0;
-        uint32_t listLength = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-        for (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 (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);
-        sleep(2); // To avoid maximum cpu usage.
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-static CAResult_t CAInitializeNetworkMonitorMutexes()
-{
-    if (!g_networkMonitorContextMutex)
-    {
-        g_networkMonitorContextMutex = ca_mutex_new();
-        if (!g_networkMonitorContextMutex)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-
-    if (!g_stopNetworkMonitorMutex)
-    {
-        g_stopNetworkMonitorMutex = ca_mutex_new();
-        if (!g_stopNetworkMonitorMutex)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_stopNetworkMonitorMutex Malloc  failed");
-            ca_mutex_free(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-    return CA_STATUS_OK;
-}
-static void CADestroyNetworkMonitorMutexes()
-{
-    ca_mutex_free(g_networkMonitorContextMutex);
-    g_networkMonitorContextMutex = NULL;
-
-    ca_mutex_free(g_stopNetworkMonitorMutex);
-    g_stopNetworkMonitorMutex = NULL;
-}
-
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
-
-    CAResult_t ret = CAInitializeNetworkMonitorMutexes();
-
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
-        return CA_STATUS_FAILED;
-    }
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-    g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
-                              sizeof(*g_networkMonitorContext));
-    if (!g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-    g_networkMonitorContext->threadPool = threadPool;
-
-    g_networkMonitorContext->netInterfaceList = u_arraylist_create();
-    if (!g_networkMonitorContext->netInterfaceList)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
-        OICFree(g_networkMonitorContext);
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
-
-
-    if (u_arraylist_length(g_networkMonitorContext->netInterfaceList))
-    {
-        g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_UP;
-    }
-    else
-    {
-        g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAIPTerminateNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    g_networkMonitorContext->threadPool = NULL;
-
-    CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
-
-    g_networkMonitorContext->netInterfaceList = NULL;
-    g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    g_networkMonitorContext->networkChangeCb = NULL;
-    g_networkMonitorContext->threadPool = NULL;
-
-    OICFree(g_networkMonitorContext);
-    g_networkMonitorContext = NULL;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-    g_stopNetworkMonitor = true;
-    ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
-    CADestroyNetworkMonitorMutexes();
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-CAResult_t CAIPStartNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-
-    g_stopNetworkMonitor = false;
-
-    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 CA_STATUS_FAILED;
-    }
-
-    if (CA_STATUS_OK != ca_thread_pool_add_task(g_networkMonitorContext->threadPool,
-            CANetworkMonitorThread, NULL))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_STATUS_FAILED;
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStopNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext is null");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_STATUS_FAILED;
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    ca_mutex_lock(g_stopNetworkMonitorMutex);
-    if (!g_stopNetworkMonitor)
-    {
-        g_stopNetworkMonitor = true;
-    }
-    else
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "CAIPStopNetworkMonitor, already stopped!");
-    }
-    ca_mutex_unlock(g_stopNetworkMonitorMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
-              list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
+        if (already)
         {
             continue;
         }
-        OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
-                  info->ipAddress);
-        CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
-        if (!newNetinfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-
-        *newNetinfo = *info;
 
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
-        if (CA_STATUS_OK != result)
+        CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+        if (!ifitem)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_STATUS_FAILED;
+            OIC_LOG(ERROR, TAG, "Malloc failed");
+            goto exit;
         }
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
 
-    VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
-    VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
+        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;
 
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
+        CAResult_t result = u_arraylist_add(iflist, ifitem);
+        if (CA_STATUS_OK != result)
         {
-            OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
-                      "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
-            *subnetMask = OICStrdup(info->subnetMask);
-            break;
+            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+            goto exit;
         }
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-bool CAIPIsConnected()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
-        return false;
+        OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, family);
     }
 
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (0 == u_arraylist_length(g_networkMonitorContext->netInterfaceList))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "IP is not connected");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return false;
-    }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return true;
-}
-
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
-        return;
-    }
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-    g_networkMonitorContext->networkChangeCb = callback;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
+    freeifaddrs(ifp);
+    return iflist;
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+exit:
+    freeifaddrs(ifp);
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
-
index 729968e..0fb68e6 100644 (file)
 
 #include "caipinterface.h"
 
-#include <wifi.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
 
 #include "caadapterutils.h"
-#include "camutex.h"
 #include "logger.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
-#define IP_MONITOR_TAG "IP_MONITOR"
+#define TAG "IP_MONITOR"
 
-/**
- * @var g_networkMonitorContextMutex
- * @brief  Mutex for synchronizing access to cached interface and IP address information.
- */
-static ca_mutex g_networkMonitorContextMutex = NULL;
-
-/**
- * @struct CAIPNwMonitorContext
- * @brief  Used for storing network monitor context information.
- */
-typedef struct
-{
-    u_arraylist_t  *netInterfaceList;
-    ca_thread_pool_t threadPool;
-    CANetworkStatus_t nwConnectivityStatus;
-    CAIPConnectionStateChangeCallback networkChangeCb;
-} CAIPNetworkMonitorContext;
-
-/**
- * @var g_networkMonitorContext
- * @brief  network monitor context.
- */
-static CAIPNetworkMonitorContext *g_networkMonitorContext = NULL;
-
-static void CARemoveInterfaceInfo()
+u_arraylist_t *CAIPGetInterfaceInformation()
 {
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList)
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
     {
-        OIC_LOG(ERROR, IP_MONITOR_TAG,
-                "netInterfaceList is empty");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return;
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
     }
 
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    for (list_index = 0; list_index < list_length; list_index++)
+    struct ifaddrs *ifp = NULL;
+    if (-1 == getifaddrs(&ifp))
     {
-        CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
-                               g_networkMonitorContext->netInterfaceList, list_index);
-        if (!netInfo)
-        {
-            continue;
-        }
-
-        if (u_arraylist_remove(g_networkMonitorContext->netInterfaceList, list_index))
-        {
-            if (g_networkMonitorContext->networkChangeCb)
-            {
-                g_networkMonitorContext->networkChangeCb(netInfo->ipAddress,
-                                                         CA_INTERFACE_DOWN);
-            }
-        }
-        else
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_remove failed");
-        }
-
-        OICFree(netInfo);
+        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+        u_arraylist_destroy(iflist);
+        return NULL;
     }
 
-    u_arraylist_free(&g_networkMonitorContext->netInterfaceList);
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-}
-
-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_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    for (list_index = 0; list_index < list_length; list_index++)
+    struct ifaddrs *ifa = NULL;
+    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
     {
-        CANetInfo_t *netInfo = (CANetInfo_t *)u_arraylist_get(
-                               g_networkMonitorContext->netInterfaceList, list_index);
-        if (!netInfo)
+        int family = ifa->ifa_addr->sa_family;
+        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
         {
             continue;
         }
 
-        if (strncmp(netInfo->interfaceName, info->interfaceName, strlen(info->interfaceName)) == 0)
+        int ifindex = if_nametoindex(ifa->ifa_name);
+        int length = u_arraylist_length(iflist);
+        int already = false;
+        for (int i = length-1; i >= 0; i--)
         {
-            if (strncmp(netInfo->ipAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+            if (ifitem->index == ifindex && ifitem->family == family)
             {
-                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");
-                }
+                already = true;
                 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;
-}
-
-void CAWiFiGetInterfaceInformation(char **interfaceName, char **ipAddress, char **subnetMask)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    int ret = WIFI_ERROR_NONE;
-
-    if (!interfaceName || !ipAddress || !subnetMask)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Invalid input: interface/ipaddress holder is NULL!");
-        return;
-    }
-
-    // Get wifi interface name
-    if (WIFI_ERROR_NONE != (ret = wifi_get_network_interface_name(interfaceName)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface name! error num [%d]", ret);
-        return;
-    }
-
-    // Get wifi connected IP address
-    wifi_ap_h accessPoint = NULL;
-    if (WIFI_ERROR_NONE != (ret = wifi_get_connected_ap(&accessPoint)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get access point! error num [%d]",
-                  ret);
-
-        OICFree(*interfaceName);
-        *interfaceName = NULL;
-        return;
-    }
-
-    if (WIFI_ERROR_NONE != (ret = wifi_ap_get_ip_address(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
-                                  ipAddress)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
-                  ret);
-        OICFree(*interfaceName);
-        *interfaceName = NULL;
-        return;
-    }
-
-    if (WIFI_ERROR_NONE != (ret = wifi_ap_get_subnet_mask(accessPoint, WIFI_ADDRESS_FAMILY_IPV4,
-                                  subnetMask)))
-    {
-        OIC_LOG_V(ERROR, IP_MONITOR_TAG, "Failed to get interface address! error num [%d]",
-                  ret);
-        OICFree(*ipAddress);
-        OICFree(*interfaceName);
-        *ipAddress = NULL;
-        *interfaceName = NULL;
-        return;
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-static void CAIPGetInterfaceInformation(u_arraylist_t **netInterfaceList)
-{
-    VERIFY_NON_NULL_VOID(netInterfaceList, IP_MONITOR_TAG, "netInterfaceList is null");
-
-    // Get wifi network information
-    char *interfaceName = NULL;
-    char *ipAddress = NULL;
-    char *subnetMask = NULL;
-    ///TODO: currently we are filling single interface. Once found the proper tizen apis for
-    // getting multiple interfaces, then this function will be updated.
-    CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
-
-    if (!interfaceName || !ipAddress || !subnetMask)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "interface/ipaddress/subnetmask is NULL!");
-        return;
-    }
-
-    CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-    if (!netInfo)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-        OICFree(interfaceName);
-        OICFree(ipAddress);
-        OICFree(subnetMask);
-        return;
-    }
-
-    // set interface name
-    OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
-
-    // set local ip address
-    OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
-
-    // set subnet mask
-    OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
-
-    CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)netInfo);
-    if (CA_STATUS_OK != result)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-    }
-    OICFree(interfaceName);
-    OICFree(ipAddress);
-    OICFree(subnetMask);
-}
-
-
-void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
-                                    void *userData)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    if (WIFI_CONNECTION_STATE_ASSOCIATION == state
-        || WIFI_CONNECTION_STATE_CONFIGURATION == state)
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_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)
-    {
-        // Get network information
-        char *interfaceName = NULL;
-        char *ipAddress = NULL;
-        char *subnetMask = NULL;
-        CAWiFiGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
-
-        CANetInfo_t *netInfo = (CANetInfo_t *)OICCalloc(1, sizeof(CANetInfo_t));
-        if (!netInfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed");
-            OICFree(interfaceName);
-            OICFree(ipAddress);
-            OICFree(subnetMask);
-            return;
-        }
-
-        // set interface name
-        OICStrcpy(netInfo->interfaceName, sizeof(netInfo->interfaceName), interfaceName);
-
-        // set local ip address
-        OICStrcpy(netInfo->ipAddress, sizeof(netInfo->ipAddress), ipAddress);
-
-        // set subnet mask
-        OICStrcpy(netInfo->subnetMask, sizeof(netInfo->subnetMask), subnetMask);
-
-        bool ret = CACheckIsInterfaceInfoChanged(netInfo);
-        if (ret)
-        {
-            OIC_LOG(DEBUG, IP_MONITOR_TAG, "CACheckIsInterfaceInfoChanged true");
-        }
-        OICFree(netInfo);
-
-        OICFree(interfaceName);
-        OICFree(ipAddress);
-        OICFree(subnetMask);
-    }
-    else
-    {
-        CARemoveInterfaceInfo();
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    if (WIFI_DEVICE_STATE_ACTIVATED == state)
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Activated State");
-    }
-    else
-    {
-        CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Wifi is in Deactivated State");
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-static CAResult_t CAInitializeNetworkMonitorMutexes()
-{
-    if (!g_networkMonitorContextMutex)
-    {
-        g_networkMonitorContextMutex = ca_mutex_new();
-        if (!g_networkMonitorContextMutex)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContextMutex Malloc  failed");
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-
-    return CA_STATUS_OK;
-}
-
-static void CADestroyNetworkMonitorMutexes()
-{
-    ca_mutex_free(g_networkMonitorContextMutex);
-    g_networkMonitorContextMutex = NULL;
-}
-
-CAResult_t CAIPInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(threadPool, IP_MONITOR_TAG, "threadPool is null");
-
-    CAResult_t ret = CAInitializeNetworkMonitorMutexes();
-
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAInitializeNetworkMonitorMutexes failed");
-        return CA_STATUS_FAILED;
-    }
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-     // Initialize Wifi service
-    wifi_error_e retValue = wifi_initialize();
-    if (WIFI_ERROR_NONE != retValue)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_initialize failed");
-        return CA_STATUS_FAILED;
-    }
-
-    g_networkMonitorContext = (CAIPNetworkMonitorContext *)OICCalloc(1,
-                              sizeof(*g_networkMonitorContext));
-    if (!g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "g_networkMonitorContext Malloc  failed");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    g_networkMonitorContext->netInterfaceList = u_arraylist_create();
-    if (!g_networkMonitorContext->netInterfaceList)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_create failed");
-        OICFree(g_networkMonitorContext);
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        CADestroyNetworkMonitorMutexes();
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    CAIPGetInterfaceInformation(&g_networkMonitorContext->netInterfaceList);
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAIPTerminateNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-     // Deinitialize Wifi service
-    wifi_error_e ret = wifi_deinitialize();
-    if (WIFI_ERROR_NONE != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "wifi_deinitialize failed");
-    }
-
-    CAClearNetInterfaceInfoList(g_networkMonitorContext->netInterfaceList);
-
-    g_networkMonitorContext->netInterfaceList = NULL;
-    g_networkMonitorContext->nwConnectivityStatus = CA_INTERFACE_DOWN;
-    g_networkMonitorContext->networkChangeCb = NULL;
-
-    OICFree(g_networkMonitorContext);
-    g_networkMonitorContext = NULL;
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    CADestroyNetworkMonitorMutexes();
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-}
-
-CAResult_t CAIPStartNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-     // Set callback for receiving state changes
-    wifi_error_e ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
-    if (WIFI_ERROR_NONE != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_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, IP_MONITOR_TAG, "wifi_set_connection_state_changed_cb failed");
-        return CA_STATUS_FAILED;
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPStopNetworkMonitor()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_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, IP_MONITOR_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, IP_MONITOR_TAG, "wifi_unset_connection_state_changed_cb failed");
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceInfo(u_arraylist_t **netInterfaceList)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    VERIFY_NON_NULL(netInterfaceList, IP_MONITOR_TAG, "u_array_list is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
-
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo list length [%d]",
-              list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
+        if (already)
         {
             continue;
         }
-        OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "CAIPGetInterfaceInfo ip [%s]",
-                  info->ipAddress);
-        CANetInfo_t *newNetinfo = (CANetInfo_t *) OICMalloc(sizeof(CANetInfo_t));
-        if (!newNetinfo)
-        {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "Malloc failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-
-        *newNetinfo = *info;
 
-        CAResult_t result = u_arraylist_add(*netInterfaceList, (void *)newNetinfo);
-        if (CA_STATUS_OK != result)
+        CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+        if (!ifitem)
         {
-            OIC_LOG(ERROR, IP_MONITOR_TAG, "u_arraylist_add failed!");
-            ca_mutex_unlock(g_networkMonitorContextMutex);
-            return CA_STATUS_FAILED;
+            OIC_LOG(ERROR, TAG, "Malloc failed");
+            goto exit;
         }
-    }
-
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAIPGetInterfaceSubnetMask(const char *ipAddress, char **subnetMask)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
 
-    VERIFY_NON_NULL(subnetMask, IP_MONITOR_TAG, "subnet mask");
-    VERIFY_NON_NULL(ipAddress, IP_MONITOR_TAG, "ipAddress is null");
-    VERIFY_NON_NULL(g_networkMonitorContext, IP_MONITOR_TAG,
-                    "g_networkMonitorContext is null");
-    VERIFY_NON_NULL(g_networkMonitorContextMutex, IP_MONITOR_TAG,
-                    "g_networkMonitorContextMutex is null");
+        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;
 
-    // Get the interface and ipaddress information from cache
-    ca_mutex_lock(g_networkMonitorContextMutex);
-    if (!g_networkMonitorContext->netInterfaceList
-        || !(u_arraylist_length(g_networkMonitorContext->netInterfaceList)))
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "Network not enabled");
-        ca_mutex_unlock(g_networkMonitorContextMutex);
-        return CA_ADAPTER_NOT_ENABLED;
-    }
-
-    uint32_t list_index = 0;
-    uint32_t list_length = u_arraylist_length(g_networkMonitorContext->netInterfaceList);
-    OIC_LOG_V(DEBUG, IP_MONITOR_TAG, "list lenght [%d]", list_length);
-    for (list_index = 0; list_index < list_length; list_index++)
-    {
-        CANetInfo_t *info = (CANetInfo_t *)u_arraylist_get(
-                            g_networkMonitorContext->netInterfaceList, list_index);
-        if (!info)
-        {
-            continue;
-        }
-
-        if (strncmp(info->ipAddress, ipAddress, strlen(ipAddress)) == 0)
+        CAResult_t result = u_arraylist_add(iflist, ifitem);
+        if (CA_STATUS_OK != result)
         {
-            OIC_LOG_V(DEBUG, IP_MONITOR_TAG,
-                      "CAIPGetInterfaceSubnetMask subnetmask is %s", info->subnetMask);
-            *subnetMask = OICStrdup(info->subnetMask);
-            break;
+            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+            goto exit;
         }
     }
-    ca_mutex_unlock(g_networkMonitorContextMutex);
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-bool CAIPIsConnected()
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-
-    wifi_connection_state_e connection_state;
-    wifi_error_e ret = wifi_get_connection_state(&connection_state);
-    if (WIFI_ERROR_NONE != ret)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "Failed to get the Connection State");
-        return false;
-    }
-
-    if (WIFI_CONNECTION_STATE_DISCONNECTED == connection_state)
-    {
-        OIC_LOG(DEBUG, IP_MONITOR_TAG, "WIFI is not Connected");
-        return false;
-    }
-
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
-    return true;
-}
-
-void CAIPSetConnectionStateChangeCallback(CAIPConnectionStateChangeCallback callback)
-{
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "IN");
-    if (!g_networkMonitorContextMutex || !g_networkMonitorContext)
-    {
-        OIC_LOG(ERROR, IP_MONITOR_TAG, "CAIPSetConnectionStateChangeCallback failed");
-        return;
-    }
-    ca_mutex_lock(g_networkMonitorContextMutex);
-
-    g_networkMonitorContext->networkChangeCb = callback;
 
-    ca_mutex_unlock(g_networkMonitorContextMutex);
+    freeifaddrs(ifp);
+    return iflist;
 
-    OIC_LOG(DEBUG, IP_MONITOR_TAG, "OUT");
+exit:
+    freeifaddrs(ifp);
+    u_arraylist_destroy(iflist);
+    return NULL;
 }
index 3449647..486f28a 100644 (file)
@@ -168,7 +168,7 @@ TEST_F(CATests, TerminateTest)
 // check return value
 TEST(StartListeningServerTest, DISABLED_TC_03_Positive_01)
 {
-    CASelectNetwork(CA_IPV4);
+    CASelectNetwork(CA_ADAPTER_IP);
     EXPECT_EQ(CA_STATUS_OK, CAStartListeningServer());
 }
 
@@ -438,14 +438,14 @@ CAResult_t checkSelectNetwork()
 TEST_F(CATests, SelectNetworkTestBad)
 {
     //Select disable network
-    EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork(1000));
+    EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)1000));
 }
 
 // check return value when selected network is disable
 TEST_F(CATests, UnSelectNetworkTest)
 {
     //UnSelect disable network
-    EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork(1000));
+    EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)1000));
 }
 
 // CAHandlerRequestResponse TC
index d76208a..2d3d6d3 100644 (file)
@@ -149,7 +149,7 @@ void DeleteDeviceInfo();
  */
 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
                                            OCDiscoveryPayload* payload,
-                                           CATransportAdapter_t adapter);
+                                           OCDevAddr *endpoint);
 
 /**
  * A helper function that Maps an @ref OCEntityHandlerResult type to an
index 16f8dc6..228055b 100644 (file)
@@ -170,6 +170,7 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
  * @param entityHandlerRequest - pointer to the OCEntityHandlerRequest struct that is created
  * @param request          - request handle
  * @param method           - RESTful method
+ * @param endpoint         - requesting endpoint
  * @param resource         - resource handle
  * @param queryBuf         - resource query of request
  * @param payload          - payload of request
@@ -182,12 +183,19 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
  * @return
  *     OCStackResult
  */
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest,
-        OCRequestHandle request,
-        OCMethod method, OCResourceHandle resource, char * queryBuf,
-        uint8_t * payload, size_t payloadSize,
-        uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
-        OCObservationId observeID);
+OCStackResult FormOCEntityHandlerRequest(
+                                OCEntityHandlerRequest *entityHandlerRequest,
+                                OCRequestHandle request,
+                                OCMethod method,
+                                OCDevAddr *endpoint,
+                                OCResourceHandle resource,
+                                char *queryBuf,
+                                uint8_t *payload,
+                                size_t payloadSize,
+                                uint8_t numVendorOptions,
+                                OCHeaderOption *vendorOptions,
+                                OCObserveAction observeAction,
+                                OCObservationId observeID);
 
 /**
  * Find a server request in the server request list and delete
index 3ff3933..a9603ea 100644 (file)
@@ -158,6 +158,8 @@ typedef enum
     OC_IP_USE_V6       = (1 << 5),   // IP adapter only
     OC_IP_USE_V4       = (1 << 6),   // IP adapter only
 
+    OC_RESERVED1       = (1 << 7),   // internal use only
+
     // Link-Local multicast is the default multicast scope for IPv6.
     // These are placed here to correspond to the IPv6 multicast address bits.
     OC_SCOPE_INTERFACE = 0x1, // IPv6 Interface-Local scope (loopback)
@@ -171,6 +173,7 @@ typedef enum
 
 #define OC_MASK_SCOPE    (0x000F)
 #define OC_MASK_MODS     (0x0FF0)
+#define OC_MASK_FAMS     (OC_IP_USE_V6|OC_IP_USE_V4)
 
 /*
  * endpoint identity
@@ -667,6 +670,8 @@ typedef struct
     OCRequestHandle requestHandle;
     // the REST method retrieved from received request PDU
     OCMethod method;
+    // description of endpoint that sent the request
+    OCDevAddr devAddr;
     // resource query send by client
     char * query;
     // Information associated with observation - valid only when OCEntityHandler
index a851da3..6f3d7a0 100644 (file)
@@ -239,8 +239,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, c
 
     if(ret == OC_STACK_OK)
     {
-        ret = BuildVirtualResourceResponse(collResource, payload,
-                CA_ADAPTER_IP);
+        ret = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr);
     }
 
     if (ret == OC_STACK_OK)
@@ -252,8 +251,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, c
             {
                 //TODO : Add resource type filtering once collections
                 // start supporting queries.
-                ret = BuildVirtualResourceResponse(temp, payload,
-                        CA_ADAPTER_IP);
+                ret = BuildVirtualResourceResponse(temp, payload, &ehRequest->devAddr);
             }
         }
     }
@@ -287,8 +285,7 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 
     if(stackRet == OC_STACK_OK)
     {
-        stackRet = BuildVirtualResourceResponse(collResource, payload,
-                CA_ADAPTER_IP);
+        stackRet = BuildVirtualResourceResponse(collResource, payload, &ehRequest->devAddr);
     }
 
     if(stackRet == OC_STACK_OK)
@@ -492,5 +489,3 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
     }
     return result;
 }
-
-
index 6f94bb3..201dac8 100644 (file)
@@ -141,12 +141,19 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                     request->observeResult = OC_STACK_OK;
                     if(result == OC_STACK_OK)
                     {
-                        result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-                                    request->method, (OCResourceHandle) resPtr, request->query,
-                                    request->payload, request->payloadSize,
+                        result = FormOCEntityHandlerRequest(
+                                    &ehRequest,
+                                    (OCRequestHandle) request,
+                                    request->method,
+                                    &request->devAddr,
+                                    (OCResourceHandle) resPtr,
+                                    request->query,
+                                    request->payload,
+                                    request->payloadSize,
                                     request->numRcvdVendorSpecificHeaderOptions,
                                     request->rcvdVendorSpecificHeaderOptions,
-                                    OC_OBSERVE_NO_OPTION, 0);
+                                    OC_OBSERVE_NO_OPTION,
+                                    0);
                         if(result == OC_STACK_OK)
                         {
                             ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest,
index f5984e9..71db404 100644 (file)
@@ -67,31 +67,24 @@ OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
 }
 
 /* This method will retrieve the port at which the secure resource is hosted */
-static OCStackResult GetSecurePortInfo(CATransportAdapter_t connType, uint16_t *port)
+static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
 {
-    CAEndpoint_t* info = NULL;
-    uint32_t size = 0;
-    OCStackResult ret = OC_STACK_ERROR;
+    uint16_t p = 0;
 
-    CAResult_t caResult = CAGetNetworkInformation(&info, &size);
-    if ((caResult == CA_STATUS_OK) && info && size)
+    if (endpoint->adapter == OC_ADAPTER_IP)
     {
-        while (size--)
+        if (endpoint->flags & OC_IP_USE_V6)
         {
-            if ((info[size].flags & CA_SECURE) && info[size].adapter == connType)
-            {
-                if (info[size].adapter == CA_ADAPTER_IP)
-                {
-                    *port = info[size].port;
-                    ret = OC_STACK_OK;
-                    break;
-                }
-            }
+            p = caglobals.ip.u6s.port;
+        }
+        else if (endpoint->flags & OC_IP_USE_V4)
+        {
+            p = caglobals.ip.u4s.port;
         }
     }
 
-    OICFree(info);
-    return ret;
+    *port = p;
+    return OC_STACK_OK;
 }
 
 /*
@@ -210,7 +203,7 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q
 }
 
 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
-                        OCDiscoveryPayload* payload, CATransportAdapter_t adapter )
+                        OCDiscoveryPayload *payload, OCDevAddr *devAddr)
 {
     if (!resourcePtr || !payload)
     {
@@ -219,7 +212,7 @@ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
     uint16_t port = 0;
     if (resourcePtr->resourceProperties & OC_SECURE)
     {
-       if(GetSecurePortInfo (adapter, &port) != OC_STACK_OK)
+       if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
        {
            port = 0;
        }
@@ -523,7 +516,7 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
             {
                 discoveryResult = BuildVirtualResourceResponse(resource,
                     (OCDiscoveryPayload*)payload,
-                    (CATransportAdapter_t)request->devAddr.adapter);
+                    &request->devAddr);
             }
         }
     }
@@ -599,12 +592,17 @@ HandleDefaultDeviceEntityHandler (OCServerRequest *request)
     OCEntityHandlerRequest ehRequest = {};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) NULL, request->query,
-            request->payload, request->payloadSize,
-            request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions,
-            (OCObserveAction)request->observationOption, (OCObservationId)0);
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle) request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle) NULL, request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        (OCObservationId)0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // At this point we know for sure that defaultDeviceHandler exists
@@ -643,11 +641,18 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
 
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) resource, request->query,
-            request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions,
-            (OCObserveAction)request->observationOption, 0);
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle)request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle)resource,
+                                        request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
@@ -750,11 +755,18 @@ HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
     OCStackResult result = OC_STACK_ERROR;
     OCEntityHandlerRequest ehRequest = {};
 
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) resource, request->query,
-            request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions,
-            (OCObserveAction)request->observationOption, (OCObservationId) 0);
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle)request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle)resource,
+                                        request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        (OCObservationId)0);
     if(result != OC_STACK_OK)
     {
         return result;
index 3f9c2b0..db84e9e 100644 (file)
@@ -302,6 +302,7 @@ OCStackResult FormOCEntityHandlerRequest(
         OCEntityHandlerRequest * entityHandlerRequest,
         OCRequestHandle request,
         OCMethod method,
+        OCDevAddr *endpoint,
         OCResourceHandle resource,
         char * queryBuf,
         uint8_t * payload,
@@ -316,6 +317,7 @@ OCStackResult FormOCEntityHandlerRequest(
         entityHandlerRequest->resource = (OCResourceHandle) resource;
         entityHandlerRequest->requestHandle = request;
         entityHandlerRequest->method = method;
+        entityHandlerRequest->devAddr = *endpoint;
         entityHandlerRequest->query = queryBuf;
         entityHandlerRequest->obsInfo.action = observeAction;
         entityHandlerRequest->obsInfo.obsId = observeID;
index 44b1e65..d2c730a 100644 (file)
@@ -421,6 +421,10 @@ static OCStackResult OCCreateEndpoint(OCDevAddr *devAddr, CAEndpoint_t **endpoin
     }
 
     ep->adapter = (CATransportAdapter_t)devAddr->adapter;
+    if (!ep->adapter)
+    {
+        ep->adapter = CA_ADAPTER_IP;
+    }
     ep->flags = OCToCATransportFlags(devAddr->flags);
     strncpy(ep->addr, devAddr->addr, MAX_ADDR_STR_SIZE_CA);
     ep->port = devAddr->port;
@@ -463,9 +467,14 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
         observer = GetObserverUsingToken (token, tokenLength);
         if(observer)
         {
-            result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
-                    OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0,
-                    NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+            result = FormOCEntityHandlerRequest(&ehRequest,
+                                                (OCRequestHandle)NULL,
+                                                OC_REST_NOMETHOD,
+                                                &observer->devAddr,
+                                                (OCResourceHandle)NULL,
+                                                NULL, NULL, 0, 0, NULL,
+                                                OC_OBSERVE_DEREGISTER,
+                                                observer->observeId);
             if(result != OC_STACK_OK)
             {
                 return result;
@@ -508,9 +517,14 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
         {
             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
             {
-                result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
-                        OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0, 0,
-                        NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+                result = FormOCEntityHandlerRequest(&ehRequest,
+                                                    (OCRequestHandle)NULL,
+                                                    OC_REST_NOMETHOD,
+                                                    &observer->devAddr,
+                                                    (OCResourceHandle)NULL,
+                                                    NULL, NULL, 0, 0, NULL,
+                                                    OC_OBSERVE_DEREGISTER,
+                                                    observer->observeId);
                 if(result != OC_STACK_OK)
                 {
                     return OC_STACK_ERROR;
@@ -737,18 +751,38 @@ static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resource
     VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM);
 
     const char *format;
+    CAEndpoint_t *ep = (CAEndpoint_t *)endpoint;
 
-    if ((endpoint->flags & CA_IPV6) && !(endpoint->flags & CA_IPV4))
-    {
-        format = "coap://[%s]:%u%s";
-    }
-    else
+    if (ep->adapter == CA_ADAPTER_IP)
     {
-        format = "coap://%s:%u%s";
+        if (ep->flags & CA_IPV6)
+        {
+            if ('\0' == ep->addr[0])  // multicast
+            {
+                return snprintf(presenceUri, CA_MAX_URI_LENGTH, OC_RSRVD_PRESENCE_URI);
+            }
+            else
+            {
+                format = "coap://[%s]:%u%s";
+            }
+        }
+        else
+        {
+            if ('\0' == ep->addr[0])  // multicast
+            {
+                OICStrcpy(ep->addr, sizeof(ep->addr), OC_MULTICAST_IP);
+                ep->port = OC_MULTICAST_PORT;
+            }
+            format = "coap://%s:%u%s";
+        }
+        return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, ep->addr,
+                        ep->port, OC_RSRVD_PRESENCE_URI);
     }
 
-    return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, endpoint->addr,
-                                               endpoint->port, OC_RSRVD_PRESENCE_URI);
+    // might work for other adapters (untested, but better than nothing)
+    format = "coap://%s%s";
+    return snprintf(presenceUri, CA_MAX_URI_LENGTH, format, ep->addr,
+                    OC_RSRVD_PRESENCE_URI);
 }
 
 
@@ -776,6 +810,7 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
         return OC_STACK_ERROR;
     }
 
+    // check for unicast presence
     uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri);
     if (uriLen < 0 || uriLen >= sizeof (presenceUri))
     {
@@ -789,17 +824,12 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
     }
     else
     {
-        CAEndpoint_t endpointMulticast;
-        endpointMulticast.flags = endpoint->flags;
-        OICStrcpy(endpointMulticast.addr, sizeof(endpointMulticast.addr), OC_MULTICAST_IP);
-        endpointMulticast.port = OC_MULTICAST_PORT;
+        // check for multiicast presence
+        CAEndpoint_t ep = { endpoint->adapter, endpoint->flags };
+        OICStrcpy(ep.addr, sizeof(ep.addr), OC_MULTICAST_IP);
+        ep.port = OC_MULTICAST_PORT;
 
-        uriLen = FormCanonicalPresenceUri(&endpointMulticast, OC_RSRVD_PRESENCE_URI, presenceUri);
-
-        if (uriLen < 0 || uriLen >= sizeof (presenceUri))
-        {
-            return OC_STACK_INVALID_URI;
-        }
+        uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri);
 
         cbNode = GetClientCB(NULL, 0, NULL, presenceUri);
         if (cbNode)
@@ -1526,8 +1556,25 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag
     }
     myStackMode = mode;
 
+    if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER)
+    {
+        caglobals.client = true;
+    }
+    if (mode == OC_SERVER || mode == OC_CLIENT_SERVER)
+    {
+        caglobals.server = true;
+    }
+
     caglobals.serverFlags = (CATransportFlags_t)serverFlags;
+    if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
+    {
+        caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4);
+    }
     caglobals.clientFlags = (CATransportFlags_t)clientFlags;
+    if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
+    {
+        caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4);
+    }
 
     defaultDeviceHandler = NULL;
     defaultDeviceHandlerCallbackParameter = NULL;