[IOT-1540] Connection manager logic add. 09/15909/16
authorjg.ham <jg.ham@samsung.com>
Mon, 13 Feb 2017 00:48:03 +0000 (09:48 +0900)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Mon, 13 Feb 2017 15:10:22 +0000 (15:10 +0000)
Add the function to switch cloud IP to local IP
in connection manager.

Change-Id: I032d2ae38e63ad79694ebc92b900f6621d0130c3
Signed-off-by: Jonggyu Ham <jg.ham@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15909
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
25 files changed:
java/iotivity-android/src/main/java/org/iotivity/ca/CaInterface.java
java/iotivity-android/src/main/java/org/iotivity/ca/CaIpConnectionPreference.java [new file with mode: 0644]
java/jni/JniCaInterface.c
java/jni/JniCaInterface.h
resource/c_common/ocrandom/include/ocrandom.h
resource/c_common/ocrandom/src/ocrandom.c
resource/csdk/connectivity/api/cautilinterface.h
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/util/SConscript
resource/csdk/connectivity/util/inc/caconnectionmanager.h
resource/csdk/connectivity/util/src/camanager/caconnectionmanager.c
resource/csdk/connectivity/util/src/camanager/camanagerutil.c
resource/csdk/connectivity/util/src/camanager/camanagerutil.h
resource/csdk/connectivity/util/src/camanager/camessagearbiter.c
resource/csdk/connectivity/util/src/camanager/camessagearbiter.h
resource/csdk/connectivity/util/src/camanager/capolicymanager.c
resource/csdk/connectivity/util/src/camanager/capolicymanager.h
resource/csdk/connectivity/util/src/cautilinterface.c
resource/csdk/include/octypes.h
resource/csdk/stack/SConscript
resource/csdk/stack/include/internal/occonnectionmanager.h [new file with mode: 0755]
resource/csdk/stack/src/occonnectionmanager.c [new file with mode: 0755]
resource/csdk/stack/src/ocstack.c
resource/include/CAManager.h
resource/src/CAManager.cpp

index 5a88476..5cad309 100644 (file)
@@ -268,4 +268,13 @@ public class CaInterface {
     }
     private static native int setCipherSuiteImpl(int cipher, int adapter);
 
+    /**
+     * Set Connection Manager configuration.
+     * It can be set a connection manager configuration.(default: CA_CLOUD)
+     */
+    public synchronized static void setConnectionUserConfig(CaIpConnectionPreference connPriority) {
+        CaInterface.caManagerSetConnectionUserConfig(connPriority.getValue());
+    }
+
+    private static native void caManagerSetConnectionUserConfig(int connPriority);
 }
diff --git a/java/iotivity-android/src/main/java/org/iotivity/ca/CaIpConnectionPreference.java b/java/iotivity-android/src/main/java/org/iotivity/ca/CaIpConnectionPreference.java
new file mode 100644 (file)
index 0000000..04edcef
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ ********************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+package org.iotivity.ca;
+
+import java.security.InvalidParameterException;
+import java.util.EnumSet;
+
+public enum CaIpConnectionPreference {
+
+    /** Cloud TCP (default) */
+    CA_CLOUD (0),
+    /** local UDP */
+    CA_LOCAL_UDP (1),
+    /** local TCP */
+    CA_LOCAL_TCP (2),
+    ;
+
+    private int value;
+
+    private CaIpConnectionPreference(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return this.value;
+    }
+}
index a2ce4a0..9e380f0 100644 (file)
@@ -453,3 +453,22 @@ JNIEXPORT jint JNICALL Java_org_iotivity_ca_CaInterface_setCipherSuiteImpl
     return ret;
 }
 
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaInterface_caManagerSetConnectionUserConfig(JNIEnv *env, jclass clazz,
+                                                                  jint connPriority)
+{
+    (void)env;
+    (void)clazz;
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+    LOGI("CaManager_SetConnecitonUserConfig connPriority: %d", connPriority);
+    CAResult_t ret = CAUtilCMSetConnectionUserConfig(connPriority);
+    if (CA_STATUS_OK != ret)
+    {
+        LOGE("CASetIpConnSwitchConfig has failed");
+    }
+#else
+    LOGI("[CaManager_SetConnecitonUserConfig] stack doesn't support TCP and CLOUD");
+    (void)connPriority;
+#endif
+}
+
index 6edd7f2..904f442 100644 (file)
@@ -166,6 +166,14 @@ extern "C" {
     JNIEXPORT jint JNICALL Java_org_iotivity_ca_CaInterface_setCipherSuiteImpl
      (JNIEnv *, jclass, jint, jint);
 
+    /*
+     * Class:       org_iotivity_ca_CaInterface
+     * Method:      caManagerSetConnectionUserConfig
+     * Signature:   (I)V
+     */
+    JNIEXPORT void JNICALL
+    Java_org_iotivity_ca_CaInterface_caManagerSetConnectionUserConfig
+    (JNIEnv *, jclass, jint);
 #ifdef __cplusplus
 }
 #endif
index e2d2eb5..a78590e 100644 (file)
@@ -40,7 +40,7 @@ extern "C" {
 
 /*
  * Size of a UUID string.
- * IoTivity formats UUIDs as strings following RFC 4122, Section 3. 
+ * IoTivity formats UUIDs as strings following RFC 4122, Section 3.
  * For example, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6".
  * This requires 36 characters, plus one for the null terminator.
  */
@@ -109,6 +109,18 @@ bool OCConvertUuidToString(const uint8_t uuid[UUID_SIZE],
 bool OCConvertStringToUuid(const char uuidString[UUID_STRING_SIZE],
                                          uint8_t uuid[UUID_SIZE]);
 
+/**
+ * Check if the provided uuid is valid.
+ * 1. The length of uuids should always be 36.
+ * 2. Hyphens are expected at positions {9, 14, 19, 24}.
+ * 3. The rest charcters should be simple xdigits.
+ *
+ * @param[i] uuid
+ *              uuid extracted from uri
+ * @retval true for success, otherwise false and an error is logged
+ */
+bool OCIsUUID(const char *uuid);
+
 #ifdef __cplusplus
 }
 #endif
index 3290de6..2038520 100644 (file)
 
 #define OC_MIN(A,B) ((A)<(B)?(A):(B))
 
+#define OC_UUID_HYPHEN_1 9
+#define OC_UUID_HYPHEN_2 14
+#define OC_UUID_HYPHEN_3 19
+#define OC_UUID_HYPHEN_4 24
+#define OC_UUID_HYPHEN_COUNT 4
+
 /**
 * @def OCRANDOM_TAG
 * @brief Logging tag for module name
@@ -71,7 +77,7 @@
 #include "Arduino.h"
 
 /*
- * ARM GCC compiler doesnt define random/srandom functions, fallback to 
+ * ARM GCC compiler doesnt define random/srandom functions, fallback to
  * rand/srand.
  */
 #if !defined(ARDUINO_ARCH_SAM)
@@ -123,9 +129,9 @@ uint8_t GetRandomBit()
     }
 }
 
-/* 
- * Currently, only the Arduino platform requires seeding. It's done 
- * automatically on the first call to OCGetRandomBytes. 
+/*
+ * Currently, only the Arduino platform requires seeding. It's done
+ * automatically on the first call to OCGetRandomBytes.
  */
 uint8_t g_isSeeded = 0;
 static void OCSeedRandom()
@@ -134,7 +140,7 @@ static void OCSeedRandom()
     {
         return;
     }
-    
+
     uint32_t result =0;
     uint8_t i;
     for (i=32; i--;)
@@ -256,24 +262,24 @@ uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound)
     uint32_t rangeBase = OC_MIN(firstBound, secondBound);
     uint32_t rangeWidth = (firstBound > secondBound) ? (firstBound - secondBound) : (secondBound - firstBound);
 
-    /* 
-     * Compute a random number between 0 and rangeWidth. Avoid using floating 
+    /*
+     * Compute a random number between 0 and rangeWidth. Avoid using floating
      * point types to avoid overflow when rangeWidth is large. The condition
-     * in the while loop will be false with probability at least 1/2. 
+     * in the while loop will be false with probability at least 1/2.
      */
     uint32_t rangeMask = 0xFFFFFFFF >> nlz(rangeWidth);
     uint32_t offset = 0;
-    do 
+    do
     {
         if(!OCGetRandomBytes((uint8_t*)&offset, sizeof(offset)))
         {
             OIC_LOG(FATAL, OCRANDOM_TAG, "OCGetRandomBytes failed");
             assert(false);
-            return rangeBase; 
+            return rangeBase;
         }
         offset = offset & rangeMask;
-    } 
-    while (offset > rangeWidth);    
+    }
+    while (offset > rangeWidth);
 
     return rangeBase + offset;
 }
@@ -353,3 +359,46 @@ bool OCConvertStringToUuid(const char uuidString[UUID_STRING_SIZE],
     return true;
 }
 
+bool OCIsUUID(const char *uuid)
+{
+    size_t hyphens[OC_UUID_HYPHEN_COUNT] = {OC_UUID_HYPHEN_1, OC_UUID_HYPHEN_2,
+                                            OC_UUID_HYPHEN_3, OC_UUID_HYPHEN_4};
+    if (strlen(uuid) != UUID_STRING_SIZE -1)
+    {
+        //The length doesn't match
+        return false;
+    }
+
+    for (size_t i = 0, counter = 0; i < (UUID_STRING_SIZE - 1); i++)
+    {
+        char var = uuid[i];
+
+        //Check if a hyphen is expected here.
+        if (i = hyphens[counter] -1)
+        {
+            //We need a hyphen here.
+            if('-' != var)
+            {
+                //The character is not a hyphen.
+                return false;
+            }
+            else
+            {
+                //Move on to the next expected hyphen position.
+                counter++;
+            }
+        }
+        else
+        {
+            //The character here should be a simple xdigit
+            if (0 == isxdigit(var))
+            {
+                //The current character is not a xdigit.
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
index 4b90ff8..5792160 100644 (file)
@@ -31,26 +31,17 @@ extern "C"
 #endif
 
 /**
- * this level depends on transmission time.
- * unicast based UDP will be checked by caretransmission.
+ * User Preference of connectivity channel for connection manager
  */
 typedef enum
 {
-    HIGH_SPEED = 0,
-    NORMAL_SPEED
-} CMSpeedLevel_t;
-
-typedef struct
-{
-    /** address for all **/
-    char addr[MAX_ADDR_STR_SIZE_CA];
-
-    /** adapter priority of all transmissions. **/
-    CATransportAdapter_t adapter;
-
-    /** level about speed of response. **/
-    CMSpeedLevel_t level;
-} CMConfigureInfo_t;
+    /** Cloud TCP (Default) */
+    CA_USER_PREF_CLOUD = 0,
+    /** local UDP */
+    CA_USER_PREF_LOCAL_UDP = 1,
+    /** local TCP */
+    CA_USER_PREF_LOCAL_TCP = 2
+} CAConnectUserPref_t;
 
 /*
  * CAUtilConfig_t structure.
@@ -58,7 +49,7 @@ typedef struct
 typedef struct
 {
     CATransportBTFlags_t bleFlags;
-    CMConfigureInfo_t cmInfo;
+    CAConnectUserPref_t connUserPref;
 } CAUtilConfig_t;
 
 /**
@@ -133,6 +124,48 @@ CAResult_t CASetPortNumberToAssign(CATransportAdapter_t adapter,
  */
 uint16_t CAGetAssignedPortNumber(CATransportAdapter_t adapter, CATransportFlags_t flag);
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+/**
+ * Initializes the Connection Manager
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAUtilCMInitailize();
+
+/**
+ * Terminate the Connection Manager
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAUtilCMTerminate();
+
+/**
+ * Update RemoteDevice Information for Connection Manager
+ * @param[in]  endpoint   Remote device information with specific device ID.
+ * @param[in]  isCloud    with cloud or not.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAUtilCMUpdateRemoteDeviceInfo(const CAEndpoint_t endpoint, bool isCloud);
+
+/**
+ * Reset RemoteDevice Info. for Connection Manager
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAUtilCMResetRemoteDeviceInfo();
+
+/**
+ * Set Connection Manager configuration
+ * @param[in]  connPrefer  enum type of CAConnectUserPref_t.(default:CA_USER_PREF_CLOUD)
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAUtilCMSetConnectionUserConfig(CAConnectUserPref_t connPrefer);
+
+/**
+ * Get Connection Manager configuration
+ * @param[out]  connPrefer  enum type of CAConnectUserPref_t.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAUtilCMGetConnectionUserConfig(CAConnectUserPref_t *connPrefer);
+#endif //TCP_ADAPTER & WITH_CLOUD
+
 #ifdef __JAVA__
 #ifdef __ANDROID__
 /**
index 04dc46e..f7e4b16 100644 (file)
@@ -48,6 +48,9 @@
 #include "cathreadpool.h" /* for thread pool */
 #include "caqueueingthread.h"
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+#include "caconnectionmanager.h"
+#endif
 #define SINGLE_HANDLE
 #define MAX_THREAD_POOL_SIZE    20
 
@@ -1003,6 +1006,14 @@ CAResult_t CADetachSendMessage(const CAEndpoint_t *endpoint, const void *sendMsg
 
     OIC_LOG_V(DEBUG, TAG, "device ID of endpoint of this message is %s", endpoint->remoteId);
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+    CAResult_t ret = CACMGetMessageData(data);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(DEBUG, TAG, "Ignore ConnectionManager");
+    }
+#endif
+
 #ifdef SINGLE_THREAD
     CAResult_t result = CAProcessSendData(data);
     if (CA_STATUS_OK != result)
index 9fdaa31..975c7b1 100644 (file)
@@ -11,6 +11,8 @@ ca_os = env.get('TARGET_OS')
 ca_transport = env.get('TARGET_TRANSPORT')
 target_os = env.get('TARGET_OS')
 project_root = env.get('SRC_DIR')
+with_cloud = env.get('WITH_CLOUD')
+with_tcp = env.get('WITH_TCP')
 root_dir = os.path.join(project_root, 'resource', 'csdk', 'connectivity')
 src_dir = os.path.join(root_dir, 'util', 'src')
 
@@ -32,7 +34,9 @@ if target_os == 'android':
                        env.AppendUnique(CA_SRC = [
                        os.path.join(src_dir, 'btpairing' ,'android', 'cabtpairing.c')])
 
-env.AppendUnique(CA_SRC = [
+if (with_cloud == True) and (with_tcp == True):
+    env.AppendUnique(CPPDEFINES = ['WITH_CLOUD'])
+    env.AppendUnique(CA_SRC = [
                os.path.join(src_dir, 'camanager', 'caconnectionmanager.c'),
                os.path.join(src_dir, 'camanager', 'camanagerutil.c'),
                os.path.join(src_dir, 'camanager', 'camessagearbiter.c'),
index eba0b1f..16ef031 100644 (file)
@@ -31,6 +31,7 @@
 #include <coap/coap.h>
 #include "cathreadpool.h"
 #include "octhread.h"
+#include "logger.h"
 #include "uarraylist.h"
 #include "cacommon.h"
 #include "caprotocolmessage.h"
@@ -43,72 +44,58 @@ extern "C"
 #endif
 
 /**
- * Callback to send replaced data.
- * @param[in]   data    send data.
- */
-typedef void (*CASendThreadFunc)(CAData_t *data);
-
-/**
- * Callback to notify received data from the remote endpoint.
- * @param[in]   data    received data.
+ * Initializes the connection manager context.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-typedef void (*CAReceiveThreadFunc)(CAData_t *data);
+CAResult_t CACMInitialize();
 
 /**
- * Context of connection manager
+ * Terminate the connection manager context.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-typedef struct
-{
-    /** send method for block data. **/
-    CASendThreadFunc sendThreadFunc;
-
-    /** callback function for received message. **/
-    CAReceiveThreadFunc receivedThreadFunc;
-
-    /** array list on which the thread is operating. **/
-    u_arraylist_t *dataList;
-
-    /** data list mutex for synchronization. **/
-    oc_mutex dataListMutex;
-
-    /** sender mutex for synchronization. **/
-    oc_mutex dataSenderMutex;
-} CAConnectionManagerContext_t;
+CAResult_t CACMTerminate();
 
 /**
- * Initializes the connection manager context.
- * @param[in]  CASendThreadFunc    function point to add data in send queue thread.
- * @param[in]  CAReceiveThreadFunc function point to add data in receive queue thread.
- * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ * Get request/response message to send.
+ * @param[in,out]  data     data to request or response.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-CAResult_t CAInitializeConnectionManager(CASendThreadFunc blockSendMethod,
-                                         CAReceiveThreadFunc receivedDataCallback);
+CAResult_t CACMGetMessageData(CAData_t *data);
 
 /**
- * Terminate the connection manager context.
+ * Set CM User Configuration
+ * @param[in]  connPriority     value of CAConnectUserPref_t
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-void CATerminateConnectionManager();
+CAResult_t CACMSetConnUserConfig(CAConnectUserPref_t connPrefer);
 
 /**
- * Initialize mutex.
- * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ * Get CM User Configuration
+ * @param[out]  connPriority     value of CAConnectUserPref_t
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-CAResult_t CAInitConnectionManagerMutexVariables();
+CAResult_t CACMGetConnUserConfig(CAConnectUserPref_t *connPrefer);
 
 /**
- * Terminate mutex.
+ * Update Remote Device Info.
+ * @param[in]  endpoint       network address.
+ * @param[in]  isCloud        with cloud or not .
+ * @return ::CA_STATUS_OK or Appropriate error code.
  */
-void CATerminateConnectionManagerMutexVariables();
+CAResult_t CACMUpdateRemoteDeviceInfo(const CAEndpoint_t endpoint, bool isCloud);
 
 /**
- * Get request/response message to send.
+ * Reset Remote Device Info.
+ * @return ::CA_STATUS_OK or Appropriate error code.
  */
-CAData_t* CAGetConnectionManagerMessageData(CAData_t *data);
+CAResult_t CACMResetRemoteDeviceInfo();
 
 /**
- * Start connection manager.
+ * Set callback to handle connection status
+ * @param[in]  callback       Callback function type for adapter status changes delivery.
+ * @return ::CA_STATUS_OK or Appropriate error code.
  */
-void CAStartConnectionManagerService(CMConfigureInfo_t info);
+CAResult_t CACMSetIPConnectionCallback(CAAdapterStateChangedCB callback);
 
 #ifdef __cplusplus
 } /* extern "C" */
index d426ac3..12e54f3 100644 (file)
 #include "caadapterutils.h"
 
 #include "caconnectionmanager.h"
+#include "camessagearbiter.h"
 #include "capolicymanager.h"
+#include "camanagerutil.h"
 
 #define TAG "OIC_CM"
 
-static oc_mutex g_threadCMConfigureMutex = NULL;
 
-// context for connection manager
-static CAConnectionManagerContext_t g_context = {.sendThreadFunc = NULL,
-                                                 .receivedThreadFunc = NULL,
-                                                 .dataList = NULL};
-
-void CAStartConnectionManagerService(CMConfigureInfo_t info)
+CAResult_t CACMInitialize()
 {
-    OIC_LOG(DEBUG, TAG, "CAStartConnectionManagerService");
-
-    oc_mutex_lock(g_threadCMConfigureMutex);
-    CMSetConfigure(info);
-    oc_mutex_unlock(g_threadCMConfigureMutex);
+    OIC_LOG(DEBUG, TAG, "CACMInitialize");
+    return CAMsgArbiterInitialize();
 }
 
-CAData_t* CAGetConnectionManagerMessageData(CAData_t *data)
+CAResult_t CACMTerminate()
 {
-    OIC_LOG(DEBUG, TAG, "CAGetConnectionManagerMessageData");
+    OIC_LOG(DEBUG, TAG, "CACMTerminate");
 
-    VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
+    return CAMsgArbiterTerminate();
+}
 
-    // TODO
-    // decide specific reqeust/response message
+CAResult_t CACMSetConnUserConfig(CAConnectUserPref_t connPrefer)
+{
+    OIC_LOG(DEBUG, TAG, "CACMSetConnUserConfig");
 
-    return data;
+    return CAPolicyMgrSetConfiguration(connPrefer);
 }
 
-CAResult_t CAInitializeConnectionManager(CASendThreadFunc sendThreadFunc,
-                                         CAReceiveThreadFunc receivedThreadFunc)
+CAResult_t CACMGetConnUserConfig(CAConnectUserPref_t *connPrefer)
 {
-    OIC_LOG(DEBUG, TAG, "CAInitializeConnectionManager");
-
-    if (!g_context.sendThreadFunc)
-    {
-        g_context.sendThreadFunc = sendThreadFunc;
-    }
-
-    if (!g_context.receivedThreadFunc)
-    {
-        g_context.receivedThreadFunc = receivedThreadFunc;
-    }
-
-    if (!g_context.dataList)
-    {
-        g_context.dataList = u_arraylist_create();
-    }
-
-    CAResult_t res = CAInitConnectionManagerMutexVariables();
-    if (CA_STATUS_OK != res)
-    {
-        u_arraylist_free(&g_context.dataList);
-        g_context.dataList = NULL;
-        OIC_LOG(ERROR, TAG, "init has failed");
-    }
-    return res;
+    OIC_LOG(DEBUG, TAG, "CACMGetConnUserConfig");
+    return CAPolicyMgrGetConfigure(connPrefer);
 }
 
-void CATerminateConnectionManager()
+CAResult_t CACMGetMessageData(CAData_t *data)
 {
-    OIC_LOG(DEBUG, TAG, "CATerminateConnectionManager");
-
-    if (g_context.dataList)
-    {
-        // TODO
-        // Remove all of management data();
-        u_arraylist_free(&g_context.dataList);
-    }
-    CATerminateConnectionManagerMutexVariables();
+    OIC_LOG(DEBUG, TAG, "CACMGetMessageData");
+
+    VERIFY_NON_NULL(data, TAG, "data is null");
+
+    return CAMsgArbiterGetMessageData(data);
 }
 
-CAResult_t CAInitConnectionManagerMutexVariables()
+CAResult_t CACMUpdateRemoteDeviceInfo(const CAEndpoint_t endpoint, bool isCloud)
 {
-    if (!g_context.dataListMutex)
-    {
-        g_context.dataListMutex = oc_mutex_new();
-        if (!g_context.dataListMutex)
-        {
-            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
-            return CA_STATUS_FAILED;
-        }
-    }
-
-    if (!g_context.dataSenderMutex)
-    {
-        g_context.dataSenderMutex = oc_mutex_new();
-        if (!g_context.dataSenderMutex)
-        {
-            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
-            CATerminateConnectionManagerMutexVariables();
-            return CA_STATUS_FAILED;
-        }
-    }
-
-    if (NULL == g_threadCMConfigureMutex)
-    {
-        g_threadCMConfigureMutex = oc_mutex_new();
-        if (NULL == g_threadCMConfigureMutex)
-        {
-            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
-            return CA_STATUS_FAILED;
-        }
-    }
-
-    return CA_STATUS_OK;
+    return CAMsgArbiterUpdateDeviceInfo(endpoint, isCloud);
 }
 
-void CATerminateConnectionManagerMutexVariables()
+CAResult_t CACMResetRemoteDeviceInfo()
 {
-    if (g_context.dataListMutex)
-    {
-        oc_mutex_free(g_context.dataListMutex);
-        g_context.dataListMutex = NULL;
-    }
-
-    if (g_context.dataSenderMutex)
-    {
-        oc_mutex_free(g_context.dataSenderMutex);
-        g_context.dataSenderMutex = NULL;
-    }
-
-    if (g_threadCMConfigureMutex)
-    {
-        oc_mutex_free(g_threadCMConfigureMutex);
-        g_threadCMConfigureMutex = NULL;
-    }
+    return CAMsgArbiterResetDeviceInfo();
 }
index 538d88a..b6844fd 100644 (file)
  *
  ******************************************************************/
 
-#include "logger.h"
-#include "cathreadpool.h"
-#include "uarraylist.h"
-#include "octhread.h"
-
 #include "camanagerutil.h"
 
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "caadapterutils.h"
+#include "logger.h"
+#include "ocrandom.h"
+#include "oic_string.h"
+#include "oic_malloc.h"
+
+/**
+ * Logging tag for module name
+ */
 #define TAG "OIC_CM_UTIL"
+
+/**
+ * This function is used to free DeviceInfo structure.
+ *
+ * @param[in] devInfo   Device info to be freed.
+ */
+static void CAMgrUtilDevInfoFree(CMDeviceInfo_t *devInfo);
+
+/**
+ * This function is used to print all components in list.
+ *
+ * @param[in]  devInfoList  Pointer to IP connection info table which contains
+ *                          D2D,D2S ip related informaions.
+ */
+static void CAMgrUtilDevInfoListPrint(CMDeviceInfoList_t *devInfoList);
+
+/**
+ * This function is used to make DeviceInfo structure.
+ *
+ * @param[in] endpoint   remote Endpoint to be added in IP connection info table.
+ *
+ * @return :: new alloced CMDeviceInfo_t pointer structure or NULL.
+ */
+static CMDeviceInfo_t* CAMgrUtilDevInfoCreate(const CAEndpoint_t endpoint);
+
+
+CAResult_t CAMgrUtilAddDevInfoToList(CMDeviceInfoList_t **devInfoList,
+                                     const CAEndpoint_t endpoint)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(devInfoList, TAG, "devInfoList");
+    VERIFY_NON_NULL(endpoint.remoteId, TAG, "deviceId");
+    VERIFY_NON_NULL(endpoint.addr, TAG, "address");
+
+    CMDeviceInfo_t *node = NULL;
+    CAResult_t ret = CAMgrUtilGetDevInfo(*devInfoList, endpoint.remoteId, &node);
+
+    if (CA_STATUS_OK == ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "deviceId[%s] is already added into list", endpoint.remoteId);
+        return CA_STATUS_FAILED;
+    }
+
+    CMDeviceInfo_t *newDevInfo = CAMgrUtilDevInfoCreate(endpoint);
+    if (NULL == newDevInfo)
+    {
+        OIC_LOG(ERROR, TAG, "CACMRemoteDeviceCreate failed!");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    CMDeviceInfoList_t *newNode = (CMDeviceInfoList_t *)OICCalloc(1, sizeof(CMDeviceInfoList_t));
+    if (NULL == newNode)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    newNode->deviceInfo = newDevInfo;
+    newNode->next = NULL;
+
+    if (*devInfoList != NULL)
+    {
+        newNode->next = *devInfoList;
+    }
+    *devInfoList = newNode;
+
+    OIC_LOG_V(DEBUG, TAG, "device id[%s] added to list", newDevInfo->deviceId);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAMgrUtilGetDevInfo(CMDeviceInfoList_t *devInfoList, const char *deviceId,
+                               CMDeviceInfo_t **devInfo)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(devInfoList, TAG, "devInfoList");
+    VERIFY_NON_NULL(deviceId, TAG, "deviceId");
+
+    CMDeviceInfoList_t *cur = devInfoList;
+    *devInfo = NULL;
+    while (cur != NULL)
+    {
+        if (NULL != cur->deviceInfo && !strcasecmp(cur->deviceInfo->deviceId, deviceId))
+        {
+            *devInfo = cur->deviceInfo;
+            OIC_LOG(DEBUG, TAG, "OUT - found Device info");
+            return CA_STATUS_OK;
+        }
+        cur = cur->next;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT - can't find Device info");
+    return CA_STATUS_FAILED;
+}
+
+CAResult_t CAMgrUtilUpdateDevInfo(CMDeviceInfoList_t *devInfoList, const CAEndpoint_t endpoint)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(devInfoList, TAG, "devInfoList");
+    VERIFY_NON_NULL(endpoint.remoteId, TAG, "deviceId");
+    VERIFY_NON_NULL(endpoint.addr, TAG, "localAddr");
+
+    CMDeviceInfo_t *node = NULL;
+    CAResult_t ret = CAMgrUtilGetDevInfo(devInfoList, endpoint.remoteId, &node);
+
+    if (CA_STATUS_OK != ret || NULL == node)
+    {
+        OIC_LOG_V(ERROR, TAG, "deviceId[%s] isn't included in list", endpoint.remoteId);
+        return ret;
+    }
+
+    node->d2dInfo.adapter |= endpoint.adapter;
+    node->d2dInfo.flags |= endpoint.flags;
+
+    if (NULL != node->d2dInfo.addr)
+    {
+        OICFree(node->d2dInfo.addr);
+    }
+    node->d2dInfo.addr = OICStrdup(endpoint.addr);
+
+    if (CA_ADAPTER_IP & endpoint.adapter)
+    {
+        node->d2dInfo.udpPort = endpoint.port;
+    }
+    else if (CA_ADAPTER_TCP & endpoint.adapter)
+    {
+        node->d2dInfo.tcpPort = endpoint.port;
+    }
+
+    CAMgrUtilDevInfoListPrint(devInfoList);
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAMgrUtilResetDevInfo(CMDeviceInfoList_t *devInfoList)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(devInfoList, TAG, "devInfoList");
+
+    CMDeviceInfoList_t *cur = devInfoList;
+    CMDeviceInfo_t *devInfo = NULL;
+
+    while (cur != NULL)
+    {
+        devInfo = cur->deviceInfo;
+
+        if (NULL != devInfo && NULL != devInfo->d2dInfo.addr)
+        {
+            devInfo->d2dInfo.adapter = 0;
+            devInfo->d2dInfo.flags = 0;
+            OICFree(devInfo->d2dInfo.addr);
+            devInfo->d2dInfo.addr = NULL;
+            devInfo->d2dInfo.udpPort = 0;
+            devInfo->d2dInfo.tcpPort = 0;
+        }
+
+        cur = cur->next;
+    }
+
+    CAMgrUtilDevInfoListPrint(devInfoList);
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return CA_STATUS_OK;
+}
+
+void CAMgrUtilDestroyDevInfoList(CMDeviceInfoList_t *devInfoList)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    while (devInfoList != NULL)
+    {
+        CMDeviceInfoList_t *temp = devInfoList;
+        devInfoList = devInfoList->next;
+        CAMgrUtilDevInfoFree(temp->deviceInfo);
+        OICFree(temp);
+        temp = NULL;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static CMDeviceInfo_t* CAMgrUtilDevInfoCreate(const CAEndpoint_t endpoint)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL_RET(endpoint.remoteId, TAG, "remoteId", NULL);
+    VERIFY_NON_NULL_RET(endpoint.addr, TAG, "cloudAddr", NULL);
+
+    CMDeviceInfo_t *node = (CMDeviceInfo_t *)OICCalloc(1, sizeof(CMDeviceInfo_t));
+    if (NULL == node)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return NULL;
+    }
+
+    node->deviceId = OICStrdup(endpoint.remoteId);
+
+    node->d2sInfo.adapter = endpoint.adapter;
+    node->d2sInfo.flags = endpoint.flags;
+    node->d2sInfo.addr = OICStrdup(endpoint.addr);
+    node->d2sInfo.udpPort = 0;
+    node->d2sInfo.tcpPort = endpoint.port;
+
+    node->d2dInfo.adapter = 0;
+    node->d2dInfo.flags = 0;
+    node->d2dInfo.addr = NULL;
+    node->d2dInfo.udpPort = 0;
+    node->d2dInfo.tcpPort = 0;
+
+    OIC_LOG_V(DEBUG, TAG, "remoteId[%s] cloudAddr[%s] cloudPort[%d]",
+              node->deviceId, node->d2sInfo.addr, node->d2sInfo.tcpPort);
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+
+    return node;
+}
+
+static void CAMgrUtilDevInfoFree(CMDeviceInfo_t *devInfo)
+{
+    if (NULL != devInfo)
+    {
+        if (NULL != devInfo->deviceId)
+        {
+            OICFree(devInfo->deviceId);
+        }
+        if (NULL != devInfo->d2dInfo.addr)
+        {
+            OICFree(devInfo->d2dInfo.addr);
+        }
+        if (NULL != devInfo->d2sInfo.addr)
+        {
+            OICFree(devInfo->d2sInfo.addr);
+        }
+
+        OICFree(devInfo);
+    }
+}
+
+static void CAMgrUtilDevInfoListPrint(CMDeviceInfoList_t *devInfoList)
+{
+    size_t index = 1;
+    CMDeviceInfoList_t *cur = devInfoList;
+    CMDeviceInfo_t *devInfo = NULL;
+
+    while (cur != NULL)
+    {
+        devInfo = cur->deviceInfo;
+        OIC_LOG(DEBUG, TAG, "---------------------------------------------------------------");
+        if (NULL != devInfo->deviceId)
+        {
+            OIC_LOG_V(DEBUG, TAG, "     %zu. device ID : %s", index, devInfo->deviceId);
+        }
+        OIC_LOG_V(DEBUG, TAG, "         local address : %s", devInfo->d2dInfo.addr);
+        OIC_LOG_V(DEBUG, TAG, "         local udp port : %d", devInfo->d2dInfo.udpPort);
+        OIC_LOG_V(DEBUG, TAG, "         local tcp port : %d", devInfo->d2dInfo.tcpPort);
+        OIC_LOG_V(DEBUG, TAG, "         cloud address : %s", devInfo->d2sInfo.addr);
+        OIC_LOG_V(DEBUG, TAG, "         cloud tcp port : %d", devInfo->d2sInfo.tcpPort);
+        OIC_LOG(DEBUG, TAG, "---------------------------------------------------------------");
+        cur = cur->next;
+        index++;
+    }
+    OIC_LOG_V(DEBUG, TAG, "Done.");
+}
+
+char *CAMgrUtilGetDeviceId(char *uri)
+{
+    VERIFY_NON_NULL_RET(uri, TAG, "uri", NULL);
+
+    char *result = NULL;
+    char *copyUri = OICStrdup(uri);
+
+    size_t tokSize = 0;
+    char *str = copyUri;
+
+    char *savePtr = NULL;
+    char *tok = strtok_r(str, "/", &savePtr);
+    while (tok != NULL)
+    {
+        tokSize = strlen(tok);
+        if (tokSize == CA_MAX_IDENTITY_SIZE - 1)
+        {
+            if (OCIsUUID(tok))
+            {
+                OIC_LOG_V(DEBUG, TAG, "[%s] has uuid", uri);
+                result = OICStrdup(tok);
+            }
+        }
+        tok = strtok_r(NULL, "/", &savePtr);
+    }
+    OICFree(copyUri);
+    copyUri = NULL;
+
+    return result;
+}
index bf0191a..6aff40f 100644 (file)
 #ifndef CA_MANAGER_UTIL_H_
 #define CA_MANAGER_UTIL_H_
 
-#include "logger.h"
-#include "cathreadpool.h"
-#include "uarraylist.h"
-#include "octhread.h"
+#include "cacommon.h"
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
+/**
+ * Information related to endpoint.
+ * Used for switching endpoint information.
+ */
+typedef struct
+{
+    CATransportAdapter_t adapter;
+    CATransportFlags_t flags;
+    char *addr;
+    uint16_t udpPort;
+    uint16_t tcpPort;
+} CMIpInfo_t;
+
+/**
+ * D2S, D2D information about specific di.
+ */
+typedef struct
+{
+    char *deviceId;
+    CMIpInfo_t d2dInfo;
+    CMIpInfo_t d2sInfo;
+} CMDeviceInfo_t;
+
+/**
+ * List structure for CMDeviceInfo_t.
+ */
+typedef struct CMDeviceInfoList
+{
+    CMDeviceInfo_t *deviceInfo;
+    struct CMDeviceInfoList *next;
+} CMDeviceInfoList_t;
+
+/**
+ * This function is used to add the DeviceInfo structure to IP connection info table.
+ *
+ * @param[in,out] devInfoList   Pointer to IP connection info table which contains
+ *                              D2D,D2S ip related informaions.
+ * @param[in]     endpoint      remote Endpoint to be added in IP connection info table.
+ *
+ * @return :: CA_STATUS_OK or Appropriate error code.
+ * @retval :: CA_STATUS_OK  Successful.
+ * @retval :: CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAMgrUtilAddDevInfoToList(CMDeviceInfoList_t **devInfoList,
+                                     const CAEndpoint_t endpoint);
 
+/**
+ * This function is used to get the DeviceInfo which have specific device id
+ * from the table.
+ *
+ * @param[in]  devInfoList  Pointer to IP connection info table which contains
+ *                          D2D,D2S ip related informaions.
+ * @param[in]  deviceId     Unique remote device id to access IP connection info
+ *                          table.
+ * @param[out] devInfo      Table information obtained with a specific device id.
+ *
+ * @return :: CA_STATUS_OK or Appropriate error code.
+ * @retval :: CA_STATUS_OK  Successful.
+ * @retval :: CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAMgrUtilGetDevInfo(CMDeviceInfoList_t *devInfoList, const char *deviceId,
+                               CMDeviceInfo_t **devInfo);
+
+/**
+ * This function is used to update IP connection table component which have specific device id.
+ *
+ * @param[in,out] devInfoList   Pointer to IP connection info table which contains
+ *                              D2D,D2S ip related informaions.
+ * @param[in]     endpoint      remote Endpoint to be updated in IP connection info table.
+ *
+ * @return :: CA_STATUS_OK or Appropriate error code.
+ * @retval :: CA_STATUS_OK  Successful.
+ * @retval :: CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAMgrUtilUpdateDevInfo(CMDeviceInfoList_t *devInfoList,
+                                  const CAEndpoint_t endpoint);
+
+/**
+ * This function is used to reset all D2D informations.
+ *
+ * @param[in,out] devInfoList   Pointer to IP connection info table which contains
+ *                              D2D,D2S ip related informaions.
+ *
+ * @return :: CA_STATUS_OK or Appropriate error code.
+ * @retval :: CA_STATUS_OK  Successful.
+ * @retval :: CA_STATUS_FAILED Operation failed.
+ */
+CAResult_t CAMgrUtilResetDevInfo(CMDeviceInfoList_t *devInfoList);
+
+/**
+ * This function is used to clear IP connection info table.
+ *
+ * @param[in,out] devInfoList   Pointer to IP connection info table which contains
+ *                              D2D,D2S ip related informaions.
+ */
+void CAMgrUtilDestroyDevInfoList(CMDeviceInfoList_t *devInfoList);
+
+/**
+ *  This function is used to get a device id from uri.
+ *
+ *  @param[in] uri
+ *
+ *  @return :: device id
+ */
+char* CAMgrUtilGetDeviceId(char *uri);
 
 #ifdef __cplusplus
 } /* extern "C" */
index 061170b..741ceff 100644 (file)
  *
  ******************************************************************/
 
-#include "logger.h"
-#include "cathreadpool.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "caadapterutils.h"
+#include "cainterface.h"
+#include "camessagehandler.h"
+#include "caremotehandler.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
 #include "octhread.h"
+#include "logger.h"
+#include "caadapterutils.h"
+
+#include "camessagearbiter.h"
+#include "camanagerutil.h"
+#include "capolicymanager.h"
+
+#define TAG "OIC_CM_MSG_ARBITER"
+
+#define CA_MSG_ARBITER_DI_URI_LENGTH 47
+
+#define CA_MSG_ARBITER_PING_URI "/oic/ping"
+
+/**
+ * List for remote device information table.
+ */
+static CMDeviceInfoList_t *g_remoteDeviceInfoList;
+
+/**
+ * Mutex to synchronize the access to remote device info list.
+ */
+static oc_mutex g_remoteDeviceInfoListMutex = NULL;
+
+/**
+ * Initializes all required mutex variable for messge arbiter.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+static CAResult_t CAMsgArbiterInitMutexVariables();
+
+/**
+ * Terminates all required mutex variable for messge arbiter.
+ */
+static void CAMsgArbiterTerminateMutexVariables();
+
+CAResult_t CAMsgArbiterInitialize()
+{
+    OIC_LOG(DEBUG, TAG, "CAMsgArbiterInitialize");
+
+    return CAMsgArbiterInitMutexVariables();
+}
+
+CAResult_t CAMsgArbiterTerminate()
+{
+    OIC_LOG(DEBUG, TAG, "CAMsgArbiterTerminate");
+
+    if (g_remoteDeviceInfoList)
+    {
+        oc_mutex_lock(g_remoteDeviceInfoListMutex);
+        CAMgrUtilDestroyDevInfoList(g_remoteDeviceInfoList);
+        oc_mutex_unlock(g_remoteDeviceInfoListMutex);
+    }
+    CAMsgArbiterTerminateMutexVariables();
+    CAPolicyMgrTerminate();
+
+    return CA_STATUS_OK;
+}
+
+static CAResult_t CAMsgArbiterInitMutexVariables()
+{
+    if (NULL == g_remoteDeviceInfoListMutex)
+    {
+        g_remoteDeviceInfoListMutex = oc_mutex_new();
+        if (NULL == g_remoteDeviceInfoListMutex)
+        {
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+    return CA_STATUS_OK;
+}
+
+static void CAMsgArbiterTerminateMutexVariables()
+{
+    if (g_remoteDeviceInfoListMutex)
+    {
+        oc_mutex_free(g_remoteDeviceInfoListMutex);
+        g_remoteDeviceInfoListMutex = NULL;
+    }
+}
+
+CAResult_t CAMsgArbiterGetMessageData(CAData_t *data)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    VERIFY_NON_NULL(data, TAG, "data is NULL");
+
+    CMDeviceInfo_t *targetInfo = NULL;
+
+    if (NULL != data->requestInfo &&
+            (NULL == data->requestInfo->info.resourceUri ||
+            !strcmp(data->requestInfo->info.resourceUri, CA_MSG_ARBITER_PING_URI)))
+    {
+        OIC_LOG(DEBUG, TAG, "ping uri and null are ignored in messsage arbiter");
+        return CA_STATUS_FAILED;
+    }
+
+    CAConnectUserPref_t connPrefer = CA_USER_PREF_LOCAL_TCP;
+    CAResult_t ret = CAPolicyMgrGetConfigure(&connPrefer);
+
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(DEBUG, TAG, "CAPolicyMgrGetConfigure is failed");
+        return ret;
+    }
+    else
+    {
+        if (CA_USER_PREF_CLOUD != connPrefer && CA_REQUEST_DATA == data->dataType
+            && NULL != data->remoteEndpoint && NULL != data->requestInfo)
+        {
+            char *deviceId = OICStrdup(data->remoteEndpoint->remoteId);
+
+            char *di= CAMgrUtilGetDeviceId(data->requestInfo->info.resourceUri);
+            //if deviceId is null && hasUUID, extract device id from uri.
+            if ((NULL == deviceId || strcmp(deviceId, "") == 0) && NULL != di)
+            {
+                deviceId = di;
+            }
+            else if (NULL != di)
+            {
+                OICFree(di);
+            }
+
+            oc_mutex_lock(g_remoteDeviceInfoListMutex);
+            ret = CAMgrUtilGetDevInfo(g_remoteDeviceInfoList, deviceId, &targetInfo);
+            oc_mutex_unlock(g_remoteDeviceInfoListMutex);
+
+            if (CA_STATUS_OK != ret)
+            {
+                OIC_LOG_V(DEBUG, TAG, "device id[%s] is not in connection switch info list",
+                        deviceId);
+                return ret;
+            }
+
+            if (NULL != targetInfo->d2dInfo.addr)
+            {
+                OICStrcpyPartial(data->remoteEndpoint->addr, sizeof(data->remoteEndpoint->addr),
+                             targetInfo->d2dInfo.addr, strlen(targetInfo->d2dInfo.addr) + 1);
+                if (CA_USER_PREF_LOCAL_TCP == connPrefer &&
+                    (targetInfo->d2dInfo.adapter & CA_ADAPTER_TCP))
+                {
+                    data->remoteEndpoint->port = targetInfo->d2dInfo.tcpPort;
+                    data->remoteEndpoint->adapter = CA_ADAPTER_TCP;
+                }
+                else if (targetInfo->d2dInfo.adapter & CA_ADAPTER_IP)
+                {
+                    data->remoteEndpoint->port = targetInfo->d2dInfo.udpPort;
+                    data->remoteEndpoint->adapter = CA_ADAPTER_IP;
+                }
+                data->remoteEndpoint->flags = targetInfo->d2dInfo.flags;
+
+                CAURI_t resourceUri = OICStrdup(data->requestInfo->info.resourceUri
+                                                                + CA_MSG_ARBITER_DI_URI_LENGTH);
+                OICFree(data->requestInfo->info.resourceUri);
+                data->requestInfo->info.resourceUri = resourceUri;
+
+                OIC_LOG_V(DEBUG, TAG, "device id[%s] switched to D2D connect", deviceId);
+                OIC_LOG_V(DEBUG, TAG, "local addr[%s] local port[%d] adapter[%s]",
+                          data->remoteEndpoint->addr, data->remoteEndpoint->port,
+                          data->remoteEndpoint->adapter == CA_ADAPTER_IP ? "IP" : "TCP");
+                OIC_LOG_V(DEBUG, TAG, "resource uri : %s", data->requestInfo->info.resourceUri);
+            }
+            else
+            {
+                OIC_LOG_V(DEBUG, TAG, "local address is not set.");
+            }
+
+            OICFree(deviceId);
+            deviceId = NULL;
+        }
+        else
+        {
+            return CA_STATUS_FAILED;
+        }
+    }
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return ret;
+}
+
+CAResult_t CAMsgArbiterUpdateDeviceInfo(const CAEndpoint_t endpoint, bool isCloud)
+{
+    OIC_LOG(DEBUG, TAG, "IN - CAMsgArbiterUpdateDeviceInfo");
+
+    VERIFY_NON_NULL(endpoint.remoteId, TAG, "remoteId");
+
+    CAResult_t ret = CA_STATUS_FAILED;
+    const char *deviceId = endpoint.remoteId;
+
+    if (isCloud)
+    {
+        oc_mutex_lock(g_remoteDeviceInfoListMutex);
+        ret = CAMgrUtilAddDevInfoToList(&g_remoteDeviceInfoList, endpoint);
+        oc_mutex_unlock(g_remoteDeviceInfoListMutex);
+
+        if (CA_STATUS_OK != ret)
+        {
+            OIC_LOG(ERROR, TAG, "AddToList failed!");
+            return ret;
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "device id[%s] is successfully added into list!", deviceId);
+    }
+    else
+    {
+        oc_mutex_lock(g_remoteDeviceInfoListMutex);
+        ret = CAMgrUtilUpdateDevInfo(g_remoteDeviceInfoList, endpoint);
+        oc_mutex_unlock(g_remoteDeviceInfoListMutex);
+
+        if (CA_STATUS_OK != ret)
+        {
+            OIC_LOG_V(ERROR, TAG, "device id[%s] is not included in list", deviceId);
+            return ret;
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "device id[%s] is successfully updated into list!", deviceId);
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT - CAMsgArbiterUpdateDeviceInfo");
+    return ret;
+}
+
+CAResult_t CAMsgArbiterResetDeviceInfo()
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    oc_mutex_lock(g_remoteDeviceInfoListMutex);
+    CAResult_t ret = CAMgrUtilResetDevInfo(g_remoteDeviceInfoList);
+    oc_mutex_unlock(g_remoteDeviceInfoListMutex);
 
-#define TAG "OIC_CM_ARBITER"
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return ret;
+}
index 238362d..44ea9b0 100644 (file)
 #ifndef CA_CONNECTIONMANAGER_ARBITER_H_
 #define CA_CONNECTIONMANAGER_ARBITER_H_
 
-#include "logger.h"
-#include "cathreadpool.h"
-#include "octhread.h"
+#include "cacommon.h"
+#include "camanagerutil.h"
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
+/**
+ * Initializes the Message Arbiter
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAMsgArbiterInitialize();
+
+/**
+ * Terminate the Message Arbiter
+ */
+CAResult_t CAMsgArbiterTerminate();
+
+/**
+ * Update Device Info. in managed data
+ * @param[in]  endpoint       network address.
+ * @param[in]  isCloud        with cloud or not .
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAMsgArbiterUpdateDeviceInfo(const CAEndpoint_t endpoint, bool isCloud);
+
+/**
+ * Reset Device Info in managed data
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAMsgArbiterResetDeviceInfo();
+
+/**
+ * Get request/response message to send.
+ * @param[in, out]  data     data to request or response.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CAMsgArbiterGetMessageData(CAData_t *data);
 
 #ifdef __cplusplus
 } /* extern "C" */
index d9a4c9e..cbefc58 100644 (file)
 
 #define TAG "OIC_CM_POLICY"
 
-static CMConfigureInfo_t g_configure = {.addr = NULL,
-                                        .adapter = CA_ADAPTER_IP,
-                                        .level = NORMAL_SPEED};
+/**
+ * Mutex to synchronize the access to g_userConfigureMutex variable.
+ */
+static oc_mutex g_userConfigureMutex = NULL;
 
-void CMSetConfigure(CMConfigureInfo_t info)
-{
-    OIC_LOG(DEBUG, TAG, "CMSetConfigurePolicy");
-    OICStrcpy(g_configure.addr, sizeof(g_configure.addr), info.addr);
-    g_configure.adapter = info.adapter;
-    g_configure.level = info.level;
-}
+/**
+ * User prefer variable to process connection manager logic.
+ * default: Cloud TCP
+ */
+static CAConnectUserPref_t g_connectUserPrefer = CA_USER_PREF_CLOUD;
 
-const char* CMGetTargetAddress()
+CAResult_t CAPolicyMgrSetConfiguration(CAConnectUserPref_t connPrefer)
 {
-    OIC_LOG(DEBUG, TAG, "CMGetTargetAddress");
-    return g_configure.addr;
+    OIC_LOG(DEBUG, TAG, "CAPolicyMgrSetConfiguration");
+
+    switch (connPrefer)
+    {
+        case CA_USER_PREF_CLOUD:
+            OIC_LOG_V(DEBUG, TAG, "connPrefer: %d(CLOUD)", connPrefer);
+            break;
+        case CA_USER_PREF_LOCAL_UDP:
+            OIC_LOG_V(DEBUG, TAG, "connPrefer: %d(LOCAL UDP)", connPrefer);
+            break;
+        case CA_USER_PREF_LOCAL_TCP:
+            OIC_LOG_V(DEBUG, TAG, "connPrefer: %d(LOCAL TCP)", connPrefer);
+            break;
+        default:
+            OIC_LOG_V(DEBUG, TAG, "Unsupported connPrefer type : %d", connPrefer);
+            return CA_STATUS_FAILED;
+    }
+
+    if (NULL == g_userConfigureMutex)
+    {
+        g_userConfigureMutex = oc_mutex_new();
+        if (NULL == g_userConfigureMutex)
+        {
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
+            return CA_MEMORY_ALLOC_FAILED;
+        }
+    }
+    oc_mutex_lock(g_userConfigureMutex);
+    g_connectUserPrefer = connPrefer;
+    oc_mutex_unlock(g_userConfigureMutex);
+
+    return CA_STATUS_OK;
 }
 
-CATransportAdapter_t CMGetAdapterType()
+CAResult_t CAPolicyMgrGetConfigure(CAConnectUserPref_t *connPrefer)
 {
-    OIC_LOG(DEBUG, TAG, "CMGetAdapterType");
-    return g_configure.adapter;
+    if (NULL == g_userConfigureMutex)
+    {
+        g_userConfigureMutex = oc_mutex_new();
+        if (NULL == g_userConfigureMutex)
+        {
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
+            return CA_MEMORY_ALLOC_FAILED;
+        }
+    }
+    oc_mutex_lock(g_userConfigureMutex);
+    *connPrefer = g_connectUserPrefer;
+    oc_mutex_unlock(g_userConfigureMutex);
+    return CA_STATUS_OK;
 }
 
-CMSpeedLevel_t CMGetSpeedOfResponseLevel()
+void CAPolicyMgrTerminate()
 {
-    OIC_LOG(DEBUG, TAG, "CMGetSpeedOfResponseLevel");
-    return g_configure.level;
+    if (g_userConfigureMutex)
+    {
+        oc_mutex_free(g_userConfigureMutex);
+        g_userConfigureMutex = NULL;
+    }
 }
index 9bef0cf..0e1b3c9 100644 (file)
@@ -40,29 +40,25 @@ extern "C"
 #endif
 
 /**
- * Set connection manager configure.
- * Target address and connectivity priority and speed level can be set in this method.
- * @param[in] info  configuration data for connection manager policy
- */
-void CMSetConfigure(CMConfigureInfo_t info);
-
-/**
- * get target address.
- * @return address
+ * Set connection Preference for Cloud or Local TCP or Local UDP
+ * @param[in] user connection preference
+ *
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-const char* CMGetTargetAddress();
+CAResult_t CAPolicyMgrSetConfiguration(CAConnectUserPref_t connPrefer);
 
 /**
- * get Adapter Type of current priority.
- * @return ::CATransportAdapter_t value.
+ * Get connection Preference
+ *
+ * @param[out]  connPrefer  Cloud | local TCP | local UDP
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
  */
-CATransportAdapter_t CMGetAdapterType();
+CAResult_t CAPolicyMgrGetConfigure(CAConnectUserPref_t *connPrefer);
 
 /**
- * get speed of response level.
- * @return ::CMSpeedLevel_t value.
+ * terminate mutex
  */
-CMSpeedLevel_t CMGetSpeedOfResponseLevel();
+void CAPolicyMgrTerminate();
 
 #ifdef __cplusplus
 } /* extern "C" */
index afcf64c..34cd8a0 100644 (file)
@@ -25,6 +25,9 @@
 #include "cacommon.h"
 #include "logger.h"
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+#include "caconnectionmanager.h"
+#endif
 #define TAG "OIC_CA_COMMON_UTILS"
 
 CAResult_t CARegisterNetworkMonitorHandler(CAAdapterStateChangedCB adapterStateCB,
@@ -165,6 +168,38 @@ uint16_t CAGetAssignedPortNumber(CATransportAdapter_t adapter, CATransportFlags_
     return 0;
 }
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+CAResult_t CAUtilCMInitailize()
+{
+    return CACMInitialize();
+}
+
+CAResult_t CAUtilCMTerminate()
+{
+    return CACMTerminate();
+}
+
+CAResult_t CAUtilCMUpdateRemoteDeviceInfo(const CAEndpoint_t endpoint, bool isCloud)
+{
+    return CACMUpdateRemoteDeviceInfo(endpoint, isCloud);
+}
+
+CAResult_t CAUtilCMResetRemoteDeviceInfo()
+{
+    return CACMResetRemoteDeviceInfo();
+}
+
+CAResult_t CAUtilCMSetConnectionUserConfig(CAConnectUserPref_t connPrefer)
+{
+    return CACMSetConnUserConfig(connPrefer);
+}
+
+CAResult_t CAUtilCMGetConnectionUserConfig(CAConnectUserPref_t *connPrefer)
+{
+    return CACMGetConnUserConfig(connPrefer);
+}
+#endif
+
 #ifdef __JAVA__
 #ifdef __ANDROID__
 /**
index 48d553e..dcc3e18 100755 (executable)
@@ -1874,6 +1874,22 @@ typedef struct trustCertChainContext
 } trustCertChainContext_t;
 #endif
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+/**
+ * User Preference of connectivity channel
+ */
+typedef enum
+{
+    /** Cloud TCP */
+    OC_USER_PREF_CLOUD = 0,
+    /** local UDP */
+    OC_USER_PREF_LOCAL_UDP = 1,
+    /** local TCP */
+    OC_USER_PREF_LOCAL_TCP =2
+} OCConnectUserPref_t;
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 04d99bd..7ea0e3d 100644 (file)
@@ -35,6 +35,7 @@ rd_mode = env.get('RD_MODE')
 with_ra = env.get('WITH_RA')
 with_ra_ibb = env.get('WITH_RA_IBB')
 with_tcp = env.get('WITH_TCP')
+with_cloud = env.get('WITH_CLOUD')
 with_mq = env.get('WITH_MQ')
 # As in the source code, it includes arduino Time library (C++)
 # It requires compile the .c with g++
@@ -186,6 +187,8 @@ liboctbstack_src = [
 
 if with_tcp == True:
     liboctbstack_src.append(OCTBSTACK_SRC + 'oickeepalive.c')
+    if with_cloud == True:
+        liboctbstack_src.append(OCTBSTACK_SRC + 'occonnectionmanager.c')
 
 if 'SERVER' in rd_mode:
     liboctbstack_src.append(OCTBSTACK_SRC + 'oicresourcedirectory.c')
diff --git a/resource/csdk/stack/include/internal/occonnectionmanager.h b/resource/csdk/stack/include/internal/occonnectionmanager.h
new file mode 100755 (executable)
index 0000000..5fbc73e
--- /dev/null
@@ -0,0 +1,41 @@
+/******************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+/**
+ * Initialize the Connection Manager and set IP ConnectionStatus callback
+ *
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult OCCMInitialize();
+
+/**
+ * Terminate the Connection Manager
+ *
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult OCCMTerminate();
+
+/**
+ *  Discover Resources by Connection Manager
+ *
+ * @param[in]  clientResponse   OCClientResponse struct pointer.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult OCCMDiscoveryResource(OCClientResponse *clientResponse);
diff --git a/resource/csdk/stack/src/occonnectionmanager.c b/resource/csdk/stack/src/occonnectionmanager.c
new file mode 100755 (executable)
index 0000000..d141605
--- /dev/null
@@ -0,0 +1,343 @@
+/******************************************************************
+ *
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include "iotivity_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <getopt.h>
+#include "octypes.h"
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocrandom.h"
+#include "logger.h"
+#include "occonnectionmanager.h"
+#include "ocpayload.h"
+#include "oic_string.h"
+#include "oic_malloc.h"
+
+#include "cacommon.h"
+#include "cainterface.h"
+#include "cautilinterface.h"
+
+#define DEFAULT_CONTEXT_VALUE (0x99)
+#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
+             TAG, #arg " is NULL"); return (retVal); } }
+#define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
+             TAG, #arg " is NULL"); return; } }
+#define CLOUD_PREFIX "/oic/route\0"
+#define CLOUD_PREFIX_LENGTH 10
+
+#define TAG "OIC_RI_CM"
+
+/**
+ * Flag for first response message.
+ * Afer first discovery response, D2D endpoint info need to be updated.
+ */
+static bool isFirstResponse = true;
+
+/**
+ * Adapter state change callback method.
+ *
+ * @param[in] adapter   CA network adapter type.
+ * @param[in] enabled   current adapter state.
+ */
+static void OCAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled);
+
+/**
+ *  Connection State change callback method.
+ *
+ *  @param[in] info         CAEndpoint which has address, port and etc.
+ *  @param[in] isConnected  current connection state.
+ */
+static void OCConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected);
+
+/**
+ * Check uri has device id.
+ *
+ * @param[in]  uri  uri of resource.
+ * @return  true if uri has device id, or false.
+ */
+static bool OCCMHasDeviceId(const char *uri);
+
+/**
+ * This function is used to find resources when connection status is changed
+ * or first discovery response.
+ *
+ * @return ::OC_STACK_OK or ERROR CODES (::OCStackResult_t error codes in octypes.h).
+ */
+static OCStackResult OCCMFindResource();
+
+/**
+ * Callback function for OCCMFindResource.
+ *
+ * @return ::OC_STACK_KEEP_TRANSACTION
+ */
+static OCStackApplicationResult OCCMFoundResource(void *ctx,
+                                OCDoHandle handle, OCClientResponse *clientResponse);
+
+OCStackResult OCCMInitialize()
+{
+    OIC_LOG_V(INFO, TAG, "%s", __func__);
+
+    //Initialize the Connection Manager
+    CAResult_t ret = CAUtilCMInitailize();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CAInitializeConnectionManager failed!");
+        return CAResultToOCResult(ret);
+    }
+
+    // Register NetworkMonitor
+    ret = CARegisterNetworkMonitorHandler(OCAdapterStateChangedHandler,
+                                          OCConnectionStateChangedHandler);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CARegisterNetworkMonitorHandler failed!");
+        return CAResultToOCResult(ret);
+    }
+
+    return CAResultToOCResult(ret);
+}
+
+OCStackResult OCCMTerminate()
+{
+    OIC_LOG_V(INFO, TAG, "%s", __func__);
+
+    //Unregister IP NetworkMonitor
+    CAResult_t ret = CAUnregisterNetworkMonitorHandler(OCAdapterStateChangedHandler,
+                                                       OCConnectionStateChangedHandler);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CAUnregisterNetworkMonitorHandler has failed");
+    }
+
+    //Terminate the Connection Manager
+    ret = CAUtilCMTerminate();
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CAUtilCMTerminate has failed");
+    }
+
+    return CAResultToOCResult(ret);
+}
+
+OCStackResult OCCMDiscoveryResource(OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "%s", __func__);
+
+    VERIFY_NON_NULL(clientResponse, ERROR, OC_STACK_INVALID_PARAM);
+
+    OCDiscoveryPayload *payload = (OCDiscoveryPayload*) clientResponse->payload;
+    if (!payload)
+    {
+        OIC_LOG(ERROR, TAG, "payload is empty!");
+        return OC_STACK_ERROR;
+    }
+
+    if (NULL == payload->sid)
+    {
+        OIC_LOG(ERROR, TAG, "Device ID is null");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(INFO, TAG, "Device ID : %s", payload->sid);
+
+    OCResourcePayload *resource = (OCResourcePayload*) payload->resources;
+
+    if (NULL == resource)
+    {
+        OIC_LOG(ERROR, TAG, "payload resource is NULL");
+        return OC_STACK_ERROR;
+    }
+
+    if (NULL == resource->uri)
+    {
+        OIC_LOG(ERROR, TAG, "resource->uri is NULL");
+        return OC_STACK_ERROR;
+    }
+
+    // update di in CM managed table
+    bool isCloud = OCCMHasDeviceId(resource->uri);
+    CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+    CopyDevAddrToEndpoint(&(clientResponse->devAddr), &endpoint);
+
+    CAResult_t ret = CAUtilCMUpdateRemoteDeviceInfo(endpoint, isCloud);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "CAUtilCMUpdateRemoteDeviceInfo is failed.");
+        return CAResultToOCResult(ret);
+    }
+
+#ifdef TCP_ADAPTER
+    if (!isCloud && resource->tcpPort != 0)
+    {
+        endpoint.adapter = CA_ADAPTER_TCP;
+        endpoint.port = resource->tcpPort;
+
+        ret = CAUtilCMUpdateRemoteDeviceInfo(endpoint, isCloud);
+        if (CA_STATUS_OK != ret)
+        {
+            OIC_LOG(ERROR, TAG, "CAUtilCMUpdateRemoteDeviceInfo is failed!");
+            return CAResultToOCResult(ret);
+        }
+    }
+#endif
+
+    //CM tries to find local resource when ocstack found a cloud resource.
+    if (isFirstResponse)
+    {
+        OCStackResult ret = OCCMFindResource();
+        if (OC_STACK_OK != ret)
+        {
+            OIC_LOG(ERROR, TAG, "OCCMFindResource is failed!");
+            return ret;
+        }
+        isFirstResponse = false;
+    }
+
+    return OC_STACK_OK;
+}
+
+static void OCAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled)
+{
+    // check user configuration
+    CAConnectUserPref_t connPrefer = CA_USER_PREF_CLOUD;
+    CAResult_t ret = CAUtilCMGetConnectionUserConfig(&connPrefer);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "CAUtilCMGetConnectionUserConfig failed with error %u", ret);
+    }
+
+    if (CA_USER_PREF_CLOUD != connPrefer)
+    {
+        //set connection callback
+        if (true == enabled)
+        {
+            OIC_LOG(DEBUG, TAG, "CM ConnectionStatusChangedHandler ENABLED");
+        }
+        else
+        {
+            OIC_LOG(DEBUG, TAG, "CM ConnectionStatusChangedHandler DISABLED");
+        }
+    }
+}
+
+static void OCConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected)
+{
+    OIC_LOG(DEBUG, TAG, "OCConnectionStateChangedHandler");
+
+    CAConnectUserPref_t connPrefer = CA_USER_PREF_CLOUD;
+    CAResult_t ret = CAUtilCMGetConnectionUserConfig(&connPrefer);
+    if (CA_STATUS_OK != ret)
+    {
+        OIC_LOG_V(ERROR, TAG, "CAUtilCMGetConnectionUserConfig failed with error %u", ret);
+    }
+    else
+    {
+        if (CA_USER_PREF_CLOUD != connPrefer)
+        {
+            if (!isConnected)
+            {
+                OIC_LOG(DEBUG, TAG, "is disconnedted");
+
+                //clean local ip up in CM managed table
+                CAUtilCMResetRemoteDeviceInfo();
+            }
+            else
+            {
+                OIC_LOG(DEBUG, TAG, "is connected");
+
+                // Find Resource
+                OCCMFindResource();
+            }
+        }
+    }
+}
+
+static OCStackResult OCCMFindResource()
+{
+    OIC_LOG_V(INFO, TAG, "%s", __func__);
+
+    OCQualityOfService qos = OC_LOW_QOS;
+    char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
+    snprintf(szQueryUri, sizeof(szQueryUri) - 1, "%s%c", OC_RSRVD_WELL_KNOWN_URI, '\0');
+
+    OCCallbackData cbData = {0,};
+    cbData.cb = OCCMFoundResource;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+    cbData.cd = NULL;
+
+    OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri,
+                                     NULL, 0, CT_DEFAULT | CT_IP_USE_V4,
+                                     (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+                                     &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack resource error");
+        return ret;
+    }
+
+    return OC_STACK_OK;
+}
+
+static OCStackApplicationResult OCCMFoundResource(void* ctx,
+                                           OCDoHandle handle,
+                                           OCClientResponse* clientResponse)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    OC_UNUSED(clientResponse);
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+static bool OCCMHasDeviceId(const char* uri)
+{
+    bool ret = false;
+    char *copyUri = OICStrdup(uri);
+    bool hasCloudPrefix = strncmp(CLOUD_PREFIX, copyUri, CLOUD_PREFIX_LENGTH) == 0 ? true : false;
+
+    int tokSize = 0;
+    char *str = copyUri;
+
+    char *savePtr = NULL;
+    char *tok = strtok_r(str, "/", &savePtr);
+    while (hasCloudPrefix && tok != NULL && ret != true)
+    {
+        tokSize = strlen(tok);
+        if (tokSize == MAX_IDENTITY_SIZE - 1)
+        {
+            if (OCIsUUID(tok))
+            {
+                OIC_LOG_V(DEBUG, TAG, "[%s] has uuid", uri);
+                ret = true;
+            }
+        }
+        tok = strtok_r(NULL, "/", &savePtr);
+    }
+    OICFree(copyUri);
+    copyUri = NULL;
+
+    return ret;
+}
index 3cdaecb..70fecf1 100644 (file)
 #include "oicgroup.h"
 #include "ocendpoint.h"
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+#include "occonnectionmanager.h"
+#endif
+
 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
 #include "routingutility.h"
 #ifdef ROUTING_GATEWAY
@@ -1596,6 +1600,10 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
                                   payload->sid);
                         OIC_LOG_V(INFO, TAG, "Device ID of response : %s",
                                   response->devAddr.remoteId);
+
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+                        OCCMDiscoveryResource(&response);
+#endif
                     }
                 }
 
@@ -2425,6 +2433,14 @@ OCStackResult OCInit2(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag
     }
 #endif
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+    // Initialize the Connection Manager
+    if (result == OC_STACK_OK)
+    {
+        result = OCCMInitialize();
+    }
+#endif
+
 exit:
     if(result != OC_STACK_OK)
     {
@@ -2493,6 +2509,11 @@ OCStackResult OCStop()
     // Terminate connectivity-abstraction layer.
     CATerminate();
 
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+    // Terminate the Connection Manager
+    OCCMTerminate();
+#endif
+
     stackState = OC_STACK_UNINITIALIZED;
     return OC_STACK_OK;
 }
index ba758c0..f5ac8a5 100644 (file)
@@ -129,6 +129,18 @@ namespace OC
          */
         OCStackResult setCipherSuite(const uint16_t cipher, OCTransportAdapter adapter);
 #endif // defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+        /**
+         * Set User Preference
+         * @param user preference
+         *        0: OC_USER_PREF_CLOUD (default)
+         *        1: OC_USER_PREF_LOCAL_UDP
+         *        2: OC_USER_PREF_LOCAL_TCP
+         * @return ::OC_STACK_OK if sucess.
+         */
+        OCStackResult setConnectionManagerUserConfig(OCConnectUserPref_t connPriority);
+#endif
     }
 }
 
index 380b3d7..127db0c 100644 (file)
@@ -160,3 +160,12 @@ OCStackResult CAManager::stopLEAdvertising()
 
     return convertCAResultToOCResult(ret);
 }
+
+#if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
+OCStackResult CAManager::setConnectionManagerUserConfig(OCConnectUserPref_t connPriority)
+{
+    CAResult_t ret = CAUtilCMSetConnectionUserConfig((CAConnectUserPref_t)connPriority);
+
+    return convertCAResultToOCResult(ret);
+}
+#endif