}
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);
}
--- /dev/null
+/*
+ ********************************************************************
+ *
+ * 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;
+ }
+}
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
+}
+
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
/*
* 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.
*/
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
#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
#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)
}
}
-/*
- * 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()
{
return;
}
-
+
uint32_t result =0;
uint8_t i;
for (i=32; i--;)
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;
}
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;
+}
+
#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.
typedef struct
{
CATransportBTFlags_t bleFlags;
- CMConfigureInfo_t cmInfo;
+ CAConnectUserPref_t connUserPref;
} CAUtilConfig_t;
/**
*/
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__
/**
#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
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)
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')
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'),
#include <coap/coap.h>
#include "cathreadpool.h"
#include "octhread.h"
+#include "logger.h"
#include "uarraylist.h"
#include "cacommon.h"
#include "caprotocolmessage.h"
#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" */
#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();
}
*
******************************************************************/
-#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;
+}
#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" */
*
******************************************************************/
-#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;
+}
#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" */
#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;
+ }
}
#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" */
#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,
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__
/**
} 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
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++
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')
--- /dev/null
+/******************************************************************
+ *
+ * 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);
--- /dev/null
+/******************************************************************
+ *
+ * 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;
+}
#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
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
}
}
}
#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)
{
// 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;
}
*/
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
}
}
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