Merge branch 'master' into notification-service
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / cainterfacecontroller.c
index 33124b8..5153b69 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdint.h>
+#include <inttypes.h>
 
+#include "logger.h"
+#include "oic_malloc.h"
+#include "caadapterutils.h"
+#include "canetworkconfigurator.h"
 #include "cainterfacecontroller.h"
-#include "cawifiadapter.h"
-#include "caethernetadapter.h"
 #include "caedradapter.h"
 #include "caleadapter.h"
-#include "cawifiadapter.h"
-#include "caethernetadapter.h"
-#include "canetworkconfigurator.h"
+#include "canfcadapter.h"
 #include "caremotehandler.h"
-#include "oic_malloc.h"
-#include "logger.h"
-#include "uthreadpool.h"
+#include "cathreadpool.h"
+#include "caipadapter.h"
+#include "cainterface.h"
+
+#ifdef RA_ADAPTER
+#include "caraadapter.h"
+#endif
 
-#define TAG PCF("CA")
+#ifdef TCP_ADAPTER
+#include "catcpadapter.h"
+#endif
 
-#define CA_MEMORY_ALLOC_CHECK(arg) { if (arg == NULL) {OIC_LOG_V(DEBUG, TAG, "memory error"); goto memory_error_exit;} }
+#define TAG "OIC_CA_INF_CTR"
 
-#define CA_CONNECTIVITY_TYPE_NUM   4
+#define CA_MEMORY_ALLOC_CHECK(arg) {if (arg == NULL) \
+    {OIC_LOG(ERROR, TAG, "memory error");goto memory_error_exit;} }
 
-static CAConnectivityHandler_t gAdapterHandler[CA_CONNECTIVITY_TYPE_NUM];
+static CAConnectivityHandler_t *g_adapterHandler = NULL;
 
-static CANetworkPacketReceivedCallback gNetworkPacketReceivedCallback = NULL;
+static uint32_t g_numberOfAdapters = 0;
 
-static CANetworkChangeCallback gNetworkChangeCallback = NULL;
+static CANetworkPacketReceivedCallback g_networkPacketReceivedCallback = NULL;
 
-static int8_t CAGetAdapterIndex(CAConnectivityType_t cType)
+static CAAdapterStateChangedCB g_adapterChangeCallback = NULL;
+
+static CAConnectionStateChangedCB g_connChangeCallback = NULL;
+
+static CAErrorHandleCallback g_errorHandleCallback = NULL;
+
+static int CAGetAdapterIndex(CATransportAdapter_t cType)
 {
-    switch (cType)
+    for (uint32_t index=0 ; index < g_numberOfAdapters ; index++)
     {
-        case CA_ETHERNET:
-            return 0;
-        case CA_WIFI:
-            return 1;
-        case CA_EDR:
-            return 2;
-        case CA_LE:
-            return 3;
+        if (cType == g_adapterHandler[index].cType )
+         {
+             return index;
+         }
     }
     return -1;
 }
 
-static void CARegisterCallback(CAConnectivityHandler_t handler, CAConnectivityType_t cType)
+static void CARegisterCallback(CAConnectivityHandler_t handler)
 {
-    OIC_LOG(DEBUG, TAG, "CARegisterCallback - Entry");
-    int8_t index = -1;
-
-    index = CAGetAdapterIndex(cType);
-
-    if (index == -1)
+    if (handler.startAdapter == NULL ||
+        handler.startListenServer == NULL ||
+        handler.stopListenServer == NULL ||
+        handler.startDiscoveryServer == NULL ||
+        handler.sendData == NULL ||
+        handler.sendDataToAll == NULL ||
+        handler.GetnetInfo == NULL ||
+        handler.readData == NULL ||
+        handler.stopAdapter == NULL ||
+        handler.terminate == NULL)
     {
-        OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
+        OIC_LOG(ERROR, TAG, "connectivity handler is not enough to be used!");
         return;
     }
+    uint32_t numberofAdapters = g_numberOfAdapters + 1;
+    CAConnectivityHandler_t *adapterHandler = OICRealloc(g_adapterHandler,
+                                   (numberofAdapters) * sizeof(*adapterHandler));
+    if (NULL == adapterHandler)
+    {
+        OIC_LOG(ERROR, TAG, "Memory allocation failed during registration");
+        return;
+    }
+    g_adapterHandler = adapterHandler;
+    g_numberOfAdapters = numberofAdapters;
+    g_adapterHandler[g_numberOfAdapters-1] = handler;
 
-    memcpy(&gAdapterHandler[index], &handler, sizeof(CAConnectivityHandler_t));
+    OIC_LOG_V(DEBUG, TAG, "%d type adapter, register complete!", handler.cType);
+}
 
-    OIC_LOG_V(DEBUG, TAG, "%d type adapter, register complete!", cType);
+#ifdef RA_ADAPTER
+CAResult_t CASetAdapterRAInfo(const CARAInfo_t *caraInfo)
+{
+    return CASetRAInfo(caraInfo);
 }
+#endif
 
-static void CAReceivedPacketCallback(CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
+static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
+                                     const void *data, uint32_t dataLen)
 {
-    OIC_LOG(DEBUG, TAG, "receivedPacketCallback in interface controller");
+    if (g_networkPacketReceivedCallback != NULL)
+    {
+        g_networkPacketReceivedCallback(sep, data, dataLen);
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "network packet received callback is NULL!");
+    }
+}
 
+static void CAAdapterChangedCallback(CATransportAdapter_t adapter, CANetworkStatus_t status)
+{
     // Call the callback.
-    if (gNetworkPacketReceivedCallback != NULL)
+    if (g_adapterChangeCallback != NULL)
     {
-        gNetworkPacketReceivedCallback(endpoint, data, dataLen);
+        if (CA_INTERFACE_UP == status)
+        {
+            g_adapterChangeCallback(adapter, true);
+        }
+        else if (CA_INTERFACE_DOWN == status)
+        {
+            g_adapterChangeCallback(adapter, false);
+        }
+    }
+    OIC_LOG_V(DEBUG, TAG, "[%d]adapter status is changed to [%d]", adapter, status);
+}
+
+#if defined(TCP_ADAPTER) || defined(EDR_ADAPTER) || defined(LE_ADAPTER)
+static void CAConnectionChangedCallback(const CAEndpoint_t *info, bool isConnected)
+{
+    // Call the callback.
+    if (g_connChangeCallback != NULL)
+    {
+        g_connChangeCallback(info, isConnected);
     }
+    OIC_LOG_V(DEBUG, TAG, "[%s] connection status is changed to [%d]", info->addr, isConnected);
 }
+#endif
 
-static void CANetworkChangedCallback(CALocalConnectivity_t *info, CANetworkStatus_t status)
+static void CAAdapterErrorHandleCallback(const CAEndpoint_t *endpoint,
+                                         const void *data, uint32_t dataLen,
+                                         CAResult_t result)
 {
-    OIC_LOG(DEBUG, TAG, "Network Changed callback");
+    OIC_LOG(DEBUG, TAG, "received error from adapter in interfacecontroller");
 
     // Call the callback.
-    if (gNetworkChangeCallback != NULL)
+    if (g_errorHandleCallback != NULL)
     {
-        gNetworkChangeCallback(info, status);
+        g_errorHandleCallback(endpoint, data, dataLen, result);
     }
 }
 
-void CAInitializeAdapters(u_thread_pool_t handle)
+void CAInitializeAdapters(ca_thread_pool_t handle)
 {
     OIC_LOG(DEBUG, TAG, "initialize adapters..");
 
-    memset(gAdapterHandler, 0, sizeof(CAConnectivityHandler_t) * CA_CONNECTIVITY_TYPE_NUM);
-
     // Initialize adapters and register callback.
-#ifdef ETHERNET_ADAPTER
-    CAInitializeEthernet(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback,
-                         handle);
-#endif /* ETHERNET_ADAPTER */
-
-#ifdef WIFI_ADAPTER
-    CAInitializeWifi(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
-#endif /* WIFI_ADAPTER */
+#ifdef IP_ADAPTER
+    CAInitializeIP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                   CAAdapterErrorHandleCallback, handle);
+#endif /* IP_ADAPTER */
 
 #ifdef EDR_ADAPTER
-    CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
+    CAInitializeEDR(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                    CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
 #endif /* EDR_ADAPTER */
 
 #ifdef LE_ADAPTER
-    CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback, handle);
+    CAInitializeLE(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                   CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
 #endif /* LE_ADAPTER */
 
+#ifdef RA_ADAPTER
+    CAInitializeRA(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                   handle);
+#endif /* RA_ADAPTER */
+
+#ifdef TCP_ADAPTER
+    CAInitializeTCP(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                    CAConnectionChangedCallback, CAAdapterErrorHandleCallback, handle);
+#endif /* TCP_ADAPTER */
+
+#ifdef NFC_ADAPTER
+    CAInitializeNFC(CARegisterCallback, CAReceivedPacketCallback, CAAdapterChangedCallback,
+                    CAAdapterErrorHandleCallback, handle);
+#endif /* NFC_ADAPTER */
 }
 
 void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback)
 {
-    OIC_LOG(DEBUG, TAG, "Set packet received callback");
+    OIC_LOG(DEBUG, TAG, "Set Receiver handle callback");
 
-    gNetworkPacketReceivedCallback = callback;
+    g_networkPacketReceivedCallback = callback;
 }
 
-void CASetNetworkChangeCallback(CANetworkChangeCallback callback)
+void CASetNetworkMonitorCallbacks(CAAdapterStateChangedCB adapterCB,
+                                  CAConnectionStateChangedCB connCB)
 {
-    OIC_LOG(DEBUG, TAG, "Set network change callback");
+    OIC_LOG(DEBUG, TAG, "Set network monitoring callback");
 
-    gNetworkChangeCallback = callback;
+    g_adapterChangeCallback = adapterCB;
+    g_connChangeCallback = connCB;
 }
 
-void CAStartAdapter(CAConnectivityType_t cType)
+void CASetErrorHandleCallback(CAErrorHandleCallback errorCallback)
 {
-    OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", cType);
-
-    int8_t index = -1;
+    OIC_LOG(DEBUG, TAG, "Set error handle callback");
+    g_errorHandleCallback = errorCallback;
+}
 
-    index = CAGetAdapterIndex(cType);
+CAResult_t CAStartAdapter(CATransportAdapter_t transportType)
+{
+    OIC_LOG_V(DEBUG, TAG, "Start the adapter of CAConnectivityType[%d]", transportType);
 
-    if (index == -1)
+    int index = CAGetAdapterIndex(transportType);
+    if (0 > index)
     {
-        OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
-        return;
+        OIC_LOG(ERROR, TAG, "unknown connectivity type!");
+        return CA_STATUS_FAILED;
     }
 
-    if (gAdapterHandler[index].startAdapter != NULL)
+    CAResult_t res = CA_STATUS_FAILED;
+    if (g_adapterHandler[index].startAdapter != NULL)
     {
-        gAdapterHandler[index].startAdapter();
+        res = g_adapterHandler[index].startAdapter();
     }
+
+    return res;
 }
 
-void CAStopAdapter(CAConnectivityType_t cType)
+void CAStopAdapter(CATransportAdapter_t transportType)
 {
-    OIC_LOG_V(DEBUG, TAG, "Stop the adapter of CAConnectivityType[%d]", cType);
-
-    int8_t index = -1;
+    OIC_LOG_V(DEBUG, TAG, "Stop the adapter of CATransportType[%d]", transportType);
 
-    index = CAGetAdapterIndex(cType);
-
-    if (index == -1)
+    int index = CAGetAdapterIndex(transportType);
+    if (0 > index)
     {
-        OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
+        OIC_LOG(ERROR, TAG, "unknown transport type!");
         return;
     }
 
-    if (gAdapterHandler[index].stopAdapter != NULL)
+    if (g_adapterHandler[index].stopAdapter != NULL)
     {
-        gAdapterHandler[index].stopAdapter();
+        g_adapterHandler[index].stopAdapter();
     }
 }
 
-CAResult_t CAGetNetworkInfo(CALocalConnectivity_t **info, uint32_t *size)
+CAResult_t CAGetNetworkInfo(CAEndpoint_t **info, uint32_t *size)
 {
-    CAResult_t res = CA_STATUS_FAILED;
-    int8_t index = 0;
-    int8_t i = 0;
-
-    CALocalConnectivity_t *resInfo = NULL;
-    uint32_t resSize = 0;
-
-    CALocalConnectivity_t *tempInfo[CA_CONNECTIVITY_TYPE_NUM];
-    uint32_t tempSize[CA_CONNECTIVITY_TYPE_NUM];
-
-    memset(tempInfo, 0, sizeof(CALocalConnectivity_t *) * CA_CONNECTIVITY_TYPE_NUM);
-    memset(tempSize, 0, sizeof(uint32_t) * CA_CONNECTIVITY_TYPE_NUM);
-
-    // #1. get information each adapter
-    for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+    if (info == NULL || size == NULL)
     {
-        if (gAdapterHandler[index].GetnetInfo != NULL)
-        {
-            res = gAdapterHandler[index].GetnetInfo(&tempInfo[index], &tempSize[index]);
+        return CA_STATUS_INVALID_PARAM;
+    }
 
-            OIC_LOG_V(DEBUG, TAG, "%d adapter network info size is %d res:%d", index,
-                    tempSize[index], res);
-        }
+    CAEndpoint_t **tempInfo = (CAEndpoint_t**) OICCalloc(g_numberOfAdapters, sizeof(*tempInfo));
+    if (!tempInfo)
+    {
+        OIC_LOG(ERROR, TAG, "Out of memory!");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+    uint32_t *tempSize =(uint32_t*) OICCalloc(g_numberOfAdapters, sizeof(*tempSize));
+    if (!tempSize)
+    {
+        OIC_LOG(ERROR, TAG, "Out of memory!");
+        OICFree(tempInfo);
+        return CA_MEMORY_ALLOC_FAILED;
     }
 
-    resSize = 0;
-    for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+    CAResult_t res = CA_STATUS_FAILED;
+    size_t resSize = 0;
+    for (uint32_t index = 0; index < g_numberOfAdapters; index++)
     {
-        // check information
-        if (tempInfo[index] == NULL || tempSize[index] <= 0)
+        if (g_adapterHandler[index].GetnetInfo != NULL)
         {
-            continue;
+            // #1. get information for each adapter
+            res = g_adapterHandler[index].GetnetInfo(&tempInfo[index],
+                                                     &tempSize[index]);
+
+            // #2. total size
+            if (res == CA_STATUS_OK)
+            {
+                resSize += tempSize[index];
+            }
+
+            OIC_LOG_V(DEBUG,
+                      TAG,
+                      "%" PRIu32 " adapter network info size is %" PRIu32 " res:%d",
+                      index,
+                      tempSize[index],
+                      res);
         }
-
-        // #2. total size
-        resSize += tempSize[index];
     }
 
-    OIC_LOG_V(DEBUG, TAG, "network info total size is %d!", resSize);
+    OIC_LOG_V(DEBUG, TAG, "network info total size is %zu!", resSize);
 
-    if (resSize <= 0)
+    if (resSize == 0)
     {
-        res = CA_STATUS_FAILED;
-        return res;
+        OICFree(tempInfo);
+        OICFree(tempSize);
+        if (res == CA_ADAPTER_NOT_ENABLED || res == CA_NOT_SUPPORTED)
+        {
+            return res;
+        }
+        else
+        {
+            return CA_STATUS_FAILED;
+        }
     }
 
     // #3. add data into result
     // memory allocation
-    resInfo = (CALocalConnectivity_t *) OICMalloc(sizeof(CALocalConnectivity_t) * resSize);
+    CAEndpoint_t *resInfo = (CAEndpoint_t *) OICCalloc(resSize, sizeof (*resInfo));
     CA_MEMORY_ALLOC_CHECK(resInfo);
-    memset(resInfo, 0, sizeof(CALocalConnectivity_t) * resSize);
 
-    i = 0;
-    for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+    // #4. save data
+    *info = resInfo;
+    *size = resSize;
+
+    for (uint32_t index = 0; index < g_numberOfAdapters; index++)
     {
         // check information
-        if (tempInfo[index] == NULL || tempSize[index] <= 0)
+        if (tempSize[index] == 0)
         {
             continue;
         }
 
-        memcpy(resInfo + i, tempInfo[index], sizeof(CALocalConnectivity_t) * tempSize[index]);
+        memcpy(resInfo,
+               tempInfo[index],
+               sizeof(*resInfo) * tempSize[index]);
 
-        i += tempSize[index];
+        resInfo += tempSize[index];
 
         // free adapter data
         OICFree(tempInfo[index]);
+        tempInfo[index] = NULL;
     }
+    OICFree(tempInfo);
+    OICFree(tempSize);
 
-    // #5. save data
-    *info = resInfo;
-    *size = resSize;
-
-    OIC_LOG_V(DEBUG, TAG, "each network info save success!");
-
-    return res;
+    OIC_LOG(DEBUG, TAG, "each network info save success!");
+    return CA_STATUS_OK;
 
     // memory error label.
 memory_error_exit:
 
+    for (uint32_t index = 0; index < g_numberOfAdapters; index++)
+    {
+        OICFree(tempInfo[index]);
+        tempInfo[index] = NULL;
+    }
+    OICFree(tempInfo);
+    OICFree(tempSize);
+
     return CA_MEMORY_ALLOC_FAILED;
 }
 
-CAResult_t CASendUnicastData(CARemoteEndpoint_t* endpoint, void* data, uint32_t length)
+CAResult_t CASendUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
+                             CADataType_t dataType)
 {
-    OIC_LOG(DEBUG, TAG, "Send unicast data to enabled interface..");
-
-    int8_t index = -1;
-    CAResult_t res = CA_STATUS_FAILED;
-
     if (endpoint == NULL)
     {
-        OIC_LOG_V(DEBUG, TAG, "Invalid endpoint");
+        OIC_LOG(DEBUG, TAG, "Invalid endpoint");
         return CA_STATUS_INVALID_PARAM;
     }
 
-    CAConnectivityType_t type = endpoint->connectivityType;
-
-    index = CAGetAdapterIndex(type);
 
-    if (index == -1)
+    u_arraylist_t *list = CAGetSelectedNetworkList();
+    if (!list)
     {
-        OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
-        return CA_STATUS_INVALID_PARAM;
+        OIC_LOG(ERROR, TAG, "No selected network");
+        return CA_SEND_FAILED;
     }
+    CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
 
-    if (gAdapterHandler[index].sendData != NULL)
+    for (uint32_t i = 0; i < u_arraylist_length(list); i++)
     {
-        res = gAdapterHandler[index].sendData(endpoint, data, length);
-    }
-    //For Unicast , data will be deleted by adapters
+        void* ptrType = u_arraylist_get(list, i);
+
+        if (NULL == ptrType)
+        {
+            continue;
+        }
+
+        CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
+        if (0 == (connType & requestedAdapter))
+        {
+            continue;
+        }
 
-    CADestroyRemoteEndpointInternal(endpoint);
+        int index = CAGetAdapterIndex(connType);
 
-    return res;
+        if (-1 == index)
+        {
+            OIC_LOG(ERROR, TAG, "unknown transport type!");
+            return CA_STATUS_INVALID_PARAM;
+        }
+
+        int32_t sentDataLen = 0;
+
+        if (NULL != g_adapterHandler[index].sendData)
+        {
+            OIC_LOG(DEBUG, TAG, "unicast message to adapter");
+            sentDataLen = g_adapterHandler[index].sendData(endpoint, data, length, dataType);
+        }
+
+        if (sentDataLen != (int32_t)length)
+        {
+            OIC_LOG(ERROR, TAG, "error in sending data. Error will be reported in adapter");
+#ifdef SINGLE_THREAD
+            //in case of single thread, no error handler. Report error immediately
+            return CA_SEND_FAILED;
+#endif
+        }
+
+    }
+
+    return CA_STATUS_OK;
 }
 
-CAResult_t CASendMulticastData(void *data, uint32_t length)
+CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length,
+                               CADataType_t dataType)
 {
-    OIC_LOG(DEBUG, TAG, "Send multicast data to enabled interface..");
-
-    uint8_t i, type;
-    int8_t index = -1;
-    CAResult_t res = CA_STATUS_FAILED;
     u_arraylist_t *list = CAGetSelectedNetworkList();
-
     if (!list)
     {
         OIC_LOG(DEBUG, TAG, "No selected network");
-        return CA_STATUS_FAILED;
+        return CA_SEND_FAILED;
     }
 
-    for (i = 0; i < u_arraylist_length(list); i++)
+    CATransportAdapter_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
+    size_t selectedLength = u_arraylist_length(list);
+    for (size_t i = 0; i < selectedLength; i++)
     {
-        type = *(uint8_t*) u_arraylist_get(list, i);
+        void* ptrType = u_arraylist_get(list, i);
 
-        index = CAGetAdapterIndex(type);
+        if (NULL == ptrType)
+        {
+            continue;
+        }
 
-        if (index == -1)
+        CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
+        if (0 == (connType & requestedAdapter))
         {
-            OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
             continue;
         }
 
-        if (gAdapterHandler[index].sendDataToAll != NULL)
+        int index = CAGetAdapterIndex(connType);
+        if (0 > index)
+        {
+            OIC_LOG(ERROR, TAG, "unknown connectivity type!");
+            continue;
+        }
+
+        uint32_t sentDataLen = 0;
+
+        if (NULL != g_adapterHandler[index].sendDataToAll)
         {
-            void* payload = (void*) OICMalloc(length);
+            void *payload = (void *) OICMalloc(length);
+            if (!payload)
+            {
+                OIC_LOG(ERROR, TAG, "Out of memory!");
+                return CA_MEMORY_ALLOC_FAILED;
+            }
             memcpy(payload, data, length);
-            res = gAdapterHandler[index].sendDataToAll(payload, length);
+            sentDataLen = g_adapterHandler[index].sendDataToAll(endpoint, payload, length, dataType);
+            OICFree(payload);
+        }
+
+        if (sentDataLen != length)
+        {
+            OIC_LOG(ERROR, TAG, "sendDataToAll failed! Error will be reported from adapter");
+#ifdef SINGLE_THREAD
+            //in case of single thread, no error handler. Report error immediately
+            return CA_SEND_FAILED;
+#endif
         }
     }
-    return res;
+
+    return CA_STATUS_OK;
 }
 
 CAResult_t CAStartListeningServerAdapters()
 {
-    OIC_LOG(DEBUG, TAG, "Start listening server from adapters..");
+    CAResult_t result = CA_STATUS_FAILED;
 
-    uint8_t i, type;
-    int8_t index = -1;
     u_arraylist_t *list = CAGetSelectedNetworkList();
+    if (!list)
+    {
+        OIC_LOG(ERROR, TAG, "No selected network");
+        return result;
+    }
+
+    size_t length = u_arraylist_length(list);
+    for (size_t i = 0; i < length; i++)
+    {
+        void* ptrType = u_arraylist_get(list, i);
+
+        if(ptrType == NULL)
+        {
+            continue;
+        }
+
+        CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
+
+        int index = CAGetAdapterIndex(connType);
+        if (0 > index)
+        {
+            OIC_LOG(ERROR, TAG, "unknown connectivity type!");
+            continue;
+        }
+
+        if (g_adapterHandler[index].startListenServer != NULL)
+        {
+            const CAResult_t tmp =
+                g_adapterHandler[index].startListenServer();
+
+            // Successful listen if at least one adapter started.
+            if (CA_STATUS_OK == tmp)
+            {
+                result = tmp;
+            }
+        }
+    }
 
+    return result;
+}
+
+CAResult_t CAStopListeningServerAdapters()
+{
+    u_arraylist_t *list = CAGetSelectedNetworkList();
     if (!list)
     {
-        OIC_LOG(DEBUG, TAG, "No selected network");
+        OIC_LOG(ERROR, TAG, "No selected network");
         return CA_STATUS_FAILED;
     }
 
-    for (i = 0; i < u_arraylist_length(list); i++)
+    size_t length = u_arraylist_length(list);
+    for (size_t i = 0; i < length; i++)
     {
-        type = *(uint8_t*) u_arraylist_get(list, i);
+        void* ptrType = u_arraylist_get(list, i);
+        if(ptrType == NULL)
+        {
+            continue;
+        }
 
-        index = CAGetAdapterIndex(type);
+        CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
 
-        if (index == -1)
+        int index = CAGetAdapterIndex(connType);
+        if (0 > index)
         {
-            OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
+            OIC_LOG(ERROR, TAG, "unknown connectivity type!");
             continue;
         }
 
-        if (gAdapterHandler[index].startListenServer != NULL)
+        if (g_adapterHandler[index].stopListenServer != NULL)
         {
-            gAdapterHandler[index].startListenServer();
+            g_adapterHandler[index].stopListenServer();
         }
     }
 
@@ -377,50 +579,102 @@ CAResult_t CAStartListeningServerAdapters()
 
 CAResult_t CAStartDiscoveryServerAdapters()
 {
-    OIC_LOG(DEBUG, TAG, "Start discovery server from adapters..");
+    CAResult_t result = CA_STATUS_FAILED;
 
-    uint8_t i, type;
-    int8_t index = -1;
     u_arraylist_t *list = CAGetSelectedNetworkList();
 
     if (!list)
     {
-        OIC_LOG(DEBUG, TAG, "No selected network");
-        return CA_STATUS_FAILED;
+        OIC_LOG(ERROR, TAG, "No selected network");
+        return result;
     }
 
-    for (i = 0; i < u_arraylist_length(list); i++)
+    size_t length = u_arraylist_length(list);
+    for (size_t i = 0; i < length; i++)
     {
-        type = *(uint8_t*) u_arraylist_get(list, i);
+        void* ptrType = u_arraylist_get(list, i);
+
+        if(ptrType == NULL)
+        {
+            continue;
+        }
 
-        index = CAGetAdapterIndex(type);
+        CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
 
-        if (index == -1)
+        int index = CAGetAdapterIndex(connType);
+        if (0 > index)
         {
-            OIC_LOG_V(DEBUG, TAG, "unknown connectivity type!");
+            OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
             continue;
         }
 
-        if (gAdapterHandler[index].startDiscoverServer != NULL)
+        if (g_adapterHandler[index].startDiscoveryServer != NULL)
         {
-            gAdapterHandler[index].startDiscoverServer();
+            const CAResult_t tmp =
+                g_adapterHandler[index].startDiscoveryServer();
+
+            // Successful discovery if at least one adapter started.
+            if (CA_STATUS_OK == tmp)
+            {
+                result = tmp;
+            }
         }
     }
 
-    return CA_STATUS_OK;
+    return result;
 }
 
 void CATerminateAdapters()
 {
-    OIC_LOG(DEBUG, TAG, "terminate all adapters..");
+    for (uint32_t index = 0; index < g_numberOfAdapters; index++)
+    {
+        if (g_adapterHandler[index].terminate != NULL)
+        {
+            g_adapterHandler[index].terminate();
+        }
+    }
+
+    OICFree(g_adapterHandler);
+    g_adapterHandler = NULL;
+    g_numberOfAdapters = 0;
+}
+
+#ifdef SINGLE_THREAD
+CAResult_t CAReadData()
+{
+    u_arraylist_t *list = CAGetSelectedNetworkList();
 
-    uint8_t index;
+    if (!list)
+    {
+        return CA_STATUS_FAILED;
+    }
 
-    for (index = 0; index < CA_CONNECTIVITY_TYPE_NUM; index++)
+    uint8_t i = 0;
+    for (i = 0; i < u_arraylist_length(list); i++)
     {
-        if (gAdapterHandler[index].terminate != NULL)
+        void *ptrType = u_arraylist_get(list, i);
+        if (NULL == ptrType)
         {
-            gAdapterHandler[index].terminate();
+            OIC_LOG(ERROR, TAG, "get list fail");
+            return CA_STATUS_FAILED;
+        }
+
+        CATransportAdapter_t connType = *(CATransportAdapter_t *) ptrType;
+
+        int index = CAGetAdapterIndex(connType);
+        if (0 > index)
+        {
+            OIC_LOG(DEBUG, TAG, "unknown connectivity type!");
+            continue;
+        }
+
+        if (g_adapterHandler[index].readData != NULL)
+        {
+            g_adapterHandler[index].readData();
         }
     }
+
+    return CA_STATUS_OK;
 }
+#endif
+