Update snapshot(2017-11-14)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / cainterfacecontroller.c
index 525f79f..c892289 100755 (executable)
@@ -37,6 +37,7 @@
 #include "cainterface.h"
 #include "caipinterface.h"
 #include <coap/utlist.h>
+#include "octhread.h"
 
 #ifdef RA_ADAPTER
 #include "caraadapter.h"
@@ -66,6 +67,11 @@ static CAErrorHandleCallback g_errorHandleCallback = NULL;
 static struct CANetworkCallback_t * g_networkChangeCallbackList = NULL;
 
 /**
+ * Mutex to synchronize network change list.
+ */
+static oc_mutex g_mutexNetCallbackList = NULL;
+
+/**
  * network callback structure is handling
  * for adapter state changed and connection state changed event.
  */
@@ -146,12 +152,14 @@ static CAResult_t AddNetworkStateChangedCallback(CAAdapterStateChangedCB adapter
         return CA_STATUS_INVALID_PARAM;
     }
 
+    oc_mutex_lock(g_mutexNetCallbackList);
     CANetworkCallback_t* callback = NULL;
     LL_FOREACH(g_networkChangeCallbackList, callback)
     {
         if (callback && adapterCB == callback->adapter && connCB == callback->conn)
         {
             OIC_LOG(DEBUG, TAG, "this callback is already added");
+            oc_mutex_unlock(g_mutexNetCallbackList);
             return CA_STATUS_OK;
         }
     }
@@ -160,12 +168,14 @@ static CAResult_t AddNetworkStateChangedCallback(CAAdapterStateChangedCB adapter
     if (NULL == callback)
     {
         OIC_LOG(ERROR, TAG, "Memory allocation failed during registration");
+        oc_mutex_unlock(g_mutexNetCallbackList);
         return CA_MEMORY_ALLOC_FAILED;
     }
 
     callback->adapter = adapterCB;
     callback->conn = connCB;
     LL_APPEND(g_networkChangeCallbackList, callback);
+    oc_mutex_unlock(g_mutexNetCallbackList);
     OIC_LOG_V(INFO, TAG, "Added NetworkStateChanged Callback [%p]", callback);
 
     return CA_STATUS_OK;
@@ -185,6 +195,7 @@ static CAResult_t RemoveNetworkStateChangedCallback(CAAdapterStateChangedCB adap
 {
     OIC_LOG(DEBUG, TAG, "Remove NetworkStateChanged Callback");
 
+    oc_mutex_lock(g_mutexNetCallbackList);
     CANetworkCallback_t* callback = NULL;
     LL_FOREACH(g_networkChangeCallbackList, callback)
     {
@@ -192,10 +203,13 @@ static CAResult_t RemoveNetworkStateChangedCallback(CAAdapterStateChangedCB adap
         {
             OIC_LOG(DEBUG, TAG, "remove specific callback");
             LL_DELETE(g_networkChangeCallbackList, callback);
+            oc_mutex_unlock(g_mutexNetCallbackList);
             OICFree(callback);
             return CA_STATUS_OK;
         }
     }
+    oc_mutex_unlock(g_mutexNetCallbackList);
+
     return CA_STATUS_OK;
 }
 
@@ -222,6 +236,8 @@ static CAResult_t CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
 
 static void CAAdapterChangedCallback(CATransportAdapter_t adapter, CANetworkStatus_t status)
 {
+
+    oc_mutex_lock(g_mutexNetCallbackList);
     // Call the callback.
     CANetworkCallback_t* callback  = NULL;
     LL_FOREACH(g_networkChangeCallbackList, callback)
@@ -240,12 +256,14 @@ static void CAAdapterChangedCallback(CATransportAdapter_t adapter, CANetworkStat
             OIC_LOG_V(INFO, TAG, "OUT application adapter changed callback [%p]", callback);
         }
     }
+    oc_mutex_unlock(g_mutexNetCallbackList);
     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)
 {
+    oc_mutex_lock(g_mutexNetCallbackList);
     // Call the callback.
     CANetworkCallback_t* callback = NULL;
     LL_FOREACH(g_networkChangeCallbackList, callback)
@@ -255,6 +273,7 @@ static void CAConnectionChangedCallback(const CAEndpoint_t *info, bool isConnect
             callback->conn(info, isConnected);
         }
     }
+    oc_mutex_unlock(g_mutexNetCallbackList);
     OIC_LOG_V(DEBUG, TAG, "[%s] connection status is changed to [%d]", info->addr, isConnected);
 }
 #endif
@@ -272,10 +291,38 @@ static void CAAdapterErrorHandleCallback(const CAEndpoint_t *endpoint,
     }
 }
 
+static void CADestroyMutex()
+{
+    if (g_mutexNetCallbackList)
+    {
+        oc_mutex_free(g_mutexNetCallbackList);
+        g_mutexNetCallbackList = NULL;
+    }
+}
+
+static CAResult_t CACreateMutex()
+{
+    if (!g_mutexNetCallbackList)
+    {
+        g_mutexNetCallbackList = oc_mutex_new();
+        if (!g_mutexNetCallbackList)
+        {
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    return CA_STATUS_OK;
+}
+
 void CAInitializeAdapters(ca_thread_pool_t handle, CATransportAdapter_t transportType)
 {
     OIC_LOG_V(DEBUG, TAG, "initialize adapters %d", transportType);
 
+    if (CA_STATUS_OK != CACreateMutex())
+    {
+        OIC_LOG(ERROR, TAG, "Failed to create mutex!");
+    }
+
     // Initialize ssl adapter.
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
     if (CA_STATUS_OK != CAinitSslAdapter())
@@ -780,6 +827,8 @@ CAResult_t CAStartDiscoveryServerAdapters()
 
 void CATerminateAdapters()
 {
+    CADestroyMutex();
+
     for (uint32_t index = 0; index < g_numberOfAdapters; index++)
     {
         if (g_adapterHandler[index].terminate != NULL)