[Tizen]Fix for LE Server termination issue
authorvimala.v <vimala.v@samsung.com>
Wed, 11 May 2016 07:07:17 +0000 (12:37 +0530)
committerJon A. Cruz <jon@joncruz.org>
Fri, 27 May 2016 05:06:43 +0000 (05:06 +0000)
On terminating, LE server doesn't call Disconnect to all the clients
connected.  This patch resolves the issue by maintaining client list
at the server and on terminating, the server disconnects with all
the clients it is connected with.

Change-Id: I0e177dbb3a2803e1d21ccc5a9d0298faa77f5740
Signed-off-by: vimala.v <vimala.v@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/8105
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jon@joncruz.org>
resource/csdk/connectivity/inc/caleinterface.h
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.h
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleutil.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleutil.h

index 084c536..6e78bc9 100644 (file)
@@ -443,6 +443,25 @@ void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback);
  *                     adapter.
  */
 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback);
+
+/**
+ * This is the callback which will be called whenever there is change in gatt connection
+ * with Client(Connected/Disconnected).
+ *
+ * @param[in]  connected      State of connection.
+ * @param[in]  remoteAddress  Mac address of the remote device in which we made connection.
+ */
+void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddress);
+
+/**
+ * This is the callback which will be called whenever there is change in gatt connection
+ * with server(Connected/Disconnected)
+ *
+ * @param[in]  connected     State of connection
+ * @param[in]  remoteAddress Mac address of the remote device in which we made connection.
+ */
+void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress);
+
 #ifdef __cplusplus
 }
 #endif
index d158914..67a44ea 100644 (file)
@@ -247,6 +247,9 @@ void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress)
     if (!connected)
     {
         OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress);
+        ca_mutex_lock(g_LEServerListMutex);
+        CARemoveLEServerInfoFromList(&g_LEServerList, remoteAddress);
+        ca_mutex_unlock(g_LEServerListMutex);
     }
     else
     {
@@ -984,7 +987,7 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress)
     CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo);
     if (CA_STATUS_OK != result)
     {
-        OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed");
+        OIC_LOG(ERROR, TAG, "CAAddLEServerInfoToList failed");
         bt_gatt_client_destroy(clientHandle);
         CALEGattDisConnect(remoteAddress);
         return CA_STATUS_FAILED;
index afa6171..c55e025 100644 (file)
@@ -66,15 +66,6 @@ void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic,
 void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData);
 
 /**
- * This is the callback which will be called whenever there is change in gatt connection
- * with server(Connected/Disconnected)
- *
- * @param[in]  connected     State of connection
- * @param[in]  remoteAddress Mac address of the remote device in which we made connection.
- */
-void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress);
-
-/**
  * This is the callback which will be called when LE advertisement is found.
  *
  * @param[in]  result         The result of Scanning
index 16c0956..af2aa63 100644 (file)
@@ -24,6 +24,7 @@
 #include "camutex.h"
 #include "caqueueingthread.h"
 #include "cagattservice.h"
+#include "oic_string.h"
 #include "oic_malloc.h"
 #include "caleutil.h"
 
@@ -114,6 +115,16 @@ static ca_thread_pool_t g_leServerThreadPool = NULL;
  */
 static GMainLoop *g_eventLoop = NULL;
 
+/**
+ * This contains the list of OIC clients connected to the server.
+ */
+static LEClientInfoList *g_LEClientList = NULL;
+
+/**
+ * Mutex to synchronize access to LE ClientList.
+ */
+static ca_mutex g_LEClientListMutex = NULL;
+
 void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddress)
 {
     VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address");
@@ -121,10 +132,24 @@ void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddr
     if (connected)
     {
         OIC_LOG_V(DEBUG, TAG, "Connected to [%s]", remoteAddress);
+        char *addr = OICStrdup(remoteAddress);
+        ca_mutex_lock(g_LEClientListMutex);
+        CAResult_t result  = CAAddLEClientInfoToList(&g_LEClientList, addr);
+        if (CA_STATUS_OK != result)
+        {
+            OIC_LOG(ERROR, TAG, "CAAddLEClientInfoToList failed");
+            ca_mutex_unlock(g_LEClientListMutex);
+            OICFree(addr);
+            return;
+        }
+        ca_mutex_unlock(g_LEClientListMutex);
     }
     else
     {
         OIC_LOG_V(DEBUG, TAG, "Disconnected from [%s]", remoteAddress);
+        ca_mutex_lock(g_LEClientListMutex);
+        CARemoveLEClientInfoFromList(&g_LEClientList, remoteAddress);
+        ca_mutex_unlock(g_LEClientListMutex);
     }
 }
 
@@ -318,6 +343,11 @@ CAResult_t CAStopLEGattServer()
 
     g_isLEGattServerStarted = false;
 
+    ca_mutex_lock(g_LEClientListMutex);
+    CADisconnectAllClient(g_LEClientList);
+    g_LEClientList = NULL;
+    ca_mutex_unlock(g_LEClientListMutex);
+
     CAResult_t res = CALEStopAdvertise();
     {
         OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res);
@@ -446,6 +476,16 @@ CAResult_t CAInitGattServerMutexVariables()
         }
     }
 
+    if (NULL == g_LEClientListMutex)
+    {
+        g_LEClientListMutex = ca_mutex_new();
+        if (NULL == g_LEClientListMutex)
+        {
+            OIC_LOG(ERROR, TAG, "ca_mutex_new failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
     OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
@@ -465,6 +505,12 @@ void CATerminateGattServerMutexVariables()
     ca_mutex_free(g_leReqRespCbMutex);
     g_leReqRespCbMutex = NULL;
 
+    ca_mutex_free(g_leServerThreadPoolMutex);
+    g_leServerThreadPoolMutex = NULL;
+
+    ca_mutex_free(g_LEClientListMutex);
+    g_LEClientListMutex = NULL;
+
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
index f3c73d6..400f81f 100644 (file)
@@ -150,15 +150,6 @@ void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h s
                                          int charValueLen, void *userData);
 
 /**
- * This is the callback which will be called whenever there is change in gatt connection
- * with Client(Connected/Disconnected).
- *
- * @param[in]  connected      State of connection.
- * @param[in]  remoteAddress  Mac address of the remote device in which we made connection.
- */
-void CALEGattServerConnectionStateChanged(bool connected, const char *remoteAddress);
-
-/**
  * Setting the connection state changed callback.
  * @param[in] connStateCb      callback for receiving the changed network info.
  */
index 07600f0..ae02a49 100644 (file)
@@ -69,8 +69,8 @@ CAResult_t CAAddLEServerInfoToList(LEServerInfoList **serverList,
 
     OIC_LOG(DEBUG, TAG, "IN");
 
-    VERIFY_NON_NULL(serverList, TAG, "clientList");
-    VERIFY_NON_NULL(leServerInfo, TAG, "leClientInfo");
+    VERIFY_NON_NULL(serverList, TAG, "serverList");
+    VERIFY_NON_NULL(leServerInfo, TAG, "leServerInfo");
 
     LEServerInfoList *node = (LEServerInfoList *) OICCalloc(1, sizeof(LEServerInfoList));
     if (NULL == node)
@@ -102,6 +102,42 @@ CAResult_t CAAddLEServerInfoToList(LEServerInfoList **serverList,
     return CA_STATUS_OK;
 }
 
+void CARemoveLEServerInfoFromList(LEServerInfoList **serverList,
+                                        const char *remoteAddress)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL_VOID(serverList, TAG, "serverList");
+    VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remoteAddress");
+
+    LEServerInfoList *temp = *serverList;
+    LEServerInfoList *prev = NULL;
+    while (temp)
+    {
+        if (!strcasecmp(temp->serverInfo->remoteAddress, remoteAddress))
+        {
+            if (NULL == prev)
+            {
+                *serverList = temp->next;
+            }
+            else
+            {
+                prev->next = temp->next;
+            }
+            CADecrementRegisteredServiceCount();
+            bt_gatt_client_destroy(temp->serverInfo->clientHandle);
+            OICFree(temp->serverInfo->remoteAddress);
+            OICFree(temp->serverInfo);
+            OICFree(temp);
+            OIC_LOG_V(DEBUG, TAG, "Device [%s] removed from list", remoteAddress);
+            break;
+        }
+        prev = temp;
+        temp = temp->next;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
 CAResult_t CAGetLEServerInfo(LEServerInfoList *serverList, const char *leAddress,
                              LEServerInfo **leServerInfo)
 {
@@ -162,13 +198,13 @@ CAResult_t CAGetLEServerInfoByPosition(LEServerInfoList *serverList, int32_t pos
     return CA_STATUS_FAILED;
 }
 
-void CAFreeLEServerList(LEServerInfoList *clientList)
+void CAFreeLEServerList(LEServerInfoList *serverList)
 {
     OIC_LOG(DEBUG, TAG, "IN");
-    while (clientList)
+    while (serverList)
     {
-        LEServerInfoList *temp = clientList;
-        clientList = clientList->next;
+        LEServerInfoList *temp = serverList;
+        serverList = serverList->next;
         CAFreeLEServerInfo(temp->serverInfo);
         OICFree(temp);
     }
@@ -199,6 +235,95 @@ void CAFreeLEServerInfo(LEServerInfo *leServerInfo)
     OIC_LOG(DEBUG, TAG, "OUT");
 }
 
+CAResult_t CAAddLEClientInfoToList(LEClientInfoList **clientList,
+                                   char *clientAddress)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL(clientList, TAG, "clientList");
+    VERIFY_NON_NULL(clientAddress, TAG, "clientAddress");
+
+    LEClientInfoList *node = (LEClientInfoList *) OICCalloc(1, sizeof(LEClientInfoList));
+    if (NULL == node)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed!");
+        return CA_STATUS_FAILED;
+    }
+
+    node->remoteAddress= clientAddress;
+    node->next = NULL;
+
+    if (*clientList == NULL)   // Empty list
+    {
+        *clientList = node;
+    }
+    else     // Add at front end
+    {
+        node->next = *clientList;
+        *clientList = node;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Device [%s] added to list", clientAddress);
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+void CARemoveLEClientInfoFromList(LEClientInfoList **clientList,
+                                  const char *clientAddress)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL_VOID(clientAddress, TAG, "clientAddress");
+
+    LEClientInfoList *temp = *clientList;
+    LEClientInfoList *prev = NULL;
+    while (temp)
+    {
+        if (!strcasecmp(temp->remoteAddress, clientAddress))
+        {
+            if (NULL == prev)
+            {
+                *clientList = temp->next;
+            }
+            else
+            {
+                prev->next = temp->next;
+            }
+            OICFree(temp->remoteAddress);
+            OICFree(temp);
+            OIC_LOG_V(DEBUG, TAG, "Device [%s] removed from list", clientAddress);
+            break;
+        }
+        prev = temp;
+        temp = temp->next;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CADisconnectAllClient(LEClientInfoList *clientList)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    while (clientList)
+    {
+        LEClientInfoList *temp = clientList;
+        clientList = clientList->next;
+        if (temp->remoteAddress)
+        {
+            int32_t ret = bt_gatt_disconnect(temp->remoteAddress);
+
+            if (BT_ERROR_NONE != ret)
+            {
+                OIC_LOG_V(ERROR, TAG,
+                          "bt_gatt_disconnect Failed with ret value [%d]",
+                          ret);
+                return;
+            }
+            OICFree(temp->remoteAddress);
+        }
+        OICFree(temp);
+    }
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
 const char *CALEGetErrorMsg(bt_error_e err)
 {
     const char *errStr = NULL;
index 5a38ec4..ed51602 100644 (file)
@@ -51,6 +51,12 @@ typedef struct _LEServerInfoList
     struct _LEServerInfoList *next;
 }LEServerInfoList;
 
+typedef struct _LEClientInfoList
+{
+    char *remoteAddress;
+    struct _LEClientInfoList *next;
+} LEClientInfoList;
+
 /**
  * Different characteristics types.
  *
@@ -86,7 +92,7 @@ void CAResetRegisteredServiceCount();
 int32_t  CAGetRegisteredServiceCount();
 
 /**
- * @brief  Used to add the serverListInfo structure to the Client List.
+ * Used to add the serverListInfo structure to the Server List.
  *
  * @param[in] serverList     Pointer to the ble server list which holds the info of list of
  *                           servers registered by the client.
@@ -101,6 +107,16 @@ CAResult_t CAAddLEServerInfoToList(LEServerInfoList **serverList,
                                    LEServerInfo *leServerInfo);
 
 /**
+ * Used to remove the serverListInfo structure from the Server List.
+ *
+ * @param[in,out] serverList     Pointer to the ble server list which holds the info of list of
+ *                               servers registered by the client.
+ * @param[in]     remoteAddress  Remote address to be removed from the client list.
+ */
+void CARemoveLEServerInfoFromList(LEServerInfoList **serverList,
+                                        const char *remoteAddress);
+
+/**
  * Used to get the serviceInfo from the list.
  *
  * @param[in]  serverList       Pointer to the ble service list which holds the info of list
@@ -147,6 +163,38 @@ void CAFreeLEServerList(LEServerInfoList *serverList);
 void CAFreeLEServerInfo(LEServerInfo *bleServerInfo);
 
 /**
+ * Used to add the client address to the Client List.
+ *
+ * @param[in] clientList     Pointer to the ble client list which holds the info of list of
+ *                           clients connected to the server.
+ * @param[in] clientAddress  Client remote address.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK  Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM  Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAAddLEClientInfoToList(LEClientInfoList **clientList,
+                                   char *clientAddress);
+
+/**
+ * Used to remove the client address from the Client List.
+ *
+ * @param[in,out] clientList     Pointer to the ble client list which holds the info of list of
+ *                               clients connected by the server.
+ * @param[in]     clientAddress  Remote address to be removed from the client list.
+ */
+void CARemoveLEClientInfoFromList(LEClientInfoList **clientList,
+                                        const char *clientAddress);
+
+/**
+ * Used to disconnect all the clients connected to the server.
+ *
+ * @param[in,out] clientList     Pointer to the ble client list which holds the info of list of
+ *                               clients connected by the server.
+ */
+void CADisconnectAllClient(LEClientInfoList *clientList);
+
+/**
  * Used to get the Error message.
  * @param[in] err   Error code(::bt_error_e).
  * @return  Error string corresponding to the BT error code.