help_vars.Add(BoolVariable('WITH_RA', 'Build with Remote Access module', False))
help_vars.Add(BoolVariable('WITH_TCP', 'Build with TCP adapter', False))
+help_vars.Add(ListVariable('WITH_MQ', 'Build with MQ publisher/broker', 'OFF', ['OFF', 'SUB', 'PUB', 'BROKER']))
help_vars.Add(EnumVariable('WITH_RD', 'Build including Resource Directory', '0', allowed_values=('0', '1')))
-help_vars.Add(BoolVariable('WITH_CLOUD', 'Build including Cloud client sample', False))
+help_vars.Add(BoolVariable('WITH_CLOUD', 'Build including Cloud Connector and Cloud Client sample', False))
help_vars.Add(BoolVariable('SIMULATOR', 'Build with simulator module', False))
<artifactId>CloudResourceDirectory</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.17</version>
- </dependency>
</dependencies>
<build>
<groupId>org.iotivity.cloud</groupId>
<artifactId>CloudStack</artifactId>
<version>0.0.1-SNAPSHOT</version>
-
+
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.test.skip>true</maven.test.skip>
</properties>
-
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>jackson-dataformat-cbor</artifactId>
<version>2.7.4</version>
</dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+ </dependency>
</dependencies>
-
<build>
<plugins>
<plugin>
</plugin>
</plugins>
</build>
-
</project>
\ No newline at end of file
if target_os in ['darwin', 'ios']:
examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+if env.get('WITH_CLOUD'):
+ examples_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD'])
+
######################################################################
# Source files and Targets
######################################################################
if target_os in ['tizen', 'linux']:
env.ParseConfig("pkg-config --cflags --libs uuid")
-env.PrependUnique(LIBS = ['c_common'])
-
common_env = env.Clone()
common_env.AppendUnique(LIBPATH = [os.path.join(env.get('BUILD_DIR'), 'resource')])
######################################################################
# Build flags
######################################################################
+common_conf = Configure(common_env)
+if common_conf.CheckFunc('QueryPerformanceFrequency'):
+ common_env.AppendUnique(CPPDEFINES = ['HAVE_QUERYPERFORMANCEFREQUENCY'])
+common_env = common_conf.Finish()
######################################################################
# Source files and Targets
common_env.InstallTarget(commonlib, 'c_common')
common_env.UserInstallTargetLib(commonlib, 'c_common')
common_env.UserInstallTargetHeader('platform_features.h', 'resource', 'platform_features.h')
+
+env.PrependUnique(LIBS = ['c_common'])
* @param precision based on this parameter, current time is returned in milliseconds or
* microseconds
*
+ * @warning This function may be sensitive to system time changes on some platforms.
+ *
* @note
* On Arduino platform:
* if the time precision is in milliseconds then the function will overflow
#include <stddef.h> // For NULL
-#if defined(_WIN32)
+#if defined(HAVE_WINDOWS_H)
# include <windows.h>
#elif !defined(WITH_ARDUINO)
# if _POSIX_TIMERS > 0
#ifdef WITH_ARDUINO
currentTime = (TIME_IN_MS == precision) ? millis() : micros();
-#elif defined(_WIN32)
- FILETIME fileTime;
+#elif defined(HAVE_QUERYPERFORMANCEFREQUENCY)
+ static LARGE_INTEGER frequency = {0};
- GetSystemTimePreciseAsFileTime(&fileTime);
-
- // fileTime should now be a QWORD hundred-nanoseconds time since 1601
+ if (!frequency.QuadPart)
+ {
+ QueryPerformanceFrequency(&frequency);
+ }
- // MSDN recommends using ULARGE_INTEGER as an intermediate representation for math.
- ULARGE_INTEGER time = { .LowPart = fileTime.dwLowDateTime,
- .HighPart = fileTime.dwHighDateTime };
+ LARGE_INTEGER count = {0};
+ QueryPerformanceCounter(&count);
currentTime =
(TIME_IN_MS == precision)
- ? time.QuadPart / (HNS_PER_US * US_PER_MS)
- : time.QuadPart / (HNS_PER_US);
+ ? count.QuadPart / (frequency.QuadPart / MS_PER_SEC)
+ : count.QuadPart / (frequency.QuadPart / US_PER_SEC);
#else
# if _POSIX_TIMERS > 0
# if defined(CLOCK_MONOTONIC_COARSE)
with_ra = env.get('WITH_RA')
with_ra_ibb = env.get('WITH_RA_IBB')
with_tcp = env.get('WITH_TCP')
+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 target_os == 'arduino':
'security/provisioning/include',
])
+if 'SUB' in with_mq:
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['MQ_SUBSCRIBER', 'WITH_MQ'])
+if 'PUB' in with_mq:
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['MQ_PUBLISHER', 'WITH_MQ'])
+if 'BROKER' in with_mq:
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['MQ_BROKER', 'WITH_MQ'])
+
if target_os not in ['arduino', 'windows']:
liboctbstack_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
build_sample = env.get('BUILD_SAMPLE')
with_ra = env.get('WITH_RA')
with_tcp = env.get('WITH_TCP')
+with_mq = env.get('WITH_MQ')
print "Given Transport is %s" % transport
print "Given OS is %s" % target_os
print "BUILD_SAMPLE is %s" % build_sample
+print "MQ flag is %s" % with_mq
targets_disallow_multitransport = ['arduino']
else:
env.AppendUnique(CPPDEFINES = ['NO_NFC_ADAPTER'])
+if 'SUB' in with_mq:
+ env.AppendUnique(CPPDEFINES = ['MQ_SUBSCRIBER', 'WITH_MQ'])
+ print "MQ SUB support"
+
+if 'PUB' in with_mq:
+ env.AppendUnique(CPPDEFINES = ['MQ_PUBLISHER', 'WITH_MQ'])
+ print "MQ PUB support"
+
+if 'BROKER' in with_mq:
+ env.AppendUnique(CPPDEFINES = ['MQ_BROKER', 'WITH_MQ'])
+ print "MQ Broker support"
+
env.SConscript('./src/SConscript')
#define MAX_ADDR_STR_SIZE_CA (256)
#else
/*
- * Max Address could be "coap+tcp://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:yyy.yyy.yyy.yyy]:xxxxx"
- * Which is 64, +1 for null terminator => 65
+ * Max Address could be "coaps+tcp://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:yyy.yyy.yyy.yyy]:xxxxx"
+ * Which is 65, +1 for null terminator => 66
* OCDevAddr (defined in OCTypes.h) must be the same
* as CAEndpoint_t (defined here)
*/
-#define MAX_ADDR_STR_SIZE_CA (65)
+#define MAX_ADDR_STR_SIZE_CA (66)
#endif
typedef enum
retVal = CA_WAIT_SUCCESS;
}
#else
- int ret;
- struct timespec abstime;
+ int ret = 0;
+ struct timespec abstime = { .tv_sec = 0 };
#ifdef __ANDROID__
if (camutex_cond_timedwait_relative)
VERIFY_NON_NULL_VOID(host, CA_ADAPTER_UTILS_TAG, "host is null");
VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
- struct addrinfo *addrs;
+ struct addrinfo *addrs = NULL;
struct addrinfo hints = { .ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM,
.ai_flags = AI_NUMERICHOST };
{
char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
- size_t len;
- int level, type, namelen;
- struct sockaddr_storage srcAddr;
+ size_t len = 0;
+ int level = 0;
+ int type = 0;
+ int namelen = 0;
+ struct sockaddr_storage srcAddr = { .ss_family = 0 };
unsigned char *pktinfo = NULL;
#if !defined(WSA_CMSG_DATA)
struct cmsghdr *cmp = NULL;
}
#endif
struct sockaddr_storage sa = { .ss_family = family };
- socklen_t socklen;
+ socklen_t socklen = 0;
if (family == AF_INET6)
{
(void)cast; // eliminates release warning
(void)fam;
- struct sockaddr_storage sock;
+ struct sockaddr_storage sock = { .ss_family = 0 };
CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
- socklen_t socklen;
+ socklen_t socklen = 0;
if (sock.ss_family == AF_INET6)
{
/** @todo figure out correct usage for ifindex, and sin6_scope_id */
{
CAInterface_t *foundNewInterface = NULL;
#ifdef __linux__
- char buf[4096];
- struct nlmsghdr *nh;
- struct sockaddr_nl sa;
- struct iovec iov = { buf, sizeof (buf) };
- struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 };
+ char buf[4096] = { 0 };
+ struct nlmsghdr *nh = NULL;
+ struct sockaddr_nl sa = { .nl_family = 0 };
+ struct iovec iov = { .iov_base = buf,
+ .iov_len = sizeof (buf) };
+ struct msghdr msg = { .msg_name = (void *)&sa,
+ .msg_namelen = sizeof (sa),
+ .msg_iov = &iov,
+ .msg_iovlen = 1 };
size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
#define TAG "OIC_CA_TCP_SERVER"
/**
- * Server port number for local test.
- */
-#define SERVER_PORT 8000
-
-/**
* Maximum CoAP over TCP header length
* to know the total data length.
*/
}
// #3. set socket length.
- socklen_t socklen;
+ socklen_t socklen = 0;
if (sa.ss_family == AF_INET6)
{
struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sa;
return sock->fd;
}
- socklen_t socklen;
+ socklen_t socklen = 0;
struct sockaddr_storage server = { .ss_family = family };
int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
class CATests : public testing::Test {
protected:
- virtual void SetUp() {
+ virtual void SetUp()
+ {
CAInitialize();
}
CABlockData_t *currData = CACreateNewBlockData(cadata);
EXPECT_TRUE(currData != NULL);
- size_t fullPayload = 0;
- CAPayload_t payload = CAGetPayloadFromBlockDataList(currData->blockDataId,
- &fullPayload);
+ if (currData)
+ {
+ size_t fullPayload = 0;
+ CAPayload_t payload = CAGetPayloadFromBlockDataList(currData->blockDataId,
+ &fullPayload);
- size_t payloadLen = (payload != NULL) ? strlen((const char*) payload) : 0;
- EXPECT_TRUE(fullPayload == payloadLen);
+ size_t payloadLen = (payload != NULL) ? strlen((const char*) payload) : 0;
+ EXPECT_TRUE(fullPayload == payloadLen);
+
+ CARemoveBlockDataFromList(currData->blockDataId);
+ }
- CARemoveBlockDataFromList(currData->blockDataId);
CADestroyDataSet(cadata);
coap_delete_list(options);
coap_delete_pdu(pdu);
CABlockData_t *currData = CACreateNewBlockData(cadata);
EXPECT_TRUE(currData != NULL);
- EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
- COAP_OPTION_BLOCK1));
+ if (currData)
+ {
+ EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
+ COAP_OPTION_BLOCK1));
- EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption1(&pdu, &requestData,
- requestData.payloadSize,
- currData->blockDataId, &options));
+ EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption1(&pdu, &requestData,
+ requestData.payloadSize,
+ currData->blockDataId, &options));
+ }
CADestroyDataSet(cadata);
coap_delete_list(options);
CABlockData_t *currData = CACreateNewBlockData(cadata);
EXPECT_TRUE(currData != NULL);
- EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
- COAP_OPTION_BLOCK1));
+ if (currData)
+ {
+ EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
+ COAP_OPTION_BLOCK1));
- EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption1(&pdu, &responseData,
- responseData.payloadSize,
- currData->blockDataId, &options));
+ EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption1(&pdu, &responseData,
+ responseData.payloadSize,
+ currData->blockDataId, &options));
+ }
CADestroyDataSet(cadata);
coap_delete_list(options);
CABlockData_t *currData = CACreateNewBlockData(cadata);
EXPECT_TRUE(currData != NULL);
- EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
- COAP_OPTION_BLOCK2));
+ if (currData)
+ {
+ EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
+ COAP_OPTION_BLOCK2));
- EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption2(&pdu, &responseData,
- responseData.payloadSize,
- currData->blockDataId, &options));
+ EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption2(&pdu, &responseData,
+ responseData.payloadSize,
+ currData->blockDataId, &options));
+ }
CADestroyDataSet(cadata);
coap_delete_list(options);
CABlockData_t *currData = CACreateNewBlockData(cadata);
EXPECT_TRUE(currData != NULL);
- EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
- COAP_OPTION_BLOCK2));
+ if (currData)
+ {
+ EXPECT_EQ(CA_STATUS_OK, CAUpdateBlockOptionType(currData->blockDataId,
+ COAP_OPTION_BLOCK2));
- EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption2(&pdu, &requestData,
- requestData.payloadSize,
- currData->blockDataId, &options));
+ EXPECT_EQ(CA_STATUS_OK, CAAddBlockOption2(&pdu, &requestData,
+ requestData.payloadSize,
+ currData->blockDataId, &options));
+ }
- CARemoveBlockDataFromList(currData->blockDataId);
CADestroyDataSet(cadata);
coap_delete_list(options);
coap_delete_pdu(pdu);
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
+#ifdef HAVE_ARDUINO_TIME_H
+#include <Time.h>
+#else
#include <time.h>
+#endif
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
OCStackResult AclToCBORPayload(const OicSecAcl_t * acl, uint8_t **outPayload, size_t *size);
/**
+ * This method removes ACE for the subject and resource from the ACL
+ *
+ * @param subject of the ACE
+ * @param resource of the ACE
+ *
+ * @return
+ * ::OC_STACK_RESOURCE_DELETED on success
+ * ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
+ * ::OC_STACK_INVALID_PARAM on invalid parameter
+ */
+OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource);
+
+/**
* This function deletes ACL data.
*
* @param acl instance of @ref OicSecAcl_t structure to be deleted.
*/
OCStackResult UpdateSecureResourceInPS(const char* rsrcName, uint8_t* cborPayload, size_t size);
+/**
+ * This method resets the secure resources according to the reset profile.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult ResetSecureResourceInPS(void);
+
+/**
+ * This method creates the reset profile from the persistent storage.
+ * The reset profile is the copy of the initial state of SVR resources
+ * when secure resources are initiated at first.
+ * In remote reset, the SVR will be reset according to the reset profile.
+ *
+ * @return ::OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult CreateResetProfile(void);
+
#endif //IOTVT_SRM_PSI_H
extern const char * OIC_RSRC_VER_URI;
extern const char * OIC_JSON_VER_NAME;
+//reset profile
+extern const char * OIC_JSON_RESET_PF_NAME;
+
extern const char * OIC_JSON_SUBJECT_NAME;
extern const char * OIC_JSON_SUBJECTID_NAME;
extern const char * OIC_JSON_RESOURCES_NAME;
initAddress();
- char szQueryUri[64] = { '\0'};
+ char szQueryUri[MAX_QUERY_LENGTH] = { '\0'};
OCDoHandle handle;
OCCallbackData cbData;
cbData.cb = getReqCB;
void *input_function(void * /*data*/)
{
char input;
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
OCDoHandle handle;
OCCallbackData cbData;
cbData.cb = discoveryReqCB;
const OCProvisionDev_t* pTargetDev,
OCProvisionResultCB resultCallback);
+/*
+ * Function to sync-up credential and ACL of the target device.
+ * This function will remove credential and ACL of target device from all devices in subnet.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ * If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback);
+
+/*
+ * Function for remote reset
+ * This function will send pstat POST(modify) message to the target device
+ * to change current mode to reset state in order to initiate remote reset.
+ *
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ * If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
+ OCProvisionResultCB resultCallback);
+
#ifdef __cplusplus
}
#endif
#define _30_PROVIS_PAIR_DEVS_ 30
#define _31_PROVIS_CRED_ 31
#define _32_PROVIS_ACL_ 32
-#define _33_PROVIS_DP_ 33
+#define _33_PROVIS_DP_ 33
#define _34_CHECK_LINK_STATUS_ 34
#define _40_UNLINK_PAIR_DEVS_ 40
#define _50_REMOVE_SELEC_DEV_ 50
-#define _60_GET_CRED_ 60
+#define _51_RESET_SELEC_DEV_ 51
+#define _60_GET_CRED_ 60
#define _61_GET_ACL_ 61
#define _99_EXIT_PRVN_CLT_ 99
g_doneCB = true;
}
+static void syncDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Sync Device SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Sync Device FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
static void inputPinCB(char* pin, size_t len)
{
if(!pin || OXM_RANDOM_PIN_SIZE>=len)
return 0;
}
+static int resetDevice(void)
+{
+ // check |own_list| for removing device
+ if (!g_own_list || 1 > g_own_cnt)
+ {
+ printf(" > Owned Device List, to Reset Device, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0;
+ }
+
+ // select device for removing it
+ int dev_num = 0;
+ for ( ; ; )
+ {
+ printf(" > Enter Device Number, for Resetting Device: ");
+ for (int ret = 0; 1 != ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for ( ; 0x20 <= getchar() ; ); // for removing overflow garbages
+ // '0x20 <= code' is character region
+ }
+ if (0 < dev_num && g_own_cnt >= dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ g_doneCB = false;
+ printf(" Resetting Selected Owned Device..\n");
+
+ OCStackResult rst = OCResetDevice((void *) g_ctx, DISCOVERY_TIMEOUT,
+ getDevInst((const OCProvisionDev_t *) g_own_list, dev_num), syncDeviceCB);
+ if (OC_STACK_OK != rst)
+ {
+ OIC_LOG_V(ERROR, TAG, "OCResetDevice API error: %d", rst);
+ return -1;
+ }
+
+ if (waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the removed result
+ printf(" > Reset Selected Owned Device SUCCEEDED\n");
+ printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
+
+ return 0;
+}
+
static OicSecAcl_t* createAcl(const int dev_num)
{
if(0>=dev_num || g_own_cnt<dev_num)
printf("** 40. Unlink Pairwise Things\n\n");
printf("** [E] REMOVE THE SELECTED DEVICE\n");
- printf("** 50. Remove the Selected Device\n\n");
+ printf("** 50. Remove the Selected Device\n");
+ printf("** 51. Reset the Selected Device\n\n");
printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
printf("** 60. Get the Credential resources of the Selected Device\n");
OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
}
break;
+ case _51_RESET_SELEC_DEV_:
+ if(resetDevice())
+ {
+ OIC_LOG(ERROR, TAG, "_51_RESET_SELEC_DEV_: error");
+ }
+ break;
case _60_GET_CRED_:
if(getCred())
{
return res;
}
+/*
+ * Function to reset the target device.
+ * This function will remove credential and ACL of target device from all devices in subnet.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev,
+ OCProvisionResultCB resultCallback)
+{
+ OIC_LOG(INFO, TAG, "IN OCResetDevice");
+ OCStackResult res = OC_STACK_ERROR;
+ if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
+ {
+ OIC_LOG(INFO, TAG, "OCResetDevice : Invalid parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (!resultCallback)
+ {
+ OIC_LOG(INFO, TAG, "OCResetDevice : NULL Callback");
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ // Send DELETE requests to linked devices
+ res = SRPSyncDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
+ if (OC_STACK_CONTINUE == res)
+ {
+ OIC_LOG(DEBUG, TAG, "OCResetDevice : Target device has no linked device except PT.");
+ if(resultCallback)
+ {
+ resultCallback(ctx, 0, NULL, false);
+ }
+ SRPResetDevice(pTargetDev, resultCallback);
+ res = OC_STACK_OK;
+ }
+ else if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to invoke SRPSyncDevice");
+ }
+ OIC_LOG(INFO, TAG, "OUT OCResetDevice");
+ return res;
+}
/**
* Internal Function to update result in link result array.
return ret;
}
+static OCStackResult SendDeleteACLRequest(void* ctx,
+ OCClientResponseHandler respHandler,
+ const OCProvisionDev_t* revokedDev,
+ const OCProvisionDev_t* destDev)
+{
+ OIC_LOG(DEBUG, TAG, "IN SendDeleteACLRequest");
+
+ if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ char *subID = NULL;
+ OCStackResult ret = ConvertUuidToStr(&revokedDev->doxm->deviceID, &subID);
+ if(OC_STACK_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "SendDeleteACLRequest : Failed to canonical UUID encoding");
+ return OC_STACK_ERROR;
+ }
+
+ char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ int snRet = 0;
+ //coaps://0.0.0.0:5684/oic/sec/acl?subjectuuid=(Canonical ENCODED UUID)
+ snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr,
+ destDev->securePort, OIC_RSRC_ACL_URI, OIC_JSON_SUBJECTID_NAME, subID);
+ OICFree(subID);
+ if (snRet < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error (snprintf) %d\n", snRet);
+ return OC_STACK_ERROR;
+ }
+ else if ((size_t)snRet >= sizeof(reqBuf))
+ {
+ OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Truncated (snprintf) %d\n", snRet);
+ return OC_STACK_ERROR;
+ }
+
+ OCCallbackData cbData;
+ memset(&cbData, 0, sizeof(cbData));
+ cbData.context = ctx;
+ cbData.cb = respHandler;
+ cbData.cd = NULL;
+ OIC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
+
+ OIC_LOG(DEBUG, TAG, "Sending remove ACL request to resource server");
+
+ ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
+ &destDev->endpoint, NULL,
+ CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (OC_STACK_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "SendDeleteACLRequest : Error in OCDoResource %d", ret);
+ }
+ OIC_LOG(DEBUG, TAG, "OUT SendDeleteACLRequest");
+
+ return ret;
+}
+
/**
* Callback handler of unlink second device.
*
}
}
+static void registerResultForResetDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
+ OCStackResult stackresult, bool hasError)
+{
+ OIC_LOG_V(INFO, TAG, "Inside registerResultForResetDevice removeData->numOfResults is %zu\n",
+ removeData->numOfResults + 1);
+ if (pLinkedDevId)
+ {
+ memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+ &pLinkedDevId->id, sizeof(pLinkedDevId->id));
+ }
+ else
+ {
+ memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+ 0, sizeof(pLinkedDevId->id) );
+ }
+ removeData->removeRes[(removeData->numOfResults)].res = stackresult;
+ removeData->hasError = hasError;
+ ++(removeData->numOfResults);
+
+ // If we get suffcient result from linked devices, we have to call user callback and do free
+ if (removeData->sizeOfResArray == removeData->numOfResults)
+ {
+ removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
+ removeData->hasError);
+ DeleteRemoveData_t(removeData);
+ }
+}
+
/**
* Callback handler of unlink first device.
*
return OC_STACK_DELETE_TRANSACTION;
}
+/**
+ * Callback handler of reset device.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPSyncDeviceCredCB(void *delDevCtx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ //Update the delete credential into delete device context
+ //Save the deleted status in delDevCtx
+ (void)handle;
+ OIC_LOG_V(INFO, TAG, "Inside SRPSyncDeviceCredCB.");
+ VERIFY_NON_NULL(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ OCStackResult res = OC_STACK_ERROR;
+
+ RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
+ OCProvisionDev_t * pTargetDev = PMCloneOCProvisionDev(removeData->revokeTargetDev);
+ OCProvisionResultCB resultCallback = removeData->resultCallback;
+ if (clientResponse)
+ {
+ OicUuid_t revDevUuid = {.id={0}};
+ if(UUID_LENGTH == clientResponse->identity.id_length)
+ {
+ memcpy(revDevUuid.id, clientResponse->identity.id, sizeof(revDevUuid.id));
+ if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+ {
+ res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID, &revDevUuid);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
+ registerResultForResetDevice(removeData, &revDevUuid,
+ OC_STACK_INCONSISTENT_DB, true);
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ registerResultForResetDevice(removeData, &revDevUuid,
+ OC_STACK_RESOURCE_DELETED, false);
+ }
+ else
+ {
+ registerResultForResetDevice(removeData, &revDevUuid,
+ clientResponse->result, false);
+ OIC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
+ }
+ }
+ else
+ {
+ OIC_LOG_V(WARNING, TAG, "Incorrect length of device UUID was sent from %s:%d",
+ clientResponse->devAddr.addr, clientResponse->devAddr.port);
+
+ if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+ {
+ /**
+ * Since server's credential was deleted,
+ * register result as OC_STACK_INCONSISTENT_DB with NULL UUID.
+ */
+ OIC_LOG_V(ERROR, TAG, "But server's credential was deleted.");
+ registerResultForResetDevice(removeData, NULL, OC_STACK_INCONSISTENT_DB, true);
+ }
+ else
+ {
+ registerResultForResetDevice(removeData, NULL, clientResponse->result, true);
+ }
+ }
+ }
+ else
+ {
+ registerResultForResetDevice(removeData, NULL, OC_STACK_ERROR, true);
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice received Null clientResponse");
+ }
+
+ SRPResetDevice(pTargetDev, resultCallback);
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of reset device sync-up
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPSyncDeviceACLCB(void *ctx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of device remote reset.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPResetDeviceCB(void *ctx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ OIC_LOG(DEBUG, TAG, "IN SRPResetDeviceCB");
+ if(OC_STACK_OK == clientResponse->result)
+ {
+ OIC_LOG(DEBUG, TAG, "Change Target Device Pstat Cm SUCCEEDED");
+ }
+
+ // Delete Cred and ACL related to the target device.
+ const OicSecCred_t *cred = NULL;
+ OCProvisionDev_t * pTargetDev = (OCProvisionDev_t *)ctx;
+ cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
+ if (cred == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to get credential of target device.");
+ goto error;
+ }
+
+ OCStackResult res = RemoveCredential(&cred->subject);
+ if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
+ {
+ OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove credential.");
+ goto error;
+ }
+
+ res = RemoveACE(&cred->subject, NULL);
+ if (res != OC_STACK_RESOURCE_DELETED && res != OC_STACK_NO_RESOURCE)
+ {
+ OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to remove ACL.");
+ goto error;
+ }
+ if (OC_STACK_OK != PDMDeleteDevice(&pTargetDev->doxm->deviceID))
+ {
+ OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to delete device from PDM");
+ }
+
+ //Close the DTLS session of the reset device.
+ CAEndpoint_t* endpoint = (CAEndpoint_t *)&clientResponse->devAddr;
+ CAResult_t caResult = CACloseDtlsSession(endpoint);
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG_V(WARNING, TAG, "OCResetDevice : Failed to close DTLS session : %d", caResult);
+ }
+
+ /**
+ * If there is no linked device, PM does not send any request.
+ * So we should directly invoke the result callback to inform the result of OCResetDevice.
+ */
+ if(OC_STACK_NO_RESOURCE == res)
+ {
+ res = OC_STACK_OK;
+ }
+
+error:
+ OICFree(pTargetDev);
+ return OC_STACK_DELETE_TRANSACTION;
+
+}
+
static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
OCProvisionDev_t* pOwnedDevList,
OCUuidList_t* pLinkedUuidList,
return res;
}
+/*
+ * Function to sync-up credential and ACL of the target device.
+ * This function will remove credential and ACL of target device from all devices in subnet.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ * If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPSyncDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
+{
+ OIC_LOG(INFO, TAG, "IN SRPSyncDevice");
+ if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
+ {
+ OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (!resultCallback)
+ {
+ OIC_LOG(INFO, TAG, "SRPSyncDevice : NULL Callback");
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ // Declare variables in here to handle error cases with goto statement.
+ OCProvisionDev_t* pOwnedDevList = NULL;
+ OCProvisionDev_t* pLinkedDevList = NULL;
+ RemoveData_t* removeData = NULL;
+
+ //1. Find all devices that has a credential of the revoked device
+ OCUuidList_t* pLinkedUuidList = NULL;
+ size_t numOfDevices = 0;
+ OCStackResult res = OC_STACK_ERROR;
+ res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to get linked devices information");
+ return res;
+ }
+ // if there is no related device, we can skip further process.
+ if (0 == numOfDevices)
+ {
+ OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No linked device found.");
+ res = OC_STACK_CONTINUE;
+ goto error;
+ }
+
+ //2. Find owned device from the network
+ res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to PMDeviceDiscovery");
+ goto error;
+ }
+
+ //3. Make a list of devices to send DELETE credential request
+ // by comparing owned devices from provisioning database with mutlicast discovery result.
+ size_t numOfLinkedDev = 0;
+ res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
+ &pLinkedDevList, &numOfLinkedDev);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : GetListofDevToReqDeleteCred() failed");
+ goto error;
+ }
+ if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
+ { // So we don't have to send request message.
+ OIC_LOG(DEBUG, TAG, "SRPSyncDevice : No alived & linked device found.");
+ res = OC_STACK_CONTINUE;
+ goto error;
+ }
+
+ // 4. Prepare RemoveData Context data.
+ removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
+ if (!removeData)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to memory allocation");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
+ if (!removeData->revokeTargetDev)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : PMCloneOCProvisionDev Failed");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->removeRes =
+ (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
+ if (!removeData->removeRes)
+ {
+ OIC_LOG(ERROR, TAG, "SRPSyncDevice : Failed to allocate memory");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->ctx = ctx;
+ removeData->linkedDevList = pLinkedDevList;
+ removeData->resultCallback = resultCallback;
+ removeData->numOfResults = 0;
+ removeData->sizeOfResArray = numOfLinkedDev;
+ removeData->hasError = false;
+
+ // 5. Send DELETE credential request to linked devices.
+ OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+ OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */
+ LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
+ {
+ res = SendDeleteACLRequest((void*)removeData, &SRPSyncDeviceACLCB,
+ removeData->revokeTargetDev, curDev);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE ACL request to\
+ %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+ goto error;
+ }
+ res = SendDeleteCredentialRequest((void*)removeData, &SRPSyncDeviceCredCB,
+ removeData->revokeTargetDev, curDev);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "SRPSyncDevice : Fail to send the DELETE credential request to\
+ %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+ totalRes = OC_STACK_ERROR;
+ }
+ else
+ {
+ totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
+ }
+ }
+
+ PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
+ PMDeleteDeviceList(pOwnedDevList);
+ OIC_LOG(INFO, TAG, "OUT SRPSyncDevice");
+
+ return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
+
+error:
+ PDMDestoryOicUuidLinkList(pLinkedUuidList);
+ PMDeleteDeviceList(pOwnedDevList);
+ PMDeleteDeviceList(pLinkedDevList);
+ if (removeData)
+ {
+ OICFree(removeData->revokeTargetDev);
+ OICFree(removeData->removeRes);
+ OICFree(removeData);
+ }
+ OIC_LOG(INFO, TAG, "OUT ERROR case SRPSyncDevice");
+ return res;
+}
+
+/*
+ * Function for remote reset
+ * This function will send pstat PUT message to the target device to initiate remote reset.
+ *
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ * If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
+ OCProvisionResultCB resultCallback)
+{
+ OIC_LOG(INFO, TAG, "IN SRPResetDevice");
+ if (!pTargetDev)
+ {
+ OIC_LOG(INFO, TAG, "SRPResetDevice : NULL parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (!resultCallback)
+ {
+ OIC_LOG(INFO, TAG, "SRPResetDevice : NULL Callback");
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ OCStackResult res = OC_STACK_ERROR;
+ OicSecPstat_t * pstat = (OicSecPstat_t *) OICCalloc(1, sizeof(OicSecPstat_t));
+ if (!pstat)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pstat->cm = (OicSecDpm_t) 1;
+ pstat->isOp = 0;
+ memcpy(pstat->deviceID.id, pTargetDev->doxm->deviceID.id, sizeof(OicUuid_t));
+ pstat->tm = (OicSecDpm_t) 2;
+ pstat->om = (OicSecDpom_t) 0;
+ pstat->smLen = 1;
+ pstat->sm = (OicSecDpom_t *) OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
+ if (NULL == pstat->sm)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+ OICFree(pstat);
+ return OC_STACK_NO_MEMORY;
+ }
+ pstat->sm[0] = (OicSecDpom_t) 3;
+
+ OCSecurityPayload * secPayload = (OCSecurityPayload *) OICCalloc(1, sizeof(OCSecurityPayload));
+ if (!secPayload)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to allocate memory");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+
+ if (OC_STACK_OK != PstatToCBORPayload(pstat, &(secPayload->securityData),
+ &(secPayload->payloadSize)))
+ {
+ OCPayloadDestroy((OCPayload *) secPayload);
+ OIC_LOG(ERROR, TAG, "Failed to PstatToCBORPayload");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+ OIC_LOG(DEBUG, TAG, "Created payload for pstat set");
+ OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if (!PMGenerateQuery(true,
+ pTargetDev->endpoint.addr,
+ pTargetDev->securePort,
+ pTargetDev->connType,
+ query, sizeof(query), OIC_RSRC_PSTAT_URI))
+ {
+ OIC_LOG(ERROR, TAG, "SRPResetDevice : Failed to generate query");
+ OCPayloadDestroy((OCPayload *) secPayload);
+ res = OC_STACK_ERROR;
+ goto error;
+ }
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCProvisionDev_t * targetDev = PMCloneOCProvisionDev(pTargetDev);
+ OCCallbackData cbData = { .context = NULL, .cb = NULL, .cd = NULL };
+ cbData.cb = &SRPResetDeviceCB;
+ cbData.context = (void *) targetDev;
+ cbData.cd = NULL;
+ OCMethod method = OC_REST_POST;
+ OCDoHandle handle = NULL;
+ OIC_LOG(DEBUG, TAG, "Sending PSTAT info to resource server");
+ res = OCDoResource(&handle, method, query,
+ &targetDev->endpoint, (OCPayload *)secPayload,
+ targetDev->connType, OC_LOW_QOS, &cbData, NULL, 0);\
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+error:
+ OICFree(pstat->sm);
+ OICFree(pstat);
+ OIC_LOG(INFO, TAG, "OUT SRPResetDevice");
+ return res;
+}
+
/**
* Internal Function to store results in result array during GetCredResourceCB.
*/
* ::OC_STACK_NO_RESOURCE on failure to find the appropriate ACE
* ::OC_STACK_INVALID_PARAM on invalid parameter
*/
-static OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
+OCStackResult RemoveACE(const OicUuid_t * subject, const char * resource)
{
OIC_LOG(DEBUG, TAG, "IN RemoveACE");
#include "secureresourcemanager.h"
#include "srmresourcestrings.h"
#include "srmutility.h"
+#include "pstatresource.h"
+#include "doxmresource.h"
#define TAG "SRM-PSI"
uint8_t *svcCbor = NULL;
uint8_t *credCbor = NULL;
uint8_t *pconfCbor = NULL;
+ uint8_t *resetPfCbor = NULL;
int64_t cborEncoderResult = CborNoError;
OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
size_t svcCborLen = 0;
size_t credCborLen = 0;
size_t pconfCborLen = 0;
+ size_t resetPfCborLen = 0;
// Gets each secure virtual resource from persistent storage
// this local scoping intended, for destroying large cbor instances after use
cborFindResult = cbor_value_dup_byte_string(&curVal, &pconfCbor, &pconfCborLen, NULL);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PCONF Name Value.");
}
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
+ }
}
// Updates the added |psPayload| with the existing secure virtual resource(s)
// this local scoping intended, for destroying large cbor instances after use
{
size_t size = aclCborLen + pstatCborLen + doxmCborLen + amaclCborLen
- + svcCborLen + credCborLen + pconfCborLen + psSize + 255;
+ + svcCborLen + credCborLen + pconfCborLen + resetPfCborLen
+ + psSize + 255;
// This added '255' is arbitrary value that is added to cover the name of the resource, map addition and ending
outPayload = (uint8_t *) OICCalloc(1, size);
cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pconfCbor, pconfCborLen);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pconf Value.");
}
+ if (strcmp(OIC_JSON_RESET_PF_NAME, rsrcName) && resetPfCborLen)
+ {
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+ }
cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
if (outPayload && outSize)
{
- OIC_LOG_V(DEBUG, TAG, "Writting in the file: %zu", outSize);
+ OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
if (ps)
{
OICFree(svcCbor);
OICFree(credCbor);
OICFree(pconfCbor);
+ OICFree(resetPfCbor);
+ return ret;
+}
+
+/**
+ * Resets the Secure Virtual Resource(s).
+ * This function reads the Reset Profile
+ * and resets the secure virtual resources accordingly.
+ *
+ * @return OCStackResult - result of updating Secure Virtual Resource(s)
+ */
+OCStackResult ResetSecureResourceInPS(void)
+{
+ OIC_LOG(DEBUG, TAG, "ResetSecureResourceInPS IN");
+
+ size_t dbSize = 0;
+ size_t outSize = 0;
+ uint8_t *dbData = NULL;
+ uint8_t *outPayload = NULL;
+
+ uint8_t *aclCbor = NULL;
+ uint8_t *pstatCbor = NULL;
+ uint8_t *doxmCbor = NULL;
+ uint8_t *resetPfCbor = NULL;
+
+ int64_t cborEncoderResult = CborNoError;
+ OCStackResult ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
+
+ if(dbData && dbSize)
+ {
+ size_t aclCborLen = 0;
+ size_t pstatCborLen = 0;
+ size_t doxmCborLen = 0;
+ size_t resetPfCborLen = 0;
+
+ // Gets the reset profile from persistent storage
+ {
+ CborParser parser; // will be initialized in |cbor_parser_init|
+ CborValue cbor; // will be initialized in |cbor_parser_init|
+ cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
+ CborValue curVal = {0};
+ CborError cborFindResult = CborNoError;
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_RESET_PF_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &resetPfCbor, &resetPfCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Reset Profile Name Value.");
+ }
+ }
+
+ // Gets each secure virtual resource from the reset profile
+ {
+ CborParser parser; // will be initialized in |cbor_parser_init|
+ CborValue cbor; // will be initialized in |cbor_parser_init|
+ cbor_parser_init(resetPfCbor, resetPfCborLen, 0, &parser, &cbor);
+ CborValue curVal = {0};
+ CborError cborFindResult = CborNoError;
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
+ }
+ }
+
+ {
+ size_t size = aclCborLen + pstatCborLen + doxmCborLen + resetPfCborLen + 255;
+ // This added '255' is arbitrary value added to cover the name of the resource, map addition, and ending
+
+ outPayload = (uint8_t *) OICCalloc(1, size);
+ VERIFY_NON_NULL(TAG, outPayload, ERROR);
+ CborEncoder encoder;
+ cbor_encoder_init(&encoder, outPayload, size, 0);
+ CborEncoder secRsrc;
+ cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value.");
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_RESET_PF_NAME, strlen(OIC_JSON_RESET_PF_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, resetPfCbor, resetPfCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Reset Profile Value.");
+
+ cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
+ outSize = encoder.ptr - outPayload;
+ }
+
+ if (outPayload && outSize)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Writing in the file: %zu", outSize);
+ OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
+ if (ps)
+ {
+ FILE *fp = ps->open(SVR_DB_DAT_FILE_NAME, "wb");
+ if (fp)
+ {
+ size_t numberItems = ps->write(outPayload, 1, outSize, fp);
+ if (outSize == numberItems)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Written %zu bytes into SVR database file", outSize);
+ ret= OC_STACK_OK;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed writing %zu in the database", numberItems);
+ }
+ ps->close(fp);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "File open failed.");
+ }
+
+ }
+ }
+ }
+
+ SRMDeInitSecureResources();
+ InitSecureResources();
+ OIC_LOG(DEBUG, TAG, "ResetSecureResourceINPS OUT");
+
+exit:
+ OICFree(dbData);
+ OICFree(outPayload);
+ OICFree(aclCbor);
+ OICFree(pstatCbor);
+ OICFree(doxmCbor);
+ OICFree(resetPfCbor);
+}
+
+/**
+ * Creates Reset Profile from the initial secure virtual resources.
+ * This function copies the secure resources
+ * and creates the Reset Profile in the Persistent Storage.
+ * Device ID in doxm and pstat are left empty as it will be renewed after reset.
+ *
+ * @return OCStackResult - result of updating Secure Virtual Resource(s)
+ */
+OCStackResult CreateResetProfile(void)
+{
+ OIC_LOG(DEBUG, TAG, "CreateResetProfile IN");
+
+ size_t dbSize = 0;
+ uint8_t *dbData = NULL;
+
+ uint8_t *aclCbor = NULL;
+ uint8_t *pstatCbor = NULL;
+ uint8_t *doxmCbor = NULL;
+ uint8_t *resetPfCbor = NULL;
+
+ OCStackResult ret = OC_STACK_ERROR;
+ int64_t cborEncoderResult = CborNoError;
+ ret = GetSecureVirtualDatabaseFromPS(NULL, &dbData, &dbSize);
+ if (dbData && dbSize)
+ {
+ size_t aclCborLen = 0;
+ size_t pstatCborLen = 0;
+ size_t doxmCborLen = 0;
+ size_t resetPfCborLen = 0;
+
+ {
+ CborParser parser;
+ CborValue cbor;
+ cbor_parser_init(dbData, dbSize, 0, &parser, &cbor);
+ CborValue curVal = {0};
+ CborError cborFindResult = CborNoError;
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_ACL_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &aclCbor, &aclCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ACL Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_PSTAT_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &pstatCbor, &pstatCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PSTAT Name Value.");
+ }
+ cborFindResult = cbor_value_map_find_value(&cbor, OIC_JSON_DOXM_NAME, &curVal);
+ if (CborNoError == cborFindResult && cbor_value_is_byte_string(&curVal))
+ {
+ cborFindResult = cbor_value_dup_byte_string(&curVal, &doxmCbor, &doxmCborLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding DOXM Name Value.");
+ }
+ }
+
+ // Set the Device ID in doxm and pstat to empty
+ if (pstatCbor)
+ {
+ OicSecPstat_t *pstat = NULL;
+ ret = CBORPayloadToPstat(pstatCbor, pstatCborLen, &pstat);
+ OICFree(pstatCbor);
+ pstatCbor = NULL;
+ pstatCborLen = 0;
+
+ OicUuid_t emptyUuid = {.id = {0} };
+ memcpy(&pstat->deviceID, &emptyUuid, sizeof(OicUuid_t));
+ memcpy(&pstat->rownerID, &emptyUuid, sizeof(OicUuid_t));
+
+ ret = PstatToCBORPayload(pstat, &pstatCbor, &pstatCborLen);
+ OICFree(pstat);
+ }
+ if (doxmCbor)
+ {
+ OicSecDoxm_t *doxm = NULL;
+ ret = CBORPayloadToDoxm(doxmCbor, doxmCborLen, &doxm);
+ OICFree(doxmCbor);
+ doxmCbor = NULL;
+ doxmCborLen = 0;
+
+ OicUuid_t emptyUuid = {.id = {0} };
+ memcpy(&doxm->deviceID, &emptyUuid, sizeof(OicUuid_t));
+ memcpy(&doxm->rownerID, &emptyUuid, sizeof(OicUuid_t));
+
+ ret = DoxmToCBORPayload(doxm, &doxmCbor, &doxmCborLen);
+ OICFree(doxm);
+ }
+
+ {
+ size_t size = aclCborLen + pstatCborLen + doxmCborLen + 255;
+ resetPfCbor = (uint8_t *) OICCalloc(1, size);
+ VERIFY_NON_NULL(TAG, resetPfCbor, ERROR);
+ CborEncoder encoder; // will be initialized in |cbor_parser_init|
+ cbor_encoder_init(&encoder, resetPfCbor, size, 0);
+ CborEncoder secRsrc; // will be initialized in |cbor_encoder_create_map|
+ cborEncoderResult |= cbor_encoder_create_map(&encoder, &secRsrc, CborIndefiniteLength);
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, aclCbor, aclCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, pstatCbor, pstatCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
+
+ cborEncoderResult |= cbor_encode_text_string(&secRsrc, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Name.");
+ cborEncoderResult |= cbor_encode_byte_string(&secRsrc, doxmCbor, doxmCborLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Doxm Value.");
+
+ cborEncoderResult |= cbor_encoder_close_container(&encoder, &secRsrc);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Array.");
+ resetPfCborLen = encoder.ptr - resetPfCbor;
+ }
+
+ UpdateSecureResourceInPS(OIC_JSON_RESET_PF_NAME, resetPfCbor, resetPfCborLen);
+
+ }
+ OIC_LOG(DEBUG, TAG, "CreateResetProfile OUT");
+
+exit:
+ OICFree(dbData);
+ OICFree(aclCbor);
+ OICFree(pstatCbor);
+ OICFree(doxmCbor);
+ OICFree(resetPfCbor);
return ret;
}
+
VERIFY_NON_NULL(TAG, pstat, ERROR);
if (OC_STACK_OK == ret)
{
- if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
+ if (true == (pstat->cm & RESET) && false == pstat->isOp)
+ {
+ gPstat->cm = pstat->cm;
+ OIC_LOG(INFO, TAG, "State changed to Ready for Reset");
+ }
+ else if (false == (pstat->cm & TAKE_OWNER) && false == pstat->isOp)
{
gPstat->cm = pstat->cm;
OIC_LOG (INFO, TAG, "State changed to Ready for Provisioning");
{
ehRet = OC_EH_OK;
}
+ if (true == (pstat->cm & RESET))
+ {
+ if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
+ {
+ ehRet = OC_EH_ERROR;
+ OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
+ DeletePstatBinData(pstat);
+ return ehRet;
+ }
+ ret = ResetSecureResourceInPS();
+ if (OC_STACK_OK == ret)
+ {
+ ehRet = OC_EH_OK;
+ }
+ DeletePstatBinData(pstat);
+ return ehRet;
+ }
}
}
exit:
const char * OIC_RSRC_VER_URI = "/oic/sec/ver";
const char * OIC_JSON_VER_NAME = "ver";
+//reset profile
+const char * OIC_JSON_RESET_PF_NAME = "resetpf";
+
const char * OIC_JSON_SUBJECT_NAME = "subject";
const char * OIC_JSON_RESOURCES_NAME = "resources";
const char * OIC_JSON_AMSS_NAME = "amss";
OC_PRESENCE,
#endif
+#ifdef MQ_BROKER
+ /** "/oic/ps" .*/
+ OC_MQ_BROKER_URI,
+#endif
+
/** Max items in the list */
OC_MAX_VIRTUAL_RESOURCES //<s Max items in the list
+
} OCVirtualResources;
/**
* Maximum length of the query supported by client/server while processing
* REST requests/responses.
*/
-#define MAX_QUERY_LENGTH (64)
+#define MAX_QUERY_LENGTH (256)
/**
* Maximum length of the Manufacturer name supported by the server
* Maximum number of vendor specific header options an application can set or receive
* in PDU
*/
-#define MAX_HEADER_OPTIONS (2)
+#define MAX_HEADER_OPTIONS (100)
/**
* Maximum Length of the vendor specific header option
/** Gateway URI.*/
#define OC_RSRVD_GATEWAY_URI "/oic/gateway"
#endif
+
+#ifdef WITH_MQ
+/** MQ Broker URI.*/
+#define OC_RSRVD_WELL_KNOWN_MQ_URI "/.well-known/ocf/ps"
+#endif
+
#ifdef WITH_PRESENCE
/** Presence URI through which the OIC devices advertise their presence.*/
#define OC_RSRVD_PRESENCE_URI "/oic/ad"
+/** Presence URI through which the OCF devices advertise their device presence.*/
+#define OCF_RSRVD_DEVICE_PRESENCE_URI "/.well-known/ocf/prs"
+
/** Sets the default time to live (TTL) for presence.*/
#define OC_DEFAULT_PRESENCE_TTL_SECONDS (60)
/** To represent resource type with RES.*/
#define OC_RSRVD_RESOURCE_TYPE_RES "oic.wk.res"
+#ifdef WITH_MQ
+/** To represent content type with MQ Broker.*/
+#define OC_RSRVD_RESOURCE_TYPE_MQ_BROKER "ocf.wk.ps"
+
+/** To represent content type with MQ Topic.*/
+#define OC_RSRVD_RESOURCE_TYPE_MQ_TOPIC "ocf.wk.ps.topic"
+#endif
+
/** To represent interface.*/
#define OC_RSRVD_INTERFACE "if"
#define MAX_ADDR_STR_SIZE (256)
#else
/** Max Address could be
- * "coap+tcp://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:yyy.yyy.yyy.yyy]:xxxxx"
+ * "coaps+tcp://[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:yyy.yyy.yyy.yyy]:xxxxx"
* +1 for null terminator.
*/
-#define MAX_ADDR_STR_SIZE (65)
+#define MAX_ADDR_STR_SIZE (66)
#endif
/** Length of MAC address */
/** To represent resource type with Publish RD.*/
#define OC_RSRVD_RESOURCE_TYPE_RDPUBLISH "oic.wk.rdpub"
+/** Cloud Account */
+
+/** Account URI.*/
+#define OC_RSRVD_ACCOUNT_URI "/.well-known/ocf/account"
+
+/** Account session URI.*/
+#define OC_RSRVD_ACCOUNT_SESSION_URI "/.well-known/ocf/account/session"
+
+/** Account token refresh URI.*/
+#define OC_RSRVD_ACCOUNT_TOKEN_REFRESH_URI "/.well-known/ocf/account/tokenrefresh"
+
+/** Defines auth provider. */
+#define OC_RSRVD_AUTHPROVIDER "authprovider"
+
+/** Defines auth code. */
+#define OC_RSRVD_AUTHCODE "authcode"
+
+/** Defines session. */
+#define OC_RSRVD_ACCESS_TOKEN "accesstoken"
+
+/** Defines status. */
+#define OC_RSRVD_STATUS "status"
+
+/** Defines grant type. */
+#define OC_RSRVD_GRANT_TYPE "granttype"
+
+/** Defines refresh token. */
+#define OC_RSRVD_REFRESH_TOKEN "refreshtoken"
+
+/** To represent grant type with refresh token. */
+#define OC_RSRVD_GRANT_TYPE_REFRESH_TOKEN "refresh_token"
+
/**
* Mark a parameter as unused. Used to prevent unused variable compiler warnings.
* Used in three cases:
* if discovery request contains an explicit querystring.
* Ex: GET /oic/res?rt=oic.sec.acl */
OC_EXPLICIT_DISCOVERABLE = (1 << 5)
+
+#ifdef WITH_MQ
+ /** When this bit is set, the resource is allowed to be published */
+ ,OC_MQ_PUBLISHER = (1 << 6)
+#endif
+
+#ifdef MQ_BROKER
+ /** When this bit is set, the resource is allowed to be notified as MQ broker.*/
+ ,OC_MQ_BROKER = (1 << 7)
+#endif
} OCResourceProperty;
/**
OC_OBSERVE_DEREGISTER = 1,
/** Others. */
- OC_OBSERVE_NO_OPTION = 2
+ OC_OBSERVE_NO_OPTION = 2,
+
+//#ifdef WITH_MQ
+ OC_MQ_SUBSCRIBER = 3,
+
+ OC_MQ_UNSUBSCRIBER = 4,
+//#endif
+
} OCObserveAction;
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, discoveryAddr);
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[100] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, discoveryAddr);
{
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[100] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, discoveryAddr);
OCStackResult ret;
OCCallbackData cbData;
/* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
strcpy(szQueryUri, RESOURCE_DISCOVERY_QUERY);
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, g_discoveryAddr);
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[100] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, g_discoveryAddr);
{
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[100] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, g_discoveryAddr);
}
}
- pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE);
+ pl->bitmap = res->resourceProperties & (OC_OBSERVABLE | OC_DISCOVERABLE
+#ifdef MQ_PUBLISHER
+ | OC_MQ_PUBLISHER
+#endif
+ );
pl->secure = (res->resourceProperties & OC_SECURE) != 0;
pl->port = securePort;
#ifdef TCP_ADAPTER
OIC_LOG_V(INFO, TAG, "Extracting params from %s", query);
+ if (strnlen(query, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
+ {
+ OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
+ return OC_STACK_INVALID_QUERY;
+ }
+
char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
while(keyValuePair)
return OC_PRESENCE;
}
#endif //WITH_PRESENCE
+
+#ifdef MQ_BROKER
+ else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
+ {
+ return OC_MQ_BROKER_URI;
+ }
+#endif //MQ_BROKER
return OC_UNKNOWN_URI;
}
OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
// Step 1: Generate the response to discovery request
- if (virtualUriInRequest == OC_WELL_KNOWN_URI)
+ if (virtualUriInRequest == OC_WELL_KNOWN_URI
+#ifdef MQ_BROKER
+ || virtualUriInRequest == OC_MQ_BROKER_URI
+#endif
+ )
{
if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
{
if (!resourceTypeQuery && interfaceQuery && (0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
{
+ OCResourceProperty prop = OC_DISCOVERABLE;
+#ifdef MQ_BROKER
+ if (OC_MQ_BROKER_URI == virtualUriInRequest)
+ {
+ prop = OC_MQ_BROKER;
+ }
+#endif
+
for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
{
bool result = false;
- if (resource->resourceProperties & OC_DISCOVERABLE)
+
+ if (resource->resourceProperties & prop)
{
result = true;
}
#include "logger.h"
#include "ocserverrequest.h"
#include "secureresourcemanager.h"
+#include "psinterface.h"
#include "doxmresource.h"
#include "cacommon.h"
#include "cainterface.h"
static OCResource *tailResource = NULL;
static OCResourceHandle platformResource = {0};
static OCResourceHandle deviceResource = {0};
+#ifdef MQ_BROKER
+static OCResourceHandle brokerResource = {0};
+#endif
+
#ifdef WITH_PRESENCE
static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
static PresenceResource presenceResource = {0};
OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode)
{
OCStackResult ret = OC_STACK_ERROR;
-
switch(caCode)
{
case CA_CREATED:
// This should not happen but,
// give it a value just in case but output an error
ret = CA_CONTENT;
- OIC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].", method);
+ OIC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].",
+ method);
}
break;
case OC_STACK_RESOURCE_CREATED:
case OC_STACK_RESOURCE_DELETED:
ret = CA_DELETED;
break;
+ case OC_STACK_RESOURCE_CHANGED:
+ ret = CA_CHANGED;
+ break;
case OC_STACK_INVALID_QUERY:
ret = CA_BAD_REQ;
break;
if (inputLength >= ENCODE_MAX_INPUT_LENGTH)
{
- OIC_LOG(ERROR, TAG, "encodeAddressForRFC6874 failed: Invalid input string: too long/unterminated!");
+ OIC_LOG(ERROR, TAG,
+ "encodeAddressForRFC6874 failed: Invalid input string: too long/unterminated!");
return OC_STACK_INVALID_PARAM;
}
{
type = PAYLOAD_TYPE_DISCOVERY;
}
+#ifdef WITH_MQ
+ else if (strcmp(cbNode->requestUri, OC_RSRVD_WELL_KNOWN_MQ_URI) == 0)
+ {
+ type = PAYLOAD_TYPE_DISCOVERY;
+ }
+#endif
else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
{
type = PAYLOAD_TYPE_DEVICE;
(observationOption << 8) | optionData[i];
}
response.sequenceNumber = observationOption;
-
response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
start = 1;
}
return OC_STACK_INVALID_PARAM;
}
- if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
+ if (!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
{
resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
}
+#ifdef MQ_PUBLISHER
+ resourceProperties = resourceProperties | OC_MQ_PUBLISHER;
+#endif
// Make sure resourceProperties bitmask has allowed properties specified
if (resourceProperties
> (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
- OC_EXPLICIT_DISCOVERABLE))
+ OC_EXPLICIT_DISCOVERABLE
+#ifdef MQ_PUBLISHER
+ | OC_MQ_PUBLISHER
+#endif
+#ifdef MQ_BROKER
+ | OC_MQ_BROKER
+#endif
+ ))
{
OIC_LOG(ERROR, TAG, "Invalid property");
return OC_STACK_INVALID_PARAM;
if(result == OC_STACK_OK)
{
+ CreateResetProfile();
result = OCCreateResource(&deviceResource,
OC_RSRVD_RESOURCE_TYPE_DEVICE,
OC_RSRVD_INTERFACE_DEFAULT,
}
memset(&platformResource, 0, sizeof(platformResource));
memset(&deviceResource, 0, sizeof(deviceResource));
+#ifdef MQ_BROKER
+ memset(&brokerResource, 0, sizeof(brokerResource));
+#endif
SRMDeInitSecureResources();
}
else
{
- OCStackResult result = BindResourceInterfaceToResource(resource, OC_RSRVD_INTERFACE_DEFAULT);
+ OCStackResult result = BindResourceInterfaceToResource(resource,
+ OC_RSRVD_INTERFACE_DEFAULT);
if (result != OC_STACK_OK)
{
OICFree(newInterface->name);
}
/* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
strcpy(szQueryUri, OC_EXPLICIT_DEVICE_DISCOVERY_URI);
if (OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS,
0, 0, 0) != OC_STACK_OK) {
InitStack(OC_CLIENT);
/* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
strcpy(szQueryUri, OC_RSRVD_WELL_KNOWN_URI);
cbData.cb = asyncDoResourcesCallback;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
InitStack(OC_CLIENT);
/* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[MAX_QUERY_LENGTH] = { 0 };
strcpy(szQueryUri, OC_RSRVD_WELL_KNOWN_URI);
cbData.cb = asyncDoResourcesCallback;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
"/a/led",
0,
NULL,
- 128));// invalid bitmask for OCResourceProperty
+ 255));// invalid bitmask for OCResourceProperty
EXPECT_EQ(OC_STACK_OK, OCStop());
}
NULL,
OC_DISCOVERABLE|OC_OBSERVABLE));
/* Start a discovery query*/
- char szQueryUri[256] = "/oic/res?if=oic.if.ll";
+ char szQueryUri[MAX_QUERY_LENGTH] = "/oic/res?if=oic.if.ll";
OCCallbackData cbData;
cbData.cb = discoveryCallback;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
if examples_env.get('LOGGING'):
examples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if examples_env.get('WITH_CLOUD'):
+ examples_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD'])
+
if target_os in ['msys_nt', 'windows']:
examples_env.AppendUnique(LIBS = ['Comctl32', 'Gdi32', 'User32'])
-if examples_env.get('LOGGING'):
- examples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
-
def make_single_file_cpp_program(program_name):
return examples_env.Program(program_name, program_name + ".cpp")
const std::string& uri,
const OCRepresentation& rep, const QueryParamsMap& queryParams,
const HeaderOptions& headerOptions,
+ OCConnectivityType connectivityType,
PostCallback& callback, QualityOfService QoS) = 0;
virtual OCStackResult DeleteResource(
virtual OCStackResult UnsubscribePresence(OCDoHandle handle) =0;
+ virtual OCStackResult SubscribeDevicePresence(OCDoHandle* handle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback& callback) = 0;
+
virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0;
virtual OCStackResult FindDirectPairingDevices(unsigned short waittime,
virtual OCStackResult GetDirectPairedDevices(GetDirectPairedCallback& callback) = 0;
- virtual OCStackResult DoDirectPairing(std::shared_ptr<OCDirectPairing> peer, const OCPrm_t& pmSel,
- const std::string& pinNumber, DirectPairingCallback& resultCallback) = 0;
-
+ virtual OCStackResult DoDirectPairing(std::shared_ptr< OCDirectPairing > peer,
+ const OCPrm_t& pmSel, const std::string& pinNumber,
+ DirectPairingCallback& resultCallback) = 0;
+
+#ifdef WITH_MQ
+ virtual OCStackResult ListenForMQTopic(
+ const OCDevAddr& devAddr,
+ const std::string& resourceUri,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ FindCallback& callback, QualityOfService QoS) = 0;
+
+ virtual OCStackResult PutMQTopicRepresentation(
+ const OCDevAddr& devAddr,
+ const std::string& uri,
+ const OCRepresentation& rep,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ MQCreateTopicCallback& callback, QualityOfService QoS) = 0;
+#endif
virtual ~IClientWrapper(){}
};
}
DirectPairingContext(DirectPairingCallback cb) : callback(cb){}
};
+
+#ifdef WITH_MQ
+ struct CreateMQTopicContext
+ {
+ MQCreateTopicCallback callback;
+ std::weak_ptr<IClientWrapper> clientWrapper;
+ CreateMQTopicContext(MQCreateTopicCallback cb, std::weak_ptr<IClientWrapper> cw)
+ : callback(cb), clientWrapper(cw){}
+ };
+#endif
}
class InProcClientWrapper : public IClientWrapper
const OCDevAddr& devAddr,
const std::string& uri,
const OCRepresentation& attributes, const QueryParamsMap& queryParams,
- const HeaderOptions& headerOptions, PostCallback& callback, QualityOfService QoS);
+ const HeaderOptions& headerOptions, OCConnectivityType connectivityType,
+ PostCallback& callback, QualityOfService QoS);
virtual OCStackResult DeleteResource(
const OCDevAddr& devAddr,
SubscribeCallback& presenceHandler);
virtual OCStackResult UnsubscribePresence(OCDoHandle handle);
- OCStackResult GetDefaultQos(QualityOfService& QoS);
+ virtual OCStackResult SubscribeDevicePresence(OCDoHandle* handle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback& callback);
+
+ OCStackResult GetDefaultQos(QualityOfService& QoS);
virtual OCStackResult FindDirectPairingDevices(unsigned short waittime,
GetDirectPairedCallback& callback);
virtual OCStackResult DoDirectPairing(std::shared_ptr<OCDirectPairing> peer, const OCPrm_t& pmSel,
const std::string& pinNumber, DirectPairingCallback& resultCallback);
+#ifdef WITH_MQ
+ virtual OCStackResult ListenForMQTopic(
+ const OCDevAddr& devAddr,
+ const std::string& resourceUri,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ FindCallback& callback, QualityOfService QoS);
+
+ virtual OCStackResult PutMQTopicRepresentation(
+ const OCDevAddr& devAddr,
+ const std::string& uri,
+ const OCRepresentation& rep,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ MQCreateTopicCallback& callback, QualityOfService QoS);
+#endif
+
private:
void listeningFunc();
std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
+ std::string assembleSetResourceUri(std::string uri, const QueryParamsList& queryParams);
OCPayload* assembleSetResourcePayload(const OCRepresentation& attributes);
OCHeaderOption* assembleHeaderOptions(OCHeaderOption options[],
const HeaderOptions& headerOptions);
// Typedef for query parameter map
typedef std::map<std::string, std::string> QueryParamsMap;
+ // Typedef for query parameter map with Vector
+ typedef std::map< std::string, std::vector<std::string> > QueryParamsList;
+
// Typedef for list of observation IDs
typedef std::vector<OCObservationId> ObservationIds;
typedef std::function<void(const PairedDevices&)> GetDirectPairedCallback;
+ typedef std::function<void(const HeaderOptions&,
+ const OCRepresentation&, const int,
+ std::shared_ptr<OCResource>)> MQCreateTopicCallback;
+
} // namespace OC
#endif
OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle);
/**
+ * Subscribes to a server's device presence change events.
+ *
+ * @param presenceHandle a handle object that can be used to identify this subscription
+ * request. It can be used to unsubscribe from these events in the future.
+ * It will be set upon successful return of this method.
+ * @param host The IP address/addressable name of the server to subscribe to.
+ * This should be in the format coap://address:port
+ * @param queryParams map which can have the query parameter name and list of value.
+ * @param observeHandler handles callback
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this observe operation
+ * This will have error codes
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ */
+ OCStackResult subscribeDevicePresence(OCPresenceHandle& presenceHandle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback callback);
+
+ /**
* Creates a resource proxy object so that get/put/observe functionality
* can be used without discovering the object in advance. Note that the
* consumer of this method needs to provide all of the details required to
OCStackResult doDirectPairing(std::shared_ptr<OCDirectPairing> peer, OCPrm_t pmSel,
const std::string& pinNumber,
DirectPairingCallback resultCallback);
+#ifdef WITH_CLOUD
+ /**
+ * API for Account Registration to Account Server
+ * @note Not supported on client mode for now since device id is not generated yet on
+ * client mode. So it should be server or both mode for API to work.
+ *
+ * @param host Host IP Address of a account server.
+ * @param authProvider Provider name used for authentication.
+ * @param authCode The authorization code obtained by using an authorization server
+ * as an intermediary between the client and resource owner.
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
+ * interface. Example: CT_DEFAULT, CT_ADAPTER_IP, CT_ADAPTER_TCP.
+ * @param cloudConnectHandler Callback function that will get the result of the operation.
+ *
+ * @return Returns ::OC_STACK_OK if success
+ */
+ OCStackResult signUp(const std::string& host,
+ const std::string& authProvider,
+ const std::string& authCode,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ /**
+ * API for Sign-In to Account Server
+ * @note Not supported on client mode for now since device id is not generated yet on
+ * client mode. So it should be server or both mode for API to work.
+ *
+ * @param host Host IP Address of a account server.
+ * @param accessToken Identifier of the resource obtained by account registration.
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
+ * interface. Example: CT_DEFAULT, CT_ADAPTER_IP, CT_ADAPTER_TCP.
+ * @param cloudConnectHandler Callback function that will get the result of the operation.
+ *
+ * @return Returns ::OC_STACK_OK if success
+ */
+ OCStackResult signIn(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ /**
+ * API for Sign-Out to Account Server
+ * @note Not supported on client mode for now since device id is not generated yet on
+ * client mode. So it should be server or both mode for API to work.
+ *
+ * @param host Host IP Address of a account server.
+ * @param accessToken Identifier of the resource obtained by account registration.
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
+ * interface. Example: CT_DEFAULT, CT_ADAPTER_IP, CT_ADAPTER_TCP.
+ * @param cloudConnectHandler Callback function that will get the result of the operation.
+ *
+ * @return Returns ::OC_STACK_OK if success
+ */
+ OCStackResult signOut(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ /**
+ * API for Refresh Access token to Account Server
+ * @note Not supported on client mode for now since device id is not generated yet on
+ * client mode. So it should be server or both mode for API to work.
+ *
+ * @param host Host IP Address of a account server.
+ * @param refreshToken Refresh token used for access token refresh.
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
+ * interface. Example: CT_DEFAULT, CT_ADAPTER_IP, CT_ADAPTER_TCP.
+ * @param cloudConnectHandler Callback function that will get the result of the operation.
+ *
+ * @return Returns ::OC_STACK_OK if success
+ */
+ OCStackResult refreshAccessToken(const std::string& host,
+ const std::string& refreshToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+#endif // WITH_CLOUD
}
}
SubscribeCallback presenceHandler);
OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle);
+ OCStackResult subscribeDevicePresence(OCPresenceHandle& presenceHandle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback callback);
+
OCResource::Ptr constructResourceObject(const std::string& host, const std::string& uri,
OCConnectivityType connectivityType, bool isObservable,
const std::vector<std::string>& resourceTypes,
OCStackResult doDirectPairing(std::shared_ptr<OCDirectPairing> peer, OCPrm_t pmSel,
const std::string& pinNumber,
DirectPairingCallback resultCallback);
-
+#ifdef WITH_CLOUD
+ OCStackResult signUp(const std::string& host,
+ const std::string& authProvider,
+ const std::string& authCode,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ OCStackResult signIn(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ OCStackResult signOut(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ OCStackResult signInOut(const std::string& host,
+ const std::string& accessToken,
+ bool isSignIn,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+
+ OCStackResult refreshAccessToken(const std::string& host,
+ const std::string& refreshToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler);
+#endif // WITH_CLOUD
private:
PlatformConfig m_cfg;
m_resourceId(std::move(o.m_resourceId)),
m_devAddr(std::move(o.m_devAddr)),
m_useHostString(o.m_useHostString),
- m_isObservable(o.m_isObservable),
+ m_property(o.m_property),
m_isCollection(o.m_isCollection),
m_resourceTypes(std::move(o.m_resourceTypes)),
m_interfaces(std::move(o.m_interfaces)),
*/
bool isObservable() const;
+#ifdef WITH_MQ
+ /**
+ * Function to provide ability to check if this resource is publisher or not
+ * @return bool true indicates resource is publisher; false indicates resource is
+ * not publisher.
+ */
+ bool isPublish() const;
+#endif
+
/**
* Function to get the list of resource types
* @return vector of resource types
*/
std::string sid() const;
+#ifdef WITH_MQ
+ /**
+ * Function to discovery Topics from MQ Broker.
+ *
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param attributeHandler handles callback
+
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult discoveryMQTopics(const QueryParamsMap& queryParametersMap,
+ FindCallback attributeHandler);
+ /**
+ * Function to create Topic into MQ Broker.
+ * SubTopic is also created through this method.
+ *
+ * @param rep representation of the topic
+ * @param topicUri new uri of the topic which want to create
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param attributeHandler handles callback
+
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult createMQTopic(const OCRepresentation& rep,
+ const std::string& topicUri,
+ const QueryParamsMap& queryParametersMap,
+ MQCreateTopicCallback attributeHandler);
+#endif
+#ifdef MQ_SUBSCRIBER
+ /**
+ * Function to subscribe Topic to MQ Broker.
+ *
+ * @param observeType allows the client to specify how it wants to observe.
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param observeHandler handles callback
+
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult subscribeMQTopic(ObserveType observeType,
+ const QueryParamsMap& queryParametersMap,
+ ObserveCallback observeHandler);
+
+ /**
+ * Function to unsubscribe Topic to MQ Broker.
+ *
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult unsubscribeMQTopic();
+
+ /**
+ * Function to request publish to MQ publisher.
+ * Publisher can confirm the request message as key:"req_pub" and value:"true".
+ *
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param attributeHandler handles callback
+
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult requestMQPublish(const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler);
+#endif
+#ifdef MQ_PUBLISHER
+ /**
+ * Function to publish Topic information into MQ Broker.
+ *
+ * @param rep representation of the topic
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param attributeHandler handles callback
+
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
+ */
+ OCStackResult publishMQTopic(const OCRepresentation& rep,
+ const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler);
+#endif
// overloaded operators allow for putting into a 'set'
// the uniqueidentifier allows for putting into a hash
bool operator==(const OCResource &other) const;
OCResourceIdentifier m_resourceId;
OCDevAddr m_devAddr;
bool m_useHostString;
- bool m_isObservable;
bool m_isCollection;
+ uint8_t m_property;
std::vector<std::string> m_resourceTypes;
std::vector<std::string> m_interfaces;
std::vector<std::string> m_children;
private:
OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
const OCDevAddr& devAddr, const std::string& uri,
- const std::string& serverId, bool observable,
+ const std::string& serverId, uint8_t property,
const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces);
OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
const std::string& host, const std::string& uri,
const std::string& serverId,
- OCConnectivityType connectivityType, bool observable,
+ OCConnectivityType connectivityType, uint8_t property,
const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces);
};
if (res->port != 0)
{
- m_devAddr.port = res->port;
+ m_devAddr.port = res->port;
}
+
if (payload->baseURI)
{
OCDevAddr rdPubAddr = m_devAddr;
new OC::OCResource(m_clientWrapper, rdPubAddr,
std::string(res->uri),
std::string(payload->sid),
- (res->bitmap & OC_OBSERVABLE) == OC_OBSERVABLE,
+ res->bitmap,
StringLLToVector(res->types),
StringLLToVector(res->interfaces)
)));
new OC::OCResource(m_clientWrapper, m_devAddr,
std::string(res->uri),
std::string(payload->sid),
- (res->bitmap & OC_OBSERVABLE) == OC_OBSERVABLE,
+ res->bitmap,
StringLLToVector(res->types),
StringLLToVector(res->interfaces)
)));
new OC::OCResource(m_clientWrapper, tcpDevAddr,
std::string(res->uri),
std::string(payload->sid),
- (res->bitmap & OC_OBSERVABLE) == OC_OBSERVABLE,
+ res->bitmap,
StringLLToVector(res->types),
StringLLToVector(res->interfaces)
)));
}
}
+#ifdef WITH_MQ
+ ListenOCContainer(std::weak_ptr<IClientWrapper> cw,
+ OCDevAddr& devAddr, OCRepPayload* payload)
+ : m_clientWrapper(cw), m_devAddr(devAddr)
+ {
+ if (payload)
+ {
+ char**topicList = nullptr;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = {0};
+ OCRepPayloadGetStringArray(payload, "topiclist", &topicList, dimensions);
+
+ for(size_t idx = 0; idx < dimensions[0]; idx++)
+ {
+ m_resources.push_back(std::shared_ptr<OC::OCResource>(
+ new OC::OCResource(m_clientWrapper, m_devAddr,
+ std::string(topicList[idx]),
+ "",
+ OC_OBSERVABLE,
+ {OC_RSRVD_RESOURCE_TYPE_MQ_TOPIC},
+ {DEFAULT_INTERFACE})));
+ }
+ }
+ }
+
+ ListenOCContainer(std::weak_ptr<IClientWrapper> cw,
+ OCDevAddr& devAddr, const std::string& topicUri)
+ : m_clientWrapper(cw), m_devAddr(devAddr)
+ {
+ m_resources.push_back(std::shared_ptr<OC::OCResource>(
+ new OC::OCResource(m_clientWrapper, m_devAddr,
+ topicUri,
+ "",
+ OC_OBSERVABLE,
+ {OC_RSRVD_RESOURCE_TYPE_MQ_TOPIC},
+ {DEFAULT_INTERFACE})));
+ }
+#endif
+
const std::vector<std::shared_ptr<OCResource>>& Resources() const
{
return m_resources;
const OCRepresentation& /*attributes*/,
const QueryParamsMap& /*queryParams*/,
const HeaderOptions& /*headerOptions*/,
+ OCConnectivityType /*connectivityType*/,
PostCallback& /*callback*/, QualityOfService /*QoS*/)
{return OC_STACK_NOTIMPL;}
virtual OCStackResult UnsubscribePresence(OCDoHandle /*handle*/)
{return OC_STACK_NOTIMPL;}
+ virtual OCStackResult SubscribeDevicePresence(
+ OCDoHandle* /*handle*/,
+ const std::string& /*host*/,
+ const QueryParamsList& /*queryParams*/,
+ OCConnectivityType /*connectivityType*/,
+ ObserveCallback& /*callback*/)
+ {return OC_STACK_NOTIMPL;}
+
virtual OCStackResult GetDefaultQos(QualityOfService& /*QoS*/)
{return OC_STACK_NOTIMPL;}
const OCPrm_t& /*pmSel*/,
const std::string& /*pinNumber*/, DirectPairingCallback& /*resultCallback*/)
{return OC_STACK_NOTIMPL;}
+
+#ifdef WITH_MQ
+ virtual OCStackResult ListenForMQTopic(const OCDevAddr& /*devAddr*/,
+ const std::string& /*resourceUri*/,
+ const QueryParamsMap& /*queryParams*/,
+ const HeaderOptions& /*headerOptions*/,
+ FindCallback& /*callback*/,
+ QualityOfService /*QoS*/)
+ {return OC_STACK_NOTIMPL;}
+
+ virtual OCStackResult PutMQTopicRepresentation(const OCDevAddr& /*devAddr*/,
+ const std::string& /*uri*/,
+ const OCRepresentation& /*rep*/,
+ const QueryParamsMap& /*queryParams*/,
+ const HeaderOptions& /*headerOptions*/,
+ MQCreateTopicCallback& /*callback*/,
+ QualityOfService /*QoS*/)
+ {return OC_STACK_NOTIMPL;}
+#endif
};
}
ListenOCContainer container(clientWrapper, clientResponse->devAddr,
reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
// loop to ensure valid construction of all resources
+
for(auto resource : container.Resources())
{
std::thread exec(context->callback, resource);
}
return result;
}
+#ifdef WITH_MQ
+ OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse* clientResponse)
+ {
+ ClientCallbackContext::ListenContext* context =
+ static_cast<ClientCallbackContext::ListenContext*>(ctx);
+
+ if (!clientResponse)
+ {
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ if (clientResponse->result != OC_STACK_OK)
+ {
+ oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
+ << clientResponse->result
+ << std::flush;
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ auto clientWrapper = context->clientWrapper.lock();
+ if (!clientWrapper)
+ {
+ oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
+ << std::flush;
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ try{
+ ListenOCContainer container(clientWrapper, clientResponse->devAddr,
+ (OCRepPayload *) clientResponse->payload);
+
+ // loop to ensure valid construction of all resources
+ for (auto resource : container.Resources())
+ {
+ std::thread exec(context->callback, resource);
+ exec.detach();
+ }
+ }
+ catch (std::exception &e){
+ oclog() << "Exception in listCallback, ignoring response: "
+ << e.what() << std::flush;
+ }
+
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ OCStackResult InProcClientWrapper::ListenForMQTopic(
+ const OCDevAddr& devAddr,
+ const std::string& resourceUri,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ FindCallback& callback, QualityOfService QoS)
+ {
+ oclog() << "ListenForMQTopic()" << std::flush;
+
+ if (!callback)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ ClientCallbackContext::ListenContext* context =
+ new ClientCallbackContext::ListenContext(callback, shared_from_this());
+ OCCallbackData cbdata;
+ cbdata.context = static_cast<void*>(context),
+ cbdata.cb = listenMQCallback;
+ cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
+
+ std::string uri = assembleSetResourceUri(resourceUri, queryParams);
+
+ OCStackResult result = OC_STACK_ERROR;
+ auto cLock = m_csdkLock.lock();
+ if (cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ OCHeaderOption options[MAX_HEADER_OPTIONS];
+ result = OCDoResource(
+ nullptr, OC_REST_GET,
+ uri.c_str(),
+ &devAddr, nullptr,
+ CT_DEFAULT,
+ static_cast<OCQualityOfService>(QoS),
+ &cbdata,
+ assembleHeaderOptions(options, headerOptions),
+ headerOptions.size());
+ }
+ else
+ {
+ delete context;
+ }
+
+ return result;
+ }
+#endif
OCStackApplicationResult listenDeviceCallback(void* ctx,
OCDoHandle /*handle*/,
}
}
+#ifdef WITH_MQ
+ OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse* clientResponse)
+ {
+ ClientCallbackContext::CreateMQTopicContext* context =
+ static_cast<ClientCallbackContext::CreateMQTopicContext*>(ctx);
+ OCRepresentation rep;
+ HeaderOptions serverHeaderOptions;
+
+ if (!clientResponse)
+ {
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ std::string createdUri;
+ OCStackResult result = clientResponse->result;
+ if (OC_STACK_OK == result ||
+ OC_STACK_RESOURCE_CREATED == result)
+ {
+ parseServerHeaderOptions(clientResponse, serverHeaderOptions);
+ try
+ {
+ rep = parseGetSetCallback(clientResponse);
+ }
+ catch(OC::OCException& e)
+ {
+ result = e.code();
+ }
+
+ bool isLocationOption = false;
+ for (auto headerOption : serverHeaderOptions)
+ {
+ if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
+ {
+ createdUri += "/";
+ createdUri += headerOption.getOptionData();
+ if (!isLocationOption)
+ {
+ isLocationOption = true;
+ }
+ }
+ }
+
+ if (!isLocationOption)
+ {
+ createdUri = clientResponse->resourceUri;
+ }
+ }
+
+ auto clientWrapper = context->clientWrapper.lock();
+
+ if (!clientWrapper)
+ {
+ oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
+ << std::flush;
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ try{
+ if (OC_STACK_OK == result ||
+ OC_STACK_RESOURCE_CREATED == result)
+ {
+ ListenOCContainer container(clientWrapper, clientResponse->devAddr,
+ createdUri);
+ for (auto resource : container.Resources())
+ {
+ std::thread exec(context->callback, serverHeaderOptions, rep, result, resource);
+ exec.detach();
+ }
+ }
+ else
+ {
+ std::thread exec(context->callback, serverHeaderOptions, rep, result, nullptr);
+ exec.detach();
+ }
+ }
+ catch (std::exception &e){
+ oclog() << "Exception in createMQTopicCallback, ignoring response: "
+ << e.what() << std::flush;
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
+ const OCDevAddr& devAddr,
+ const std::string& uri,
+ const OCRepresentation& rep,
+ const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ MQCreateTopicCallback& callback, QualityOfService QoS)
+ {
+ if (!callback)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ OCStackResult result;
+ ClientCallbackContext::CreateMQTopicContext* ctx =
+ new ClientCallbackContext::CreateMQTopicContext(callback, shared_from_this());
+ OCCallbackData cbdata;
+ cbdata.context = static_cast<void*>(ctx),
+ cbdata.cb = createMQTopicCallback;
+ cbdata.cd = [](void* c){delete (ClientCallbackContext::CreateMQTopicContext*)c;};
+
+ std::string url = assembleSetResourceUri(uri, queryParams);
+
+ auto cLock = m_csdkLock.lock();
+
+ if (cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ OCHeaderOption options[MAX_HEADER_OPTIONS];
+
+ result = OCDoResource(nullptr, OC_REST_PUT,
+ url.c_str(), &devAddr,
+ assembleSetResourcePayload(rep),
+ CT_DEFAULT,
+ static_cast<OCQualityOfService>(QoS),
+ &cbdata,
+ assembleHeaderOptions(options, headerOptions),
+ headerOptions.size());
+ }
+ else
+ {
+ delete ctx;
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+#endif
OCStackApplicationResult getResourceCallback(void* ctx,
OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
return ret;
}
+ std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
+ const QueryParamsList& queryParams)
+ {
+ if (!uri.empty())
+ {
+ if (uri.back() == '/')
+ {
+ uri.resize(uri.size() - 1);
+ }
+ }
+
+ ostringstream paramsList;
+ if (queryParams.size() > 0)
+ {
+ paramsList << '?';
+ }
+
+ for (auto& param : queryParams)
+ {
+ for (auto& paramList : param.second)
+ {
+ paramsList << param.first << '=' << paramList;
+ if (paramList != param.second.back())
+ {
+ paramsList << '&';
+ }
+ }
+ paramsList << ';';
+ }
+
+ std::string queryString = paramsList.str();
+
+ if (queryString.empty())
+ {
+ return uri;
+ }
+
+ if (queryString.back() == ';')
+ {
+ queryString.resize(queryString.size() - 1);
+ }
+
+ std::string ret = uri + queryString;
+ return ret;
+ }
+
OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
{
MessageContainer ocInfo;
const std::string& uri,
const OCRepresentation& rep,
const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
+ OCConnectivityType connectivityType,
PostCallback& callback, QualityOfService QoS)
{
if (!callback)
result = OCDoResource(nullptr, OC_REST_POST,
url.c_str(), &devAddr,
assembleSetResourcePayload(rep),
- CT_DEFAULT,
+ connectivityType,
static_cast<OCQualityOfService>(QoS),
&cbdata,
assembleHeaderOptions(options, headerOptions),
return result;
}
+ OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback& callback)
+ {
+ if (!callback)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ OCStackResult result;
+
+ ClientCallbackContext::ObserveContext* ctx =
+ new ClientCallbackContext::ObserveContext(callback);
+ OCCallbackData cbdata;
+ cbdata.context = static_cast<void*>(ctx),
+ cbdata.cb = observeResourceCallback;
+ cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
+
+ auto cLock = m_csdkLock.lock();
+
+ if (cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+
+ std::ostringstream os;
+ os << host << OCF_RSRVD_DEVICE_PRESENCE_URI;
+ std::string url = assembleSetResourceUri(os.str(), queryParams);
+
+ result = OCDoResource(handle, OC_REST_OBSERVE,
+ url.c_str(), nullptr,
+ nullptr, connectivityType,
+ OC_LOW_QOS, &cbdata,
+ nullptr, 0);
+ }
+ else
+ {
+ delete ctx;
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
{
qos = m_cfg.QoS;
return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle);
}
+ OCStackResult subscribeDevicePresence(OCPresenceHandle& presenceHandle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback callback)
+ {
+ return OCPlatform_impl::Instance().subscribeDevicePresence(presenceHandle,
+ host,
+ queryParams,
+ connectivityType,
+ callback);
+ }
+
OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
{
return OCPlatform_impl::Instance().sendResponse(pResponse);
return OCPlatform_impl::Instance().doDirectPairing(peer, pmSel,
pinNumber, resultCallback);
}
+#ifdef WITH_CLOUD
+ OCStackResult signUp(const std::string& host,
+ const std::string& authProvider,
+ const std::string& authCode,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return OCPlatform_impl::Instance().signUp(host, authProvider, authCode,
+ connectivityType, cloudConnectHandler);
+ }
+ OCStackResult signIn(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return OCPlatform_impl::Instance().signIn(host, accessToken,
+ connectivityType, cloudConnectHandler);
+ }
+
+ OCStackResult signOut(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return OCPlatform_impl::Instance().signOut(host, accessToken,
+ connectivityType, cloudConnectHandler);
+ }
+
+ OCStackResult refreshAccessToken(const std::string& host,
+ const std::string& refreshToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return OCPlatform_impl::Instance().refreshAccessToken(host, refreshToken,
+ connectivityType, cloudConnectHandler);
+ }
+#endif // WITH_CLOUD
} // namespace OCPlatform
} //namespace OC
return std::shared_ptr<OCResource>();
}
+ uint8_t resourceProperty = 0;
+ if (isObservable)
+ {
+ resourceProperty = (resourceProperty | OC_OBSERVABLE);
+ }
return std::shared_ptr<OCResource>(new OCResource(m_client,
host,
uri, "", connectivityType,
- isObservable,
+ resourceProperty,
resourceTypes,
interfaces));
}
std::ref(presenceHandle));
}
+ OCStackResult OCPlatform_impl::subscribeDevicePresence(OCPresenceHandle& presenceHandle,
+ const std::string& host,
+ const QueryParamsList& queryParams,
+ OCConnectivityType connectivityType,
+ ObserveCallback callback)
+ {
+ return checked_guard(m_client, &IClientWrapper::SubscribeDevicePresence,
+ &presenceHandle, host, queryParams, connectivityType, callback);
+ }
+
OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
{
return checked_guard(m_server, &IServerWrapper::sendResponse,
return checked_guard(m_client, &IClientWrapper::DoDirectPairing,
peer, pmSel, pinNumber, resultCallback);
}
+#ifdef WITH_CLOUD
+ OCStackResult OCPlatform_impl::signUp(const std::string& host,
+ const std::string& authProvider,
+ const std::string& authCode,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ const char* di = OCGetServerInstanceIDString();
+ if (!di)
+ {
+ oclog() << "The mode should be Server or Both to generate UUID" << std::flush;
+ return result_guard(OC_STACK_ERROR);
+ }
+ std::string deviceId(di);
+
+ OCRepresentation rep;
+ rep.setValue(OC_RSRVD_DEVICE_ID, deviceId);
+ rep.setValue(OC_RSRVD_AUTHPROVIDER, authProvider);
+ rep.setValue(OC_RSRVD_AUTHCODE, authCode);
+
+ std::string uri = host + OC_RSRVD_ACCOUNT_URI;
+
+ OCDevAddr devAddr;
+ QueryParamsMap queryParams;
+ HeaderOptions headerOptions;
+
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_client, &IClientWrapper::GetDefaultQos, defaultQos);
+
+ return checked_guard(m_client, &IClientWrapper::PostResourceRepresentation,
+ devAddr, uri, rep, queryParams, headerOptions,
+ connectivityType, cloudConnectHandler, defaultQos);
+ }
+
+ OCStackResult OCPlatform_impl::signIn(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return signInOut(host, accessToken, true, connectivityType, cloudConnectHandler);
+ }
+
+ OCStackResult OCPlatform_impl::signOut(const std::string& host,
+ const std::string& accessToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ return signInOut(host, accessToken, false, connectivityType, cloudConnectHandler);
+ }
+ OCStackResult OCPlatform_impl::signInOut(const std::string& host,
+ const std::string& accessToken,
+ bool isSignIn,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ const char* di = OCGetServerInstanceIDString();
+ if (!di)
+ {
+ oclog() << "The mode should be Server or Both to generate UUID" << std::flush;
+ return result_guard(OC_STACK_ERROR);
+ }
+ std::string deviceId(di);
+
+ OCRepresentation rep;
+ rep.setValue(OC_RSRVD_DEVICE_ID, deviceId);
+ rep.setValue(OC_RSRVD_ACCESS_TOKEN, accessToken);
+ rep.setValue(OC_RSRVD_STATUS, isSignIn);
+
+ std::string uri = host + OC_RSRVD_ACCOUNT_SESSION_URI;
+
+ OCDevAddr devAddr;
+ QueryParamsMap queryParams;
+ HeaderOptions headerOptions;
+
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_client, &IClientWrapper::GetDefaultQos, defaultQos);
+
+ return checked_guard(m_client, &IClientWrapper::PostResourceRepresentation,
+ devAddr, uri, rep, queryParams, headerOptions,
+ connectivityType, cloudConnectHandler, defaultQos);
+ }
+
+ OCStackResult OCPlatform_impl::refreshAccessToken(const std::string& host,
+ const std::string& refreshToken,
+ OCConnectivityType connectivityType,
+ PostCallback cloudConnectHandler)
+ {
+ const char* di = OCGetServerInstanceIDString();
+ if (!di)
+ {
+ oclog() << "The mode should be Server or Both to generate UUID" << std::flush;
+ return result_guard(OC_STACK_ERROR);
+ }
+ std::string deviceId(di);
+
+ OCRepresentation rep;
+ rep.setValue(OC_RSRVD_DEVICE_ID, deviceId);
+ rep.setValue(OC_RSRVD_REFRESH_TOKEN, refreshToken);
+ rep.setValue(OC_RSRVD_GRANT_TYPE, OC_RSRVD_GRANT_TYPE_REFRESH_TOKEN);
+
+ std::string uri = host + OC_RSRVD_ACCOUNT_TOKEN_REFRESH_URI;
+
+ OCDevAddr devAddr;
+ QueryParamsMap queryParams;
+ HeaderOptions headerOptions;
+
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_client, &IClientWrapper::GetDefaultQos, defaultQos);
+
+ return checked_guard(m_client, &IClientWrapper::PostResourceRepresentation,
+ devAddr, uri, rep, queryParams, headerOptions,
+ connectivityType, cloudConnectHandler, defaultQos);
+ }
+#endif // WITH_CLOUD
} //namespace OC
OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
const OCDevAddr& devAddr, const std::string& uri,
- const std::string& serverId, bool observable,
+ const std::string& serverId, uint8_t property,
const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces)
: m_clientWrapper(clientWrapper), m_uri(uri),
m_resourceId(serverId, m_uri), m_devAddr(devAddr),
- m_isObservable(observable), m_isCollection(false),
+ m_property(property), m_isCollection(false),
m_resourceTypes(resourceTypes), m_interfaces(interfaces),
m_observeHandle(nullptr)
{
OCResource::OCResource(std::weak_ptr<IClientWrapper> clientWrapper,
const std::string& host, const std::string& uri,
const std::string& serverId,
- OCConnectivityType connectivityType, bool observable,
+ OCConnectivityType connectivityType, uint8_t property,
const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces)
: m_clientWrapper(clientWrapper), m_uri(uri),
m_resourceId(serverId, m_uri),
- m_isObservable(observable), m_isCollection(false),
+ m_property(property), m_isCollection(false),
m_resourceTypes(resourceTypes), m_interfaces(interfaces),
m_observeHandle(nullptr)
{
{
return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PostResourceRepresentation,
m_devAddr, m_uri, rep, queryParametersMap,
- m_headerOptions, attributeHandler, QoS);
+ m_headerOptions, CT_DEFAULT, attributeHandler, QoS);
}
OCStackResult OCResource::post(const OCRepresentation& rep,
bool OCResource::isObservable() const
{
- return m_isObservable;
+ return (m_property & OC_OBSERVABLE) == OC_OBSERVABLE;
+}
+
+#ifdef WITH_MQ
+bool OCResource::isPublish() const
+{
+ return (m_property & OC_MQ_PUBLISHER) == OC_MQ_PUBLISHER;
}
+#endif
std::vector<std::string> OCResource::getResourceTypes() const
{
return this->uniqueIdentifier().m_representation;
}
+#ifdef WITH_MQ
+OCStackResult OCResource::discoveryMQTopics(const QueryParamsMap& queryParametersMap,
+ FindCallback attributeHandler)
+{
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
+ return checked_guard(m_clientWrapper.lock(),
+ &IClientWrapper::ListenForMQTopic,
+ m_devAddr, m_uri,
+ queryParametersMap, m_headerOptions,
+ attributeHandler, defaultQos);
+}
+
+OCStackResult OCResource::createMQTopic(const OCRepresentation& rep,
+ const std::string& topicUri,
+ const QueryParamsMap& queryParametersMap,
+ MQCreateTopicCallback attributeHandler)
+{
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
+ return checked_guard(m_clientWrapper.lock(), &IClientWrapper::PutMQTopicRepresentation,
+ m_devAddr, topicUri, rep, queryParametersMap,
+ m_headerOptions, attributeHandler, defaultQos);
+}
+#endif
+#ifdef MQ_SUBSCRIBER
+OCStackResult OCResource::subscribeMQTopic(ObserveType observeType,
+ const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
+{
+ QualityOfService defaultQoS = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
+
+ return result_guard(observe(observeType, queryParametersMap, observeHandler, defaultQoS));
+}
+
+OCStackResult OCResource::unsubscribeMQTopic()
+{
+ QualityOfService defaultQoS = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQoS);
+ return result_guard(cancelObserve(defaultQoS));
+}
+
+OCStackResult OCResource::requestMQPublish(const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler)
+{
+ OCRepresentation rep;
+ rep.setValue(std::string("req_pub"), std::string("true"));
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
+ return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
+}
+#endif
+#ifdef MQ_PUBLISHER
+OCStackResult OCResource::publishMQTopic(const OCRepresentation& rep,
+ const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler)
+{
+ QualityOfService defaultQos = OC::QualityOfService::NaQos;
+ checked_guard(m_clientWrapper.lock(), &IClientWrapper::GetDefaultQos, defaultQos);
+ return result_guard(post(rep, queryParametersMap, attributeHandler, defaultQos));
+}
+#endif
+
bool OCResource::operator==(const OCResource &other) const
{
return m_resourceId == other.m_resourceId;
if secured == '1':
oclib_env.AppendUnique(LIBS=['tinydtls'])
+if oclib_env.get('WITH_CLOUD'):
+ oclib_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD'])
+
######################################################################
# Source files and Targets
######################################################################
{
}
+ void onObserve(const HeaderOptions, const OCRepresentation&, const int&, const int&)
+ {
+ }
+
void directPairHandler(std::shared_ptr<OCDirectPairing> /*dev*/, OCStackResult /*res*/)
{
}
void pairedHandler(const PairedDevices& /*list*/)
{
}
-
+#ifdef WITH_CLOUD
+ void accountHandler(const HeaderOptions& /*headerOptions*/, const OCRepresentation& /*rep*/,
+ const int /*eCode*/)
+ {
+ }
+#endif
//Helper methods
void DeleteStringLL(OCStringLL* ll)
{
EXPECT_EQ(OC_STACK_OK, OCPlatform::unsubscribePresence(presenceHandle));
}
+ //SubscribeDevicePresence Test
+ TEST(SubscribeDevicePresenceTest, DISABLED_SubscribeDevicePresenceWithValidParameters)
+ {
+ std::string hostAddress = "192.168.1.2:5000";
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
+ QueryParamsList queryParams = {};
+
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::subscribeDevicePresence(presenceHandle,
+ hostAddress, queryParams, CT_DEFAULT, &onObserve));
+ }
+
+ TEST(SubscribeDevicePresenceTest, SubscribeDevicePresenceWithNullHost)
+ {
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
+ QueryParamsList queryParams = {};
+
+ EXPECT_ANY_THROW(OCPlatform::subscribeDevicePresence(presenceHandle,
+ nullptr, queryParams, CT_DEFAULT, &onObserve));
+ }
+
+ TEST(SubscribeDevicePresenceTest, SubscribeDevicePresenceWithNullOnObserve)
+ {
+ std::string hostAddress = "192.168.1.2:5000";
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
+ QueryParamsList queryParams = {};
+
+ EXPECT_ANY_THROW(OCPlatform::subscribeDevicePresence(presenceHandle,
+ hostAddress, queryParams, CT_DEFAULT, NULL));
+ }
+
+ TEST(SubscribeDevicePresenceTest, DISABLED_UnsubscribePresenceWithValidHandle)
+ {
+ std::string hostAddress = "192.168.1.2:5000";
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
+ QueryParamsList queryParams = {};
+
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::subscribeDevicePresence(presenceHandle,
+ hostAddress, queryParams, CT_DEFAULT, &onObserve));
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::unsubscribePresence(presenceHandle));
+ }
+
TEST(FindDirectPairingTest, FindDirectPairingNullCallback)
{
EXPECT_ANY_THROW(OCPlatform::findDirectPairingDevices(1, nullptr));
std::shared_ptr<OCDirectPairing> s_dp(new OCDirectPairing(&peer));
EXPECT_ANY_THROW(OCPlatform::doDirectPairing(nullptr, pmSel, pin, nullptr));
}
+#ifdef WITH_CLOUD
+ //SignUp Test
+ TEST(SignUpTest, DISABLED_SignUpWithValidParameters)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string authProvider("AnyAuthProvider");
+ std::string authCode("AnyAuthCode");
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::signUp(host, authProvider, authCode,
+ CT_DEFAULT, &accountHandler));
+ }
+
+ TEST(SignUpTest, SignUpWithNullCallback)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string authProvider("AnyAuthProvider");
+ std::string authCode("AnyAuthCode");
+ EXPECT_ANY_THROW(OCPlatform::signUp(host, authProvider, authCode, CT_DEFAULT, nullptr));
+ }
+
+ //SignIn Test
+ TEST(SignInTest, DISABLED_SignInWithValidParameters)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string accessToken("AnyAccessToken");
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::signIn(host, accessToken, CT_DEFAULT, &accountHandler));
+ }
+
+ TEST(SignInTest, SignInWithNullCallback)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string accessToken("AnyAccessToken");
+ EXPECT_ANY_THROW(OCPlatform::signIn(host, accessToken, CT_DEFAULT, nullptr));
+ }
+
+ //SignOut Test
+ TEST(SignOutTest, DISABLED_SignOutWithValidParameters)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string accessToken("AnyAccessToken");
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::signOut(host, accessToken,
+ CT_DEFAULT, &accountHandler));
+ }
+
+ TEST(SignOutTest, SignOutWithNullCallback)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string accessToken("AnyAccessToken");
+ EXPECT_ANY_THROW(OCPlatform::signOut(host, accessToken, CT_DEFAULT, nullptr));
+ }
+
+ //RefreshAccessToken Test
+ TEST(RefreshAccessTokenTest, DISABLED_RefreshAccessTokenWithValidParameters)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string refreshToken("AnyRefreshToken");
+ EXPECT_EQ(OC_STACK_OK, OCPlatform::refreshAccessToken(host, refreshToken,
+ CT_DEFAULT, &accountHandler));
+ }
+
+ TEST(RefreshAccessTokenTest, RefreshAccessTokenWithNullCallback)
+ {
+ std::string host("coap+tcp://192.168.1.2:5000");
+ std::string refreshToken("AnyRefreshToken");
+ EXPECT_ANY_THROW(OCPlatform::refreshAccessToken(host, refreshToken, CT_DEFAULT, nullptr));
+ }
+#endif // WITH_CLOUD
}
if unittests_env.get('LOGGING'):
unittests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if unittests_env.get('WITH_CLOUD'):
+ unittests_env.AppendUnique(CPPDEFINES = ['WITH_CLOUD'])
+
######################################################################
# Source files and Targets
######################################################################
RCSRepresentation RCSRepresentation::fromOCRepresentation(const OC::OCRepresentation& ocRep)
{
- return RCSRepresentation(ocRep.getUri(), ocRep.getResourceInterfaces(),
+ RCSRepresentation rcsRep(ocRep.getUri(), ocRep.getResourceInterfaces(),
ocRep.getResourceTypes(),
ResourceAttributesConverter::fromOCRepresentation(ocRep));
+
+ // Convert child representations
+ for (auto &childOCRep : ocRep.getChildren())
+ {
+ rcsRep.addChild(fromOCRepresentation(childOCRep));
+ }
+
+ return rcsRep;
}
OC::OCRepresentation RCSRepresentation::toOCRepresentation(const RCSRepresentation& rcsRep)
#include "RCSResourceAttributes.h"
#include "ExpiryTimer.h"
+#include "ocrandom.h"
+
namespace OIC
{
namespace Service
CacheID DataCache::generateCacheID()
{
CacheID retID = 0;
- srand(time(NULL));
-
while (1)
{
if (findSubscriber(retID).first == 0 && retID != 0)
{
break;
}
- retID = rand();
- }
+ retID = OCGetRandom();
+ }
return retID;
}