From 44afcaa714a2cef07506b0976eabe6987f9488fe Mon Sep 17 00:00:00 2001 From: "jg.ham" Date: Mon, 13 Feb 2017 09:48:03 +0900 Subject: [PATCH] [IOT-1540] Connection manager logic add. Add the function to switch cloud IP to local IP in connection manager. Change-Id: I032d2ae38e63ad79694ebc92b900f6621d0130c3 Signed-off-by: Jonggyu Ham Reviewed-on: https://gerrit.iotivity.org/gerrit/15909 Tested-by: jenkins-iotivity Reviewed-by: Dan Mihai --- .../java/org/iotivity/ca/CaInterface.java | 9 + .../iotivity/ca/CaIpConnectionPreference.java | 47 +++ java/jni/JniCaInterface.c | 19 + java/jni/JniCaInterface.h | 8 + resource/c_common/ocrandom/include/ocrandom.h | 14 +- resource/c_common/ocrandom/src/ocrandom.c | 73 +++- .../csdk/connectivity/api/cautilinterface.h | 69 +++- .../csdk/connectivity/src/camessagehandler.c | 11 + resource/csdk/connectivity/util/SConscript | 6 +- .../util/inc/caconnectionmanager.h | 75 ++-- .../util/src/camanager/caconnectionmanager.c | 132 ++----- .../util/src/camanager/camanagerutil.c | 318 +++++++++++++++- .../util/src/camanager/camanagerutil.h | 109 +++++- .../util/src/camanager/camessagearbiter.c | 243 ++++++++++++- .../util/src/camanager/camessagearbiter.h | 36 +- .../util/src/camanager/capolicymanager.c | 81 ++++- .../util/src/camanager/capolicymanager.h | 28 +- .../connectivity/util/src/cautilinterface.c | 35 ++ resource/csdk/include/octypes.h | 16 + resource/csdk/stack/SConscript | 3 + .../include/internal/occonnectionmanager.h | 41 +++ resource/csdk/stack/src/occonnectionmanager.c | 343 ++++++++++++++++++ resource/csdk/stack/src/ocstack.c | 21 ++ resource/include/CAManager.h | 12 + resource/src/CAManager.cpp | 9 + 25 files changed, 1526 insertions(+), 232 deletions(-) create mode 100644 java/iotivity-android/src/main/java/org/iotivity/ca/CaIpConnectionPreference.java create mode 100755 resource/csdk/stack/include/internal/occonnectionmanager.h create mode 100755 resource/csdk/stack/src/occonnectionmanager.c diff --git a/java/iotivity-android/src/main/java/org/iotivity/ca/CaInterface.java b/java/iotivity-android/src/main/java/org/iotivity/ca/CaInterface.java index 5a8847687..5cad30900 100644 --- a/java/iotivity-android/src/main/java/org/iotivity/ca/CaInterface.java +++ b/java/iotivity-android/src/main/java/org/iotivity/ca/CaInterface.java @@ -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 index 000000000..04edcef0e --- /dev/null +++ b/java/iotivity-android/src/main/java/org/iotivity/ca/CaIpConnectionPreference.java @@ -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; + } +} diff --git a/java/jni/JniCaInterface.c b/java/jni/JniCaInterface.c index a2ce4a0cb..9e380f059 100644 --- a/java/jni/JniCaInterface.c +++ b/java/jni/JniCaInterface.c @@ -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 +} + diff --git a/java/jni/JniCaInterface.h b/java/jni/JniCaInterface.h index 6edd7f231..904f442be 100644 --- a/java/jni/JniCaInterface.h +++ b/java/jni/JniCaInterface.h @@ -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 diff --git a/resource/c_common/ocrandom/include/ocrandom.h b/resource/c_common/ocrandom/include/ocrandom.h index e2d2eb53a..a78590ede 100644 --- a/resource/c_common/ocrandom/include/ocrandom.h +++ b/resource/c_common/ocrandom/include/ocrandom.h @@ -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 diff --git a/resource/c_common/ocrandom/src/ocrandom.c b/resource/c_common/ocrandom/src/ocrandom.c index 3290de61f..203852059 100644 --- a/resource/c_common/ocrandom/src/ocrandom.c +++ b/resource/c_common/ocrandom/src/ocrandom.c @@ -61,6 +61,12 @@ #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; +} + diff --git a/resource/csdk/connectivity/api/cautilinterface.h b/resource/csdk/connectivity/api/cautilinterface.h index 4b90ff8ca..5792160ea 100644 --- a/resource/csdk/connectivity/api/cautilinterface.h +++ b/resource/csdk/connectivity/api/cautilinterface.h @@ -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__ /** diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c index 04dc46e0f..f7e4b16c0 100644 --- a/resource/csdk/connectivity/src/camessagehandler.c +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -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) diff --git a/resource/csdk/connectivity/util/SConscript b/resource/csdk/connectivity/util/SConscript index 9fdaa31e5..975c7b113 100644 --- a/resource/csdk/connectivity/util/SConscript +++ b/resource/csdk/connectivity/util/SConscript @@ -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'), diff --git a/resource/csdk/connectivity/util/inc/caconnectionmanager.h b/resource/csdk/connectivity/util/inc/caconnectionmanager.h index eba0b1f51..16ef0311c 100644 --- a/resource/csdk/connectivity/util/inc/caconnectionmanager.h +++ b/resource/csdk/connectivity/util/inc/caconnectionmanager.h @@ -31,6 +31,7 @@ #include #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" */ diff --git a/resource/csdk/connectivity/util/src/camanager/caconnectionmanager.c b/resource/csdk/connectivity/util/src/camanager/caconnectionmanager.c index d426ac3fd..12e54f365 100644 --- a/resource/csdk/connectivity/util/src/camanager/caconnectionmanager.c +++ b/resource/csdk/connectivity/util/src/camanager/caconnectionmanager.c @@ -33,134 +33,54 @@ #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(); } diff --git a/resource/csdk/connectivity/util/src/camanager/camanagerutil.c b/resource/csdk/connectivity/util/src/camanager/camanagerutil.c index 538d88ad7..b6844fdf6 100644 --- a/resource/csdk/connectivity/util/src/camanager/camanagerutil.c +++ b/resource/csdk/connectivity/util/src/camanager/camanagerutil.c @@ -18,11 +18,319 @@ * ******************************************************************/ -#include "logger.h" -#include "cathreadpool.h" -#include "uarraylist.h" -#include "octhread.h" - #include "camanagerutil.h" +#include +#include +#include + +#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; +} diff --git a/resource/csdk/connectivity/util/src/camanager/camanagerutil.h b/resource/csdk/connectivity/util/src/camanager/camanagerutil.h index bf0191ac7..6aff40faf 100644 --- a/resource/csdk/connectivity/util/src/camanager/camanagerutil.h +++ b/resource/csdk/connectivity/util/src/camanager/camanagerutil.h @@ -26,16 +26,117 @@ #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" */ diff --git a/resource/csdk/connectivity/util/src/camanager/camessagearbiter.c b/resource/csdk/connectivity/util/src/camanager/camessagearbiter.c index 061170b0b..741ceff46 100644 --- a/resource/csdk/connectivity/util/src/camanager/camessagearbiter.c +++ b/resource/csdk/connectivity/util/src/camanager/camessagearbiter.c @@ -18,8 +18,245 @@ * ******************************************************************/ -#include "logger.h" -#include "cathreadpool.h" +#include +#include +#include + +#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; +} diff --git a/resource/csdk/connectivity/util/src/camanager/camessagearbiter.h b/resource/csdk/connectivity/util/src/camanager/camessagearbiter.h index 238362d51..44ea9b038 100644 --- a/resource/csdk/connectivity/util/src/camanager/camessagearbiter.h +++ b/resource/csdk/connectivity/util/src/camanager/camessagearbiter.h @@ -26,15 +26,45 @@ #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" */ diff --git a/resource/csdk/connectivity/util/src/camanager/capolicymanager.c b/resource/csdk/connectivity/util/src/camanager/capolicymanager.c index d9a4c9e25..cbefc58f8 100644 --- a/resource/csdk/connectivity/util/src/camanager/capolicymanager.c +++ b/resource/csdk/connectivity/util/src/camanager/capolicymanager.c @@ -33,32 +33,75 @@ #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; + } } diff --git a/resource/csdk/connectivity/util/src/camanager/capolicymanager.h b/resource/csdk/connectivity/util/src/camanager/capolicymanager.h index 9bef0cf52..0e1b3c9b3 100644 --- a/resource/csdk/connectivity/util/src/camanager/capolicymanager.h +++ b/resource/csdk/connectivity/util/src/camanager/capolicymanager.h @@ -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" */ diff --git a/resource/csdk/connectivity/util/src/cautilinterface.c b/resource/csdk/connectivity/util/src/cautilinterface.c index afcf64c7e..34cd8a019 100644 --- a/resource/csdk/connectivity/util/src/cautilinterface.c +++ b/resource/csdk/connectivity/util/src/cautilinterface.c @@ -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__ /** diff --git a/resource/csdk/include/octypes.h b/resource/csdk/include/octypes.h index 48d553e76..dcc3e1898 100755 --- a/resource/csdk/include/octypes.h +++ b/resource/csdk/include/octypes.h @@ -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 diff --git a/resource/csdk/stack/SConscript b/resource/csdk/stack/SConscript index 04d99bdb6..7ea0e3def 100644 --- a/resource/csdk/stack/SConscript +++ b/resource/csdk/stack/SConscript @@ -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 index 000000000..5fbc73eb2 --- /dev/null +++ b/resource/csdk/stack/include/internal/occonnectionmanager.h @@ -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 index 000000000..d1416050a --- /dev/null +++ b/resource/csdk/stack/src/occonnectionmanager.c @@ -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 +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#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; +} diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 3cdaecb6e..70fecf1c3 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -64,6 +64,10 @@ #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; } diff --git a/resource/include/CAManager.h b/resource/include/CAManager.h index ba758c066..f5ac8a5ab 100644 --- a/resource/include/CAManager.h +++ b/resource/include/CAManager.h @@ -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 } } diff --git a/resource/src/CAManager.cpp b/resource/src/CAManager.cpp index 380b3d7a5..127db0c3a 100644 --- a/resource/src/CAManager.cpp +++ b/resource/src/CAManager.cpp @@ -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 -- 2.34.1