modify the preprocessor to stop the thread in ipadapter
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipadapter.c
index 0a455f4..48905f6 100644 (file)
 #endif
 #include "camutex.h"
 #include "uarraylist.h"
+#include "caremotehandler.h"
 #include "logger.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 
 /**
  * @def IP_ADAPTER_TAG
  * @brief Logging tag for module name
  */
-#define IP_ADAPTER_TAG "IP_ADAP"
+#define IP_ADAPTER_TAG "IPAD"
 
 /**
  * @def CA_PORT
  * @brief Port to listen for incoming data
  */
-#define CA_PORT   6298
+#ifdef ARDUINO
+#define CA_PORT   55555
+#else
+#define CA_PORT   0
+#endif
 
 /**
  * @def CA_SECURE_PORT
  */
 #define CA_MULTICAST_IP "224.0.1.187"
 
+#ifndef SINGLE_THREAD
 /**
  * @var CAIPData
  * @brief Holds inter thread ip data information.
  */
 typedef struct
 {
-    CARemoteEndpoint_t *remoteEndpoint;
+    CAEndpoint_t *remoteEndpoint;
     void *data;
     uint32_t dataLen;
+    bool isMulticast;
 } CAIPData;
 
 /**
+ * @var g_sendQueueHandle
+ * @brief Queue handle for Send Data
+ */
+static CAQueueingThread_t *g_sendQueueHandle = NULL;
+#endif
+
+/**
  * @var g_networkPacketCallback
  * @brief Network Packet Received Callback to CA
  */
@@ -89,10 +104,10 @@ static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
 static CANetworkChangeCallback g_networkChangeCallback = NULL;
 
 /**
- * @var g_sendQueueHandle
- * @brief Queue handle for Send Data
+ * @var g_errorCallback
+ * @brief error Callback to CA adapter
  */
-static CAQueueingThread_t *g_sendQueueHandle = NULL;
+static CAErrorHandleCallback g_errorCallback = NULL;
 
 /**
  * @var g_threadPool
@@ -100,29 +115,32 @@ static CAQueueingThread_t *g_sendQueueHandle = NULL;
  */
 static ca_thread_pool_t g_threadPool = NULL;
 
-static CAResult_t CAIPInitializeQueueHandles();
-
-static void CAIPDeinitializeQueueHandles();
-
 static void CAIPNotifyNetworkChange(const char *address, uint16_t port,
-                                          CANetworkStatus_t status);
+                                    CANetworkStatus_t status);
 
 static void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status);
 
-static void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port, const void *data,
-                                       uint32_t dataLength, bool isSecured,
-                                       const CARemoteId_t *identity);
+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 char *ipAddress, uint16_t port,
-                                       const void *data, uint32_t dataLength);
+static uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint,
+                                 const void *data, uint32_t dataLength);
 #endif
 
 static CAResult_t CAIPStopServers();
 
+#ifndef SINGLE_THREAD
+
+static CAResult_t CAIPInitializeQueueHandles();
+
+static void CAIPDeinitializeQueueHandles();
+
 static void CAIPSendDataThread(void *threadData);
 
-static CAIPData *CACreateIPData(const CARemoteEndpoint_t *remoteEndpoint,
-                                            const void *data, uint32_t dataLength);
+static CAIPData *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
+                                const void *data, uint32_t dataLength, bool isMulticast);
 void CAFreeIPData(CAIPData *ipData);
 
 static void CADataDestroyer(void *data, uint32_t size);
@@ -170,21 +188,124 @@ void CAIPDeinitializeQueueHandles()
     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
+
 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");
 
-    CALocalConnectivity_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_IPV4, address);
+    CAEndpoint_t *localEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
+                                                         CA_ADAPTER_IP,
+                                                         address, port);
     if (!localEndpoint)
     {
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "localEndpoint creation failed!");
         return;
     }
 
-    localEndpoint->addressInfo.IP.port = port;
-
     if (g_networkChangeCallback)
     {
         g_networkChangeCallback(localEndpoint, status);
@@ -194,7 +315,7 @@ void CAIPNotifyNetworkChange(const char *address, uint16_t port, CANetworkStatus
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "g_networkChangeCallback is NULL");
     }
 
-    CAAdapterFreeLocalEndpoint(localEndpoint);
+    CAFreeEndpoint(localEndpoint);
 
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
 }
@@ -208,7 +329,7 @@ void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
     if (CA_INTERFACE_UP == status)
     {
         uint16_t port = CA_PORT;
-        CAResult_t ret = CAIPStartUnicastServer(ipAddress, &port, false, false);
+        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);
@@ -220,7 +341,7 @@ void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
 
 #ifdef __WITH_DTLS__
         port = CA_SECURE_PORT;
-        ret = CAIPStartUnicastServer(ipAddress, &port, false, true);
+        ret = CAIPStartUnicastServer(ipAddress, &port, true);
         if (CA_STATUS_OK == ret)
         {
             OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Secure Unicast server started on %d", port);
@@ -258,16 +379,19 @@ void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
 }
 
 #ifdef __WITH_DTLS__
-uint32_t CAIPPacketSendCB(const char *ipAddress, uint16_t port,
-        const void *data, uint32_t dataLength)
+uint32_t CAIPPacketSendCB(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
-    VERIFY_NON_NULL_RET(ipAddress, IP_ADAPTER_TAG, "ipAddress is NULL", 0);
-
+    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(ipAddress, port, data, dataLength, false, true);
+    uint32_t sentLength = CAIPSendData(endpoint, data, dataLength, false);
+
+    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);
 
@@ -277,72 +401,126 @@ uint32_t CAIPPacketSendCB(const char *ipAddress, uint16_t port,
 }
 #endif
 
-void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port, const void *data,
-                                uint32_t dataLength, bool isSecured,
-                                const CARemoteId_t *identity)
+void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
+                          uint32_t dataLength)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
-    VERIFY_NON_NULL_VOID(ipAddress, IP_ADAPTER_TAG, "ipAddress is NULL");
-
+    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", ipAddress, port);
+    OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
 
-    // CA is freeing this memory
-    CARemoteEndpoint_t *endPoint = CAAdapterCreateRemoteEndpoint(CA_IPV4, ipAddress, NULL );
-    if (!endPoint)
+    void *buf = OICCalloc(dataLength + 1, sizeof (char));
+    if (!buf)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG, "EndPoint creation failed!");
+        OIC_LOG(ERROR, IP_ADAPTER_TAG, "Memory Allocation failed!");
         return;
     }
-    endPoint->addressInfo.IP.port = port;
-    endPoint->isSecured = isSecured;
-    if (identity)
+    memcpy(buf, data, dataLength);
+
+    if (g_networkPacketCallback)
+    {
+        g_networkPacketCallback(endpoint, buf, dataLength);
+    }
+    else
     {
-        endPoint->identity = *identity;
+        OICFree(buf);
     }
+    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+}
 
+void CAIPErrorHandler (const CAEndpoint_t *endpoint, const void *data,
+                       uint32_t dataLength, CAResult_t result)
+{
+    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
-    void *buf = OICCalloc(dataLength + 1, sizeof(char));
+    VERIFY_NON_NULL_VOID(endpoint, IP_ADAPTER_TAG, "endpoint 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!");
-        CAAdapterFreeRemoteEndpoint(endPoint);
         return;
     }
     memcpy(buf, data, dataLength);
-    if (g_networkPacketCallback)
+    if (g_errorCallback)
     {
-        g_networkPacketCallback(endPoint, buf, dataLength);
+        g_errorCallback(endpoint, buf, dataLength, result);
     }
     else
     {
         OICFree(buf);
-        CAAdapterFreeRemoteEndpoint(endPoint);
     }
 
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+
+    return;
+}
+
+int32_t CAIPSendDataInternal(const CAEndpoint_t *remoteEndpoint, const void *data,
+                             uint32_t dataLength, bool isMulticast)
+{
+    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;
 }
 
 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
-                                CANetworkPacketReceivedCallback networkPacketCallback,
-                                CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
+                          CANetworkPacketReceivedCallback networkPacketCallback,
+                          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");
+#ifndef SINGLE_THREAD
     VERIFY_NON_NULL(handle, IP_ADAPTER_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);
+        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to initialize n/w monitor[%d]", ret);
         return ret;
     }
     CAIPSetConnectionStateChangeCallback(CAIPConnectionStateCB);
@@ -356,10 +534,11 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
     }
 
     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
+    CAIPSetErrorHandleCallback(CAIPErrorHandler);
 #ifdef __WITH_DTLS__
     CAAdapterNetDtlsInit();
 
-    CADTLSSetAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, CA_IPV4);
+    CADTLSSetAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, 0);
 #endif
 
     CAConnectivityHandler_t ipHandler;
@@ -372,16 +551,17 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
     ipHandler.readData = CAReadIPData;
     ipHandler.stopAdapter = CAStopIP;
     ipHandler.terminate = CATerminateIP;
-    registerCallback(ipHandler, CA_IPV4);
+    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;
     }
-
-    OIC_LOG(INFO, IP_ADAPTER_TAG, "OUT IntializeIP is Success");
+#endif
+    OIC_LOG(INFO, IP_ADAPTER_TAG, "OUT");
     return CA_STATUS_OK;
 }
 
@@ -397,12 +577,14 @@ CAResult_t CAStartIP()
         return ret;
     }
 
+#ifndef SINGLE_THREAD
     // Start send queue thread
     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
     {
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "Failed to Start Send Data Thread");
         return CA_STATUS_FAILED;
     }
+#endif
 
     bool retVal = CAIPIsConnected();
     if (false == retVal)
@@ -411,6 +593,16 @@ CAResult_t CAStartIP()
         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)
+    {
+        OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Start unicast serv failed[%d]", ret);
+
+    }
+#else
     u_arraylist_t *netInterfaceList = u_arraylist_create();
 
     VERIFY_NON_NULL(netInterfaceList, IP_ADAPTER_TAG, "netInterfaceList is NULL");
@@ -433,7 +625,7 @@ CAResult_t CAStartIP()
             continue;
         }
         uint16_t unicastPort = CA_PORT;
-        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, false, false);
+        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, false);
         if (CA_STATUS_OK == ret)
         {
             OIC_LOG_V(DEBUG, IP_ADAPTER_TAG, "Unicast server started on %d port",
@@ -442,7 +634,7 @@ CAResult_t CAStartIP()
 
 #ifdef __WITH_DTLS__
         unicastPort = CA_SECURE_PORT;
-        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, false, true);
+        ret = CAIPStartUnicastServer(netInfo->ipAddress, &unicastPort, true);
 
         if (CA_STATUS_OK == ret)
         {
@@ -452,6 +644,7 @@ CAResult_t CAStartIP()
 #endif
     }
     CAClearNetInterfaceInfoList(netInterfaceList);
+#endif
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
     return ret;
 }
@@ -460,19 +653,27 @@ 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. Couldn't start multicast server");
-        return CA_STATUS_OK;
+        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");
 
-    CAResult_t ret = CAIPGetInterfaceInfo(&netInterfaceList);
+    ret = CAIPGetInterfaceInfo(&netInterfaceList);
     if (CA_STATUS_OK != ret)
     {
         OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "Failed to get IP interface info [%d]", ret);
@@ -501,6 +702,7 @@ CAResult_t CAStartIPListeningServer()
     }
 
     CAClearNetInterfaceInfoList(netInterfaceList);
+#endif
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
     return ret;
 }
@@ -508,72 +710,44 @@ CAResult_t CAStartIPListeningServer()
 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 CARemoteEndpoint_t *remoteEndpoint, const void *data,
-                                  uint32_t dataLength)
+int32_t CASendIPUnicastData(const CAEndpoint_t *remoteEndpoint,
+                            const void *data, uint32_t dataLength)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
     VERIFY_NON_NULL_RET(remoteEndpoint, IP_ADAPTER_TAG, "remoteEndpoint", -1);
     VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1);
-    VERIFY_NON_NULL_RET(g_sendQueueHandle, IP_ADAPTER_TAG, "sendQueueHandle", -1);
-
     if (0 == dataLength)
     {
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length");
         return -1;
     }
 
-    // Create IPData to add to queue
-    CAIPData *ipData = CACreateIPData(remoteEndpoint, data, dataLength);
-    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));
-
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-        return dataLength;
-    }
+    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    return CAIPSendDataInternal(remoteEndpoint, data, dataLength, false);
 }
 
-int32_t CASendIPMulticastData(const void *data, uint32_t dataLength)
+int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
     VERIFY_NON_NULL_RET(data, IP_ADAPTER_TAG, "data", -1);
-    VERIFY_NON_NULL_RET(g_sendQueueHandle, IP_ADAPTER_TAG, "sendQueueHandle", -1);
-
     if (0 == dataLength)
     {
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "Invalid Data Length");
         return -1;
     }
 
-    // Create IPData to add to queue
-    CAIPData *ipData = CACreateIPData(NULL, data, dataLength);
-    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));
-
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-        return dataLength;
-    }
+    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
+    return CAIPSendDataInternal(endpoint, data, dataLength, true);
 }
 
-CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
+CAResult_t CAGetIPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
@@ -583,8 +757,7 @@ CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *s
     bool retVal = CAIPIsConnected();
     if (false == retVal)
     {
-        OIC_LOG(ERROR, IP_ADAPTER_TAG,
-                "Failed to get interface address, IP not Connected");
+        OIC_LOG(ERROR, IP_ADAPTER_TAG, "IP not Connected");
         return CA_ADAPTER_NOT_ENABLED;
     }
 
@@ -610,8 +783,7 @@ CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *s
     }
 #endif
 
-    CALocalConnectivity_t *conInfo = (CALocalConnectivity_t *) OICCalloc(
-                                      netInfoSize, sizeof(CALocalConnectivity_t));
+    CAEndpoint_t *conInfo = (CAEndpoint_t *)OICCalloc(netInfoSize, sizeof (CAEndpoint_t));
     if (!conInfo)
     {
         OIC_LOG(ERROR, IP_ADAPTER_TAG, "Malloc Failed");
@@ -629,21 +801,23 @@ CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *s
             continue;
         }
 
-        conInfo[count].type = CA_IPV4;
-        conInfo[count].isSecured = false;
-        conInfo[count].addressInfo.IP.port = CAGetServerPortNum(netInfo->ipAddress, false);
-        strncpy(conInfo[count].addressInfo.IP.ipAddress, netInfo->ipAddress,
-                strlen(netInfo->ipAddress));
+        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
         {
             count ++;
-            conInfo[count].type = CA_IPV4;
-            conInfo[count].isSecured = true;
-            conInfo[count].addressInfo.IP.port = CAGetServerPortNum(netInfo->ipAddress, true);
-            strncpy(conInfo[count].addressInfo.IP.ipAddress, netInfo->ipAddress,
-                    strlen(netInfo->ipAddress));
+            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);
         }
 #endif
         count ++;
@@ -659,7 +833,7 @@ CAResult_t CAGetIPInterfaceInformation(CALocalConnectivity_t **info, uint32_t *s
 CAResult_t CAReadIPData()
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
+    CAIPPullData();
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
     return CA_STATUS_OK;
 }
@@ -689,17 +863,23 @@ CAResult_t CAStopIP()
     // Stop IP network monitor
     CAIPStopNetworkMonitor();
 
+#ifndef SINGLE_THREAD
     // Stop send queue thread
     if (g_sendQueueHandle)
     {
         CAQueueingThreadStop(g_sendQueueHandle);
     }
+#endif
 
     // Stop Unicast, Secured unicast and Multicast servers running
-    CAIPStopServers();
+    CAResult_t result = CAIPStopServers();
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG_V(ERROR, IP_ADAPTER_TAG, "stop srv fail:%d", result);
+    }
 
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-    return CA_STATUS_OK;
+    return result;
 }
 
 void CATerminateIP()
@@ -710,7 +890,7 @@ void CATerminateIP()
     CAStopIP();
 
 #ifdef __WITH_DTLS__
-    CADTLSSetAdapterCallbacks(NULL, NULL, CA_IPV4);
+    CADTLSSetAdapterCallbacks(NULL, NULL, 0);
 #endif
 
     CAIPSetPacketReceiveCallback(NULL);
@@ -722,106 +902,10 @@ void CATerminateIP()
     CAIPSetConnectionStateChangeCallback(NULL);
     CAIPTerminateNetworkMonitor();
 
+#ifndef SINGLE_THREAD
     // Terminate message queue handler
     CAIPDeinitializeQueueHandles();
-
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
-}
-
-void CAIPSendDataThread(void *threadData)
-{
-    OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
-
-    CAIPData *ipData = (CAIPData *) threadData;
-    if (!ipData)
-    {
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Invalid ip data!");
-        return;
-    }
-
-    //If remoteEndpoint is NULL, its Multicast, else its Unicast.
-    if (ipData->remoteEndpoint)
-    {
-        //Processing for sending unicast
-        char *address = ipData->remoteEndpoint->addressInfo.IP.ipAddress;
-        uint16_t port = ipData->remoteEndpoint->addressInfo.IP.port;
-
-#ifdef __WITH_DTLS__
-        if (!ipData->remoteEndpoint->isSecured)
-        {
-            OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Unicast Data is called");
-            CAIPSendData(address, port, ipData->data, ipData->dataLen, false,
-                               ipData->remoteEndpoint->isSecured);
-        }
-        else
-        {
-            OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!");
-            CAResult_t result = CAAdapterNetDtlsEncrypt(address, port, ipData->data,
-                                                        ipData->dataLen, CA_IPV4);
-
-            if (CA_STATUS_OK != result)
-            {
-                OIC_LOG(ERROR, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!");
-            }
-            OIC_LOG_V(DEBUG, IP_ADAPTER_TAG,
-                      "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
-        }
-#else
-        CAIPSendData(address, port, ipData->data, ipData->dataLen, false,
-                           ipData->remoteEndpoint->isSecured);
 #endif
-    }
-    else
-    {
-        //Processing for sending multicast
-        OIC_LOG(DEBUG, IP_ADAPTER_TAG, "Send Multicast Data is called");
-        CAIPSendData(CA_MULTICAST_IP, CA_MCAST_PORT, ipData->data,
-                           ipData->dataLen, true, false);
-    }
 
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "OUT");
 }
-
-CAIPData *CACreateIPData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
-                                     uint32_t dataLength)
-{
-    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 = CAAdapterCopyRemoteEndpoint(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;
-
-    return ipData;
-}
-
-void CAFreeIPData(CAIPData *ipData)
-{
-    VERIFY_NON_NULL_VOID(ipData, IP_ADAPTER_TAG, "ipData is NULL");
-
-    CAAdapterFreeRemoteEndpoint(ipData->remoteEndpoint);
-    OICFree(ipData->data);
-    OICFree(ipData);
-}
-
-void CADataDestroyer(void *data, uint32_t size)
-{
-    CAIPData *etdata = (CAIPData *) data;
-
-    CAFreeIPData(etdata);
-}
-