Update snapshot(2017-12-14)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipadapter.c
index 48905f6..d6b1b89 100644 (file)
@@ -1,4 +1,4 @@
-/******************************************************************
+/* ****************************************************************
  *
  * Copyright 2014 Samsung Electronics All Rights Reserved.
  *
 #include <string.h>
 #include <stdint.h>
 
+#include "caipnwmonitor.h"
 #include "caipinterface.h"
 #include "caqueueingthread.h"
 #include "caadapterutils.h"
 #ifdef __WITH_DTLS__
-#include "caadapternetdtls.h"
+#include "ca_adapter_net_ssl.h"
+#ifdef WITH_TCP
+#include "catcpinterface.h"
 #endif
-#include "camutex.h"
+#endif
+
+#include "octhread.h"
 #include "uarraylist.h"
 #include "caremotehandler.h"
 #include "logger.h"
 #include "oic_string.h"
 
 /**
- * @def IP_ADAPTER_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.
+ * Logging tag for module name.
  */
-#define CA_MULTICAST_IP "224.0.1.187"
+#define TAG "OIC_CA_IP_ADAP"
 
 #ifndef SINGLE_THREAD
 /**
- * @var CAIPData
- * @brief Holds inter thread ip data information.
+ * Holds inter thread ip data information.
  */
 typedef struct
 {
@@ -82,55 +57,36 @@ typedef struct
     void *data;
     uint32_t dataLen;
     bool isMulticast;
-} CAIPData;
+} CAIPData_t;
 
 /**
- * @var g_sendQueueHandle
- * @brief Queue handle for Send Data
+ * Queue handle for Send Data.
  */
 static CAQueueingThread_t *g_sendQueueHandle = NULL;
 #endif
 
 /**
- * @var g_networkPacketCallback
- * @brief Network Packet Received Callback to CA
+ * Network Packet Received Callback to CA.
  */
 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
 
 /**
- * @var g_networkChangeCallback
- * @brief Network Changed Callback to CA
+ * Network Changed Callback to CA.
  */
-static CANetworkChangeCallback g_networkChangeCallback = NULL;
+static CAAdapterChangeCallback g_networkChangeCallback = NULL;
 
 /**
- * @var g_errorCallback
- * @brief error Callback to CA adapter
+ * error Callback to CA adapter.
  */
 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);
+static CAResult_t CAIPPacketReceivedCB(const CASecureEndpoint_t *endpoint,
+                                       const void *data, size_t dataLength);
 #ifdef __WITH_DTLS__
-static uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint,
-                                 const void *data, uint32_t dataLength);
+static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint,
+                                const void *data, size_t dataLength);
 #endif
 
-static CAResult_t CAIPStopServers();
-
 #ifndef SINGLE_THREAD
 
 static CAResult_t CAIPInitializeQueueHandles();
@@ -139,20 +95,20 @@ static void CAIPDeinitializeQueueHandles();
 
 static void CAIPSendDataThread(void *threadData);
 
-static CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
-                                const void *data, uint32_t dataLength, bool isMulticast);
-void CAFreeIPData(CAIPData *ipData);
+static CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
+                                  const void *data, uint32_t dataLength,
+                                  bool isMulticast);
+
+void CAFreeIPData(CAIPData_t *ipData);
 
 static void CADataDestroyer(void *data, uint32_t size);
 
 CAResult_t CAIPInitializeQueueHandles()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_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,752 +116,446 @@ 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");
     return CA_STATUS_OK;
 }
 
 void CAIPDeinitializeQueueHandles()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_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);
-}
-#endif
+#endif // SINGLE_THREAD
 
-void CAIPNotifyNetworkChange(const char *address, uint16_t port, CANetworkStatus_t status)
+void CAIPAdapterHandler(CATransportAdapter_t adapter, 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);
+        g_networkChangeCallback(adapter, status);
     }
     else
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "g_networkChangeCallback is NULL");
+        OIC_LOG(ERROR, TAG, "g_networkChangeCallback is NULL");
     }
 
-    CAFreeEndpoint(localEndpoint);
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
-
-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)
+    if (CA_INTERFACE_DOWN == 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(DEBUG, TAG, "Network status for IP is down");
+
+        CAResult_t res = CAQueueingThreadClearData(g_sendQueueHandle);
+        if (res != CA_STATUS_OK)
         {
-            OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to start Unicast server port[%d]", ret);
+            OIC_LOG_V(ERROR, TAG, "CAQueueingThreadClearData failed[%d]", res);
         }
 
 #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);
-        }
+#ifdef WITH_TCP
+        CATCPCloseInProgressConnections();
+#endif
+        OIC_LOG(DEBUG, TAG, "close all ssl session");
+        CAcloseSslConnectionAll(CA_ADAPTER_IP);
 #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");
 }
 
 #ifdef __WITH_DTLS__
-uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
+static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_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);
+    VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", -1);
+    VERIFY_NON_NULL_RET(data, TAG, "data is NULL", -1);
 
-    if (sentLength == 0)
-    {
-        g_errorCallback(endpoint, data, dataLength, CA_SEND_FAILED);
-    }
-
-    OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Successfully sent %d of encrypted data!", sentLength);
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-
-    return sentLength;
+    CAIPSendData(endpoint, data, dataLength, false);
+    return dataLength;
 }
 #endif
 
-void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
-                          uint32_t dataLength)
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "ipAddress is NULL");
-    VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL");
 
-    OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+CAResult_t CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
+                                size_t dataLength)
+{
+    VERIFY_NON_NULL(sep, TAG, "sep is NULL");
+    VERIFY_NON_NULL(data, TAG, "data is NULL");
 
-    void *buf = OICCalloc(dataLength + 1, sizeof (char));
-    if (!buf)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!");
-        return;
-    }
-    memcpy(buf, data, dataLength);
+    OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
 
+    CAResult_t res = CA_STATUS_OK;
     if (g_networkPacketCallback)
     {
-        g_networkPacketCallback(endpoint, buf, dataLength);
-    }
-    else
-    {
-        OICFree(buf);
+        res = g_networkPacketCallback(sep, data, dataLength);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
+        }
     }
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    return res;
 }
 
-void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data,
-                       uint32_t dataLength, CAResult_t result)
+void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
+                      uint32_t dataLength, CAResult_t result)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_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, TAG, "data is NULL");
 
-    VERIFY_NON_NULL_VOID(data, IP_ADAPTER_TAG, "data is NULL");
-
-    void *buf = (void*)OICMalloc(sizeof(char) * dataLength);
-    if (!buf)
-    {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!");
-        return;
-    }
-    memcpy(buf, data, dataLength);
     if (g_errorCallback)
     {
-        g_errorCallback(endpoint, buf, dataLength, result);
-    }
-    else
-    {
-        OICFree(buf);
+        g_errorCallback(endpoint, data, dataLength, result);
     }
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-
-    return;
 }
 
-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));
-    }
+    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;
+    }
+//TODO Enable once TizenRT supports IPv6
+#ifndef __TIZENRT__
+    caglobals.ip.ipv6enabled = flags & CA_IPV6;
 #endif
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return dataLength;
+    caglobals.ip.ipv4enabled = flags & CA_IPV4;
+    caglobals.ip.dualstack = caglobals.ip.ipv6enabled && caglobals.ip.ipv4enabled;
 }
 
 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
                           CANetworkPacketReceivedCallback networkPacketCallback,
-                          CANetworkChangeCallback netCallback,
+                          CAAdapterChangeCallback 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;
 
+    CAIPSetErrorHandler(CAIPErrorHandler);
     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
-    CAIPSetErrorHandleCallback(CAIPErrorHandler);
-#ifdef __WITH_DTLS__
-    CAAdapterNetDtlsInit();
 
-    CADTLSSetAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, 0);
+#ifdef __WITH_DTLS__
+    CAsetSslAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, CA_ADAPTER_IP);
 #endif
 
-    CAConnectivityHandler_t ipHandler;
-    ipHandler.startAdapter = CAStartIP;
-    ipHandler.startListenServer = CAStartIPListeningServer;
-    ipHandler.startDiscoveryServer = CAStartIPDiscoveryServer;
-    ipHandler.sendData = CASendIPUnicastData;
-    ipHandler.sendDataToAll = CASendIPMulticastData;
-    ipHandler.GetnetInfo = CAGetIPInterfaceInformation;
-    ipHandler.readData = CAReadIPData;
-    ipHandler.stopAdapter = CAStopIP;
-    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");
+    static const CAConnectivityHandler_t ipHandler =
+        {
+            .startAdapter = CAStartIP,
+            .stopAdapter = CAStopIP,
+            .startListenServer = CAStartIPListeningServer,
+            .stopListenServer = CAStopIPListeningServer,
+            .startDiscoveryServer = CAStartIPDiscoveryServer,
+            .sendData = CASendIPUnicastData,
+            .sendDataToAll = CASendIPMulticastData,
+            .GetnetInfo = CAGetIPInterfaceInformation,
+            .readData = CAReadIPData,
+            .terminate = CATerminateIP,
+            .cType = CA_ADAPTER_IP
+        };
+    registerCallback(ipHandler);
+
+    OIC_LOG(INFO, TAG, "OUT IntializeIP is Success");
     return CA_STATUS_OK;
 }
 
 CAResult_t CAStartIP()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    // Specific the port number received from application.
+    caglobals.ip.u6.port  = caglobals.ports.udp.u6;
+    caglobals.ip.u6s.port = caglobals.ports.udp.u6s;
+    caglobals.ip.u4.port  = caglobals.ports.udp.u4;
+    caglobals.ip.u4s.port = caglobals.ports.udp.u4s;
 
-    // Start monitoring IP network
-    CAResult_t ret = CAIPStartNetworkMonitor();
+    CAIPStartNetworkMonitor(CAIPAdapterHandler, CA_ADAPTER_IP);
+#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
+#ifndef __TIZENRT__
+    if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
+#else
+    if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle, "IoT_IPSendQueue"))
+#endif
     {
-        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;
+
+    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);
+    CAResult_t ret = CAIPStartListenServer();
     if (CA_STATUS_OK != ret)
     {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Start multicast failed[%d]", ret);
+        OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
+        return ret;
     }
-#else
-    u_arraylist_t *netInterfaceList = u_arraylist_create();
 
-    VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
+    return CA_STATUS_OK;
+}
 
-    ret = CAIPGetInterfaceInfo(&netInterfaceList);
+CAResult_t CAStopIPListeningServer()
+{
+    CAResult_t ret = CAIPStopListenServer();
     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_V(ERROR, TAG, "Failed to stop listening server![%d]", ret);
     }
 
-    CAClearNetInterfaceInfoList(netInterfaceList);
-#endif
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
     return ret;
 }
 
 CAResult_t CAStartIPDiscoveryServer()
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-    /* Both listening and discovery server are same */
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
     return CAStartIPListeningServer();
 }
 
-int32_t CASendIPUnicastData(const CAEndpoint_t *remoteEndpoint,
-                            const void *data, uint32_t dataLength)
+static int32_t CAQueueIPData(bool isMulticast, const CAEndpoint_t *endpoint,
+                             const void *data, uint32_t dataLength)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_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);
+    return dataLength;
 
-    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_t *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_t));
+
+#endif // SINGLE_THREAD
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CAIPSendDataInternal(endpoint, data, dataLength, true);
+    return dataLength;
 }
 
-CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint,
+                            const void *data, uint32_t dataLength,
+                            CADataType_t dataType)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    (void)dataType;
+    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,
+                              CADataType_t dataType)
+{
+    (void)dataType;
+    return CAQueueIPData(true, endpoint, data, dataLength);
+}
 
-    bool retVal = CAIPIsConnected();
-    if (false == retVal)
+CAResult_t CAReadIPData()
+{
+    CAIPPullData();
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAStopIP()
+{
+#ifndef SINGLE_THREAD
+    if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "IP not Connected");
-        return CA_ADAPTER_NOT_ENABLED;
+        CAQueueingThreadStop(g_sendQueueHandle);
     }
+#endif
+
+    CAIPStopNetworkMonitor(CA_ADAPTER_IP);
+    CAIPStopServer();
+    //Re-initializing the Globals to start them again
+    CAInitializeIPGlobals();
+
+    return CA_STATUS_OK;
+}
 
-    u_arraylist_t *netInterfaceList = u_arraylist_create();
+void CATerminateIP()
+{
+#ifdef __WITH_DTLS__
+    CAsetSslAdapterCallbacks(NULL, NULL, CA_ADAPTER_IP);
+#endif
 
-    VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
+    CAIPSetPacketReceiveCallback(NULL);
 
-    CAResult_t ret = CAIPGetInterfaceInfo(&netInterfaceList);
-    if (CA_STATUS_OK != ret)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "CAIPGetInterfaceInfo failed:%d", ret);
-        CAClearNetInterfaceInfoList(netInterfaceList);
-        return ret;
-    }
+#ifndef SINGLE_THREAD
+    CAIPDeinitializeQueueHandles();
+#endif
+}
 
-    uint32_t listLength = u_arraylist_length(netInterfaceList);
-    uint32_t netInfoSize = listLength;
+#ifndef SINGLE_THREAD
 
-#ifdef __WITH_DTLS__
-    if (listLength)
+void CAIPSendDataThread(void *threadData)
+{
+    CAIPData_t *ipData = (CAIPData_t *) threadData;
+    if (!ipData)
     {
-        netInfoSize = listLength * 2;
+        OIC_LOG(DEBUG, TAG, "Invalid ip data!");
+        return;
     }
-#endif
 
-    CAEndpoint_t *conInfo = (CAEndpoint_t *)OICCalloc(netInfoSize, sizeof (CAEndpoint_t));
-    if (!conInfo)
+    if (ipData->isMulticast)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Malloc Failed");
-        CAClearNetInterfaceInfoList(netInterfaceList);
-        return CA_MEMORY_ALLOC_FAILED;
+        //Processing for sending multicast
+        OIC_LOG(DEBUG, TAG, "Send Multicast Data is called");
+        CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true);
     }
-
-    uint32_t listIndex = 0;
-    uint32_t count = 0;
-    for (listIndex = 0; listIndex < listLength; listIndex++)
+    else
     {
-        CANetInfo_t *netInfo = (CANetInfo_t *) u_arraylist_get(netInterfaceList, listIndex);
-        if (!netInfo)
+        //Processing for sending unicast
+#ifdef __WITH_DTLS__
+        if (ipData->remoteEndpoint && ipData->remoteEndpoint->flags & CA_SECURE)
         {
-            continue;
+            OIC_LOG(INFO, TAG, "DTLS encrypt called");
+            CAResult_t result = CAencryptSsl(ipData->remoteEndpoint, ipData->data, ipData->dataLen);
+            if (CA_STATUS_OK != result)
+            {
+                OIC_LOG(ERROR, TAG, "CAencryptSsl failed!");
+            }
+            OIC_LOG_V(INFO, TAG, "CAencryptSsl returned with result[%d]", result);
         }
-
-        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);
-
-#ifdef __WITH_DTLS__
-        // copy secure unicast server information
+        else
         {
-            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);
+            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
-        count ++;
     }
-    *size = count;
-    *info = conInfo;
-    CAClearNetInterfaceInfoList(netInterfaceList);
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
 }
 
-CAResult_t CAReadIPData()
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-    CAIPPullData();
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
+#endif
 
-CAResult_t CAIPStopServers()
+#ifndef SINGLE_THREAD
+CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data,
+                           uint32_t dataLength, bool isMulticast)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
+    VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
+    VERIFY_NON_NULL_RET(data, TAG, "IPData is NULL", NULL);
 
-    // Stop all unicast and multicast servers.
-    if (CA_STATUS_OK == CAIPStopAllServers())
+    CAIPData_t *ipData = (CAIPData_t *) OICMalloc(sizeof(*ipData));
+    if (!ipData)
     {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAIPStopAllServers success");
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return NULL;
     }
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAStopIP()
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-#ifdef __WITH_DTLS__
-    CAAdapterNetDtlsDeInit();
-#endif
-
-    // Stop IP network monitor
-    CAIPStopNetworkMonitor();
-
-#ifndef SINGLE_THREAD
-    // Stop send queue thread
-    if (g_sendQueueHandle)
+    ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
+    ipData->data = (void *) OICMalloc(dataLength);
+    if (!ipData->data)
     {
-        CAQueueingThreadStop(g_sendQueueHandle);
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        CAFreeIPData(ipData);
+        return NULL;
     }
-#endif
 
-    // Stop Unicast, Secured unicast and Multicast servers running
-    CAResult_t result = CAIPStopServers();
-    if (CA_STATUS_OK != result)
-    {
-        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "stop srv fail:%d", result);
-    }
+    memcpy(ipData->data, data, dataLength);
+    ipData->dataLen = dataLength;
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return result;
+    ipData->isMulticast = isMulticast;
+
+    return ipData;
 }
 
-void CATerminateIP()
+void CAFreeIPData(CAIPData_t *ipData)
 {
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    // Stop IP adapter
-    CAStopIP();
-
-#ifdef __WITH_DTLS__
-    CADTLSSetAdapterCallbacks(NULL, NULL, 0);
-#endif
-
-    CAIPSetPacketReceiveCallback(NULL);
+    VERIFY_NON_NULL_VOID(ipData, TAG, "ipData is NULL");
 
-    // Terminate IP server
-    CAIPTerminateServer();
-
-    // Terminate network monitor
-    CAIPSetConnectionStateChangeCallback(NULL);
-    CAIPTerminateNetworkMonitor();
+    CAFreeEndpoint(ipData->remoteEndpoint);
+    OICFree(ipData->data);
+    OICFree(ipData);
+}
 
-#ifndef SINGLE_THREAD
-    // Terminate message queue handler
-    CAIPDeinitializeQueueHandles();
-#endif
+void CADataDestroyer(void *data, uint32_t size)
+{
+    if (size < sizeof(CAIPData_t))
+    {
+        OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
+    }
+    CAIPData_t *etdata = (CAIPData_t *) data;
 
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    CAFreeIPData(etdata);
 }
+
+#endif // SINGLE_THREAD