}
bool Callback::MatchAllRequiredResourceTypes(
- std::vector<std::string>& requiredResourceTypes,
- std::vector<std::string>& deviceResourceTypes)
+ const std::vector<std::string>& requiredResourceTypes,
+ const std::vector<std::string>& deviceResourceTypes)
{
for (auto const& targetResourceType : requiredResourceTypes)
{
void Callback::DeviceDiscoveryCallback(
bool deviceResponding,
bool newInfoLearntAboutDevice,
- InternalDeviceInfo deviceInfo,
- std::vector<std::string> deviceResourceTypeList)
+ const InternalDeviceInfo& deviceInfo,
+ const std::vector<std::string>& deviceResourceTypeList)
{
// Create IPCADiscoveredDeviceInfo object for callback.
IPCADiscoveredDeviceInfo deviceInfoUsedForCallback = {0};
// Device discovery related.
void DeviceDiscoveryCallback(bool deviceResponding,
bool newInfoLearntAboutDevice,
- InternalDeviceInfo deviceInfo,
- std::vector<std::string> resourceTypes);
+ const InternalDeviceInfo& deviceInfo,
+ const std::vector<std::string>& resourceTypes);
// resource->get() callback.
void GetCallback(IPCAStatus status,
void RequestAccessCompletionCallback(IPCAStatus status, CallbackInfo::Ptr cbInfo);
private:
- bool MatchAllRequiredResourceTypes(std::vector<std::string>& requiredResourceTypes,
- std::vector<std::string>& deviceResourceTypes);
+ bool MatchAllRequiredResourceTypes(const std::vector<std::string>& requiredResourceTypes,
+ const std::vector<std::string>& deviceResourceTypes);
private:
// Mutex for synchronization use.
// Entry point for the thread that will request access to a device.
static void RequestAccessWorkerThread(RequestAccessContext* requestContext);
- // Get DeviceDetails for devieId.
+ // Get DeviceDetails for deviceId.
IPCAStatus FindDeviceDetails(const std::string& deviceId,
DeviceDetails::Ptr& deviceDetails);
void DebugOutputOCFDevices();
void DebugOutputOCRep(const OCRepresentation& rep);
+ // Thread safe copy.
+ template <typename _T>
+ void ThreadSafeCopy(const _T& source, _T& dest);
+
private:
// Lock for sync access to protected members in OCFFramework.
std::recursive_mutex m_OCFFrameworkMutex;
ocfFramework->GetCommonResources(device);
}
- // Make a snapshot of all callbacks.
+ // Take a snapshot of callbacks for thread safe iteration.
std::vector<Callback::Ptr> callbackSnapshot;
- {
- std::lock_guard<std::recursive_mutex> lock(ocfFramework->m_OCFFrameworkMutex);
- callbackSnapshot = ocfFramework->m_callbacks;
- }
+ ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
// Callback to apps.
for (const auto& device : devicesThatAreNotResponding)
{
+ // Take a snapshot of device->discoveredResourceTypes and deviceInfo
+ // for thread safe use by the callee.
+ std::vector<std::string> resourceTypesSnapshot;
+ ocfFramework->ThreadSafeCopy(device->discoveredResourceTypes, resourceTypesSnapshot);
+
+ InternalDeviceInfo deviceInfoSnapshot;
+ ocfFramework->ThreadSafeCopy(device->deviceInfo, deviceInfoSnapshot);
+
for (const auto& callback : callbackSnapshot)
{
callback->DeviceDiscoveryCallback(
false, /* device is no longer responding to discovery */
false,
- device->deviceInfo,
- device->discoveredResourceTypes);
+ deviceInfoSnapshot,
+ resourceTypesSnapshot);
}
}
IPCAStatus OCFFramework::IPCADeviceOpenCalled(std::string& deviceId)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
// Has the app discovered the device?
DeviceDetails::Ptr deviceDetails;
IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
}
// Inform apps. If new device, the device info may come in subsequent discovery callbacks with
- // IPCA_DEVICE_UPDATED_INFO status. Make a snapshot of all callbacks.
+ // IPCA_DEVICE_UPDATED_INFO status.
+
+ // Take a snapshot of variables that may be updated by the stack during the callback.
std::vector<Callback::Ptr> callbackSnapshot;
- {
- std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
- callbackSnapshot = m_callbacks;
- }
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ std::vector<std::string> resourceTypesSnapshot;
+ ThreadSafeCopy(deviceDetails->discoveredResourceTypes, resourceTypesSnapshot);
+
+ InternalDeviceInfo deviceInfoSnapshot;
+ ThreadSafeCopy(deviceDetails->deviceInfo, deviceInfoSnapshot);
// Indicate discovery to apps.
for (const auto& callback : callbackSnapshot)
callback->DeviceDiscoveryCallback(
true,
updatedDeviceInformation,
- deviceDetails->deviceInfo,
- deviceDetails->discoveredResourceTypes);
+ deviceInfoSnapshot,
+ resourceTypesSnapshot);
}
}
// Inform apps.
- // Make a snapshot of all callbacks.
+ // Take snapshots of variables that may be updated during the callback.
std::vector<Callback::Ptr> callbackSnapshot;
- {
- std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
- callbackSnapshot = m_callbacks;
- }
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ std::vector<std::string> resourceTypesSnapshot;
+ ThreadSafeCopy(deviceDetails->discoveredResourceTypes, resourceTypesSnapshot);
+
+ InternalDeviceInfo deviceInfoSnapshot;
+ ThreadSafeCopy(deviceDetails->deviceInfo, deviceInfoSnapshot);
// Indicate discovery to apps.
for (const auto& callback : callbackSnapshot)
callback->DeviceDiscoveryCallback(
true, /* device is responding */
true, /* this is an updated device info */
- deviceDetails->deviceInfo,
- deviceDetails->discoveredResourceTypes);
+ deviceInfoSnapshot,
+ resourceTypesSnapshot);
}
DebugOutputOCFDevices();
IPCAStatus status = MapOCStackResultToIPCAStatus((OCStackResult)eCode);
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->SetCallback(status, rep, callbackInfo);
}
status = IPCA_FAIL;
}
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->GetCallback(status, rep, callbackInfo);
}
status = IPCA_FAIL;
}
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->ObserveCallback(status, rep, callbackInfo);
}
IPCAStatus status = MapOCStackResultToIPCAStatus((OCStackResult)eCode);
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->DeleteResourceCallback(status, callbackInfo);
}
const std::string& targetResourcePath,
const std::string& targetRT)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
// Return resource matching resource path.
if (deviceDetails->resourceMap.find(targetResourcePath) != deviceDetails->resourceMap.end())
{
IPCAStatus OCFFramework::CopyDeviceInfo(std::string& deviceId, IPCADeviceInfo** callerDeviceInfo)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
*callerDeviceInfo = nullptr;
DeviceDetails::Ptr deviceDetails;
IPCAStatus OCFFramework::CopyPlatformInfo(std::string& deviceId,
IPCAPlatformInfo** callerPlatformInfo)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
*callerPlatformInfo = nullptr;
DeviceDetails::Ptr deviceDetails;
std::string& deviceId,
std::vector<std::string>& resourcePathList)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
DeviceDetails::Ptr deviceDetails;
IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
if (status != IPCA_OK)
ResourceInfoType resourceInfoType,
std::vector<std::string>& resourceInfo)
{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+
DeviceDetails::Ptr deviceDetails;
IPCAStatus status = FindDeviceDetails(deviceId, deviceDetails);
if (status != IPCA_OK)
size_t passwordBufferSize = OXM_PRECONFIG_PIN_MAX_SIZE + 1;
memset(passwordBuffer, 0, passwordBufferSize);
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
// We need to set the preconfigured pin before attempting to do MOT.
// Callback to the app asking for the password.
- for (const auto& callback : ocfFramework->m_callbacks)
+ for (const auto& callback : callbackSnapshot)
{
callback->PasswordInputCallback(deviceId,
IPCA_OWNERSHIP_TRANSFER_PRECONFIGURED_PIN,
}
else
{
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
// This app is already a subowner of the device
- for (const auto& callback : ocfFramework->m_callbacks)
+ for (const auto& callback : callbackSnapshot)
{
callback->RequestAccessCompletionCallback(
IPCA_SECURITY_UPDATE_REQUEST_FINISHED,
// success or failure of doMultipleOwnershipTransfer.
if (IPCA_OK != status)
{
- for (const auto& callback : ocfFramework->m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ocfFramework->ThreadSafeCopy(ocfFramework->m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->RequestAccessCompletionCallback(callbackStatus, callbackInfo);
}
}
}
-void OCFFramework::OnMultipleOwnershipTransferCompleteCallback(PMResultList_t* result,
+void OCFFramework::OnMultipleOwnershipTransferCompleteCallback(
+ PMResultList_t* result,
bool error,
std::string deviceId,
CallbackInfo::Ptr callbackInfo)
status = IPCA_SECURITY_UPDATE_REQUEST_FAILED;
}
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->RequestAccessCompletionCallback(status, callbackInfo);
}
OCConvertUuidToString(deviceId.id, uuidString);
strDeviceId = uuidString;
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->PasswordInputCallback(
strDeviceId,
{
OC_UNUSED(passwordBufferSize);
- for (const auto& callback : m_callbacks)
+ // Take a snapshot of callbacks for thread safe iteration.
+ std::vector<Callback::Ptr> callbackSnapshot;
+ ThreadSafeCopy(m_callbacks, callbackSnapshot);
+
+ for (const auto& callback : callbackSnapshot)
{
callback->PasswordDisplayCallback("",
IPCA_OWNERSHIP_TRANSFER_RANDOM_PIN,
}
}
}
+
+template <typename _T>
+void OCFFramework::ThreadSafeCopy(const _T& source, _T& dest)
+{
+ std::lock_guard<std::recursive_mutex> lock(m_OCFFrameworkMutex);
+ dest = source;
+}
}
// Start the test elevator once and use it through out the rest of the tests.
-TEST(ElevatorServerStart, DISABLED_start)
+TEST(ElevatorServerStart, start)
{
IPCASetUnitTestMode();
ASSERT_TRUE(StartElevator1());
}
// Test IoTivity api directly before subsequent tests which use IPCA apis.
-TEST(IoTivityDirect, DISABLED_IsIoTivityWorking)
+TEST(IoTivityDirect, IsIoTivityWorking)
{
ElevatorClient elevatorClient;
int loopCount;
}
};
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagNonExistenceAttribute)
+TEST_F(IPCAPropertyBagTest, PropertyBagNonExistenceAttribute)
{
EXPECT_EQ(IPCA_FAIL, IPCAPropertyBagGetValueInt(m_propertyBagHandle,
"NonexistenceAttribute", &m_intValue));
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagInt)
+TEST_F(IPCAPropertyBagTest, PropertyBagInt)
{
ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueInt(m_propertyBagHandle, "IntValue", 3));
ASSERT_EQ(IPCA_OK, IPCAPropertyBagGetValueInt(m_propertyBagHandle, "IntValue", &m_intValue));
EXPECT_EQ(3, m_intValue);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDouble)
+TEST_F(IPCAPropertyBagTest, PropertyBagDouble)
{
ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueDouble(m_propertyBagHandle,
"DoubleValue", 12345678));
"doubleValue", &m_doubleValue)); // incorrect capital case
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBool)
+TEST_F(IPCAPropertyBagTest, PropertyBagBool)
{
bool trueBool, falseBool;
EXPECT_FALSE(falseBool);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagString)
+TEST_F(IPCAPropertyBagTest, PropertyBagString)
{
ASSERT_EQ(IPCA_OK, IPCAPropertyBagSetValueString(m_propertyBagHandle,
"MyString", "Hello World"));
IPCAPropertyBagFreeString(m_charPointerValue);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagPropertyBagType)
+TEST_F(IPCAPropertyBagTest, PropertyBagPropertyBagType)
{
IPCAPropertyBagHandle propertyBagHandle1, propertyBagHandle2, propertyBagHandle3;
CreateIntPropertyBag(propertyBagHandle1, "IntValue1", 1);
IPCAPropertyBagDestroy(propertyBag3);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagIntArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagIntArrayType)
{
// array of int
int intArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
IPCAPropertyBagFreeIntArray(readBackIntArray);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagDoubleArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagDoubleArrayType)
{
// array of double
double doubleArray[] = {1.01, 2.02, 3.03, 4.04, 5.05, 6.06, 7.07, 8.08, 9.09, 10.010};
IPCAPropertyBagFreeDoubleArray(readBackDoubleArray);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagBoolArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagBoolArrayType)
{
// array of bool
bool boolArray[] = {true, true, false, false, true, false, true, false, false, false};
IPCAPropertyBagFreeBoolArray(readBackBoolArray);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagStringArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagStringArrayType)
{
// array of string
char* stringArray[] = {"hello world 1", "hello world 2", "hello world 3"};
IPCAPropertyBagFreeStringArray(readBackString, readbackStringSize);
}
-TEST_F(IPCAPropertyBagTest, DISABLED_PropertyBagPropertyBagArrayType)
+TEST_F(IPCAPropertyBagTest, PropertyBagPropertyBagArrayType)
{
IPCAPropertyBagHandle propertyBagHandle1, propertyBagHandle1A;
EXPECT_EQ(IPCA_OK, IPCAPropertyBagCreate(&propertyBagHandle1));
}
};
-TEST_F(IPCAMiscTest, DISABLED_ShouldNotAllowMultipleCallsToIPCOpen)
+TEST_F(IPCAMiscTest, ShouldNotAllowMultipleCallsToIPCOpen)
{
EXPECT_EQ(IPCA_ALREADY_OPENED, DoAnotherIPCAOpen());
}
-TEST_F(IPCAMiscTest, DISABLED_IPCAOpenShouldBeAllowedAfterIPCAClose)
+TEST_F(IPCAMiscTest, IPCAOpenShouldBeAllowedAfterIPCAClose)
{
IPCAClose(m_ipcaAppHandle);
m_ipcaAppHandle = NULL;
/*
* IPCADiscoverDevices() must be called before IPCAOpenDevice().
*/
-TEST_F(IPCAMiscTest, DISABLED_ShouldFailOpenDeviceWithoutDiscoveryFirst)
+TEST_F(IPCAMiscTest, ShouldFailOpenDeviceWithoutDiscoveryFirst)
{
IPCADeviceHandle deviceHandle;
&deviceHandle));
}
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindElevatorServer)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindElevatorServer)
{
EXPECT_TRUE(IsElevator1Discovered());
}
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindDeviceAndPlatformInfo)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindDeviceAndPlatformInfo)
{
EXPECT_EQ(IPCA_OK, ConfirmDeviceAndPlatformInfo());
}
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindElevatorResources)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindElevatorResources)
{
EXPECT_EQ(IPCA_OK, ConfirmResources());
}
-TEST_F(IPCAElevatorClient, DISABLED_DiscoveryShouldFindTargetedResourceTypes)
+TEST_F(IPCAElevatorClient, DiscoveryShouldFindTargetedResourceTypes)
{
EXPECT_EQ(IPCA_OK, ConfirmResourceTypes());
}
-TEST_F(IPCAElevatorClient, DISABLED_ShouldBeAbleToFilterOnResourceInterface)
+TEST_F(IPCAElevatorClient, ShouldBeAbleToFilterOnResourceInterface)
{
EXPECT_EQ(IPCA_OK, ConfirmResourceInterfaces());
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyGetDataFromElevatorServer)
+TEST_F(IPCAElevatorClient, SuccessfullyGetDataFromElevatorServer)
{
// Directly set target floor of the elevator to 8.
g_testElevator1.SetTargetFloor(8);
EXPECT_EQ(8, elevatorTargetFloor);
}
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailGetUnknownResource)
+TEST_F(IPCAElevatorClient, ShouldFailGetUnknownResource)
{
EXPECT_EQ(IPCA_RESOURCE_NOT_FOUND, GetUnknownResource());
}
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailSetUnknownResource)
+TEST_F(IPCAElevatorClient, ShouldFailSetUnknownResource)
{
EXPECT_EQ(IPCA_RESOURCE_NOT_FOUND, SetUnknownResource());
}
-TEST_F(IPCAElevatorClient, DISABLED_ShouldFailSetWithUnknownInterface)
+TEST_F(IPCAElevatorClient, ShouldFailSetWithUnknownInterface)
{
size_t incorrectInterfaceCount = g_testElevator1.GetIncorrectInterfaceCount();
EXPECT_EQ(true, SetUnknoownInterface());
EXPECT_EQ((incorrectInterfaceCount + 1), g_testElevator1.GetIncorrectInterfaceCount());
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullySetElevatorServerProperties)
+TEST_F(IPCAElevatorClient, SuccessfullySetElevatorServerProperties)
{
g_testElevator1.SetTargetFloor(1); // Set to known target floor.
EXPECT_EQ(8, newTargetFloor);
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyCreateAndDeleteResources)
+TEST_F(IPCAElevatorClient, SuccessfullyCreateAndDeleteResources)
{
// Do a few rounds of create resource with relative path.
size_t beforeCreateCount, afterCreateCount;
}
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfullyReceiveResourceChangeNotifications)
+TEST_F(IPCAElevatorClient, SuccessfullyReceiveResourceChangeNotifications)
{
// Set to known target floor.
g_testElevator1.SetTargetFloor(1);
StopObserve();
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfulFactoryReset)
+TEST_F(IPCAElevatorClient, SuccessfulFactoryReset)
{
EXPECT_EQ(IPCA_OK, FactoryResetElevator());
}
-TEST_F(IPCAElevatorClient, DISABLED_SuccessfulReboot)
+TEST_F(IPCAElevatorClient, SuccessfulReboot)
{
EXPECT_EQ(IPCA_OK, RebootElevator());
}
-TEST(ElevatorServerStop, DISABLED_Stop)
+TEST(ElevatorServerStop, Stop)
{
StopElevator1();
}
// Forward decl.\r
OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,\r
OCMethod method,\r
+ bool isCancelObserve,\r
const OCRepresentation& rep,\r
const QueryParamsMap& queryParametersMap,\r
PostCallback postCallback,\r
}\r
}\r
\r
+ // One time request is responded, remove the pending request.\r
+ if (pendingRequest->method & (OC_REST_POST | OC_REST_GET | OC_REST_DELETE))\r
+ {\r
+ std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+ g_requestList.erase(pendingRequest->requestNumber);\r
+ }\r
+\r
return OC_STACK_OK;\r
}\r
\r
OCEntityHandlerResult result = MockEntityHandler(\r
OC_REQUEST_FLAG,\r
OC_REST_DELETE,\r
+ false,\r
rep,\r
queryParametersMap,\r
&defaultCallback,\r
OCEntityHandlerResult result = MockEntityHandler(\r
OC_REQUEST_FLAG,\r
OC_REST_GET,\r
+ false,\r
rep,\r
queryParametersMap,\r
&defaultCallback,\r
OCEntityHandlerResult result = MockEntityHandler(\r
OC_REQUEST_FLAG,\r
OC_REST_POST,\r
+ false,\r
rep,\r
queryParametersMap,\r
attributeHandler,\r
OC_OBSERVE_FLAG,\r
(observeType == ObserveType::Observe) ?\r
OC_REST_OBSERVE : OC_REST_OBSERVE_ALL,\r
+ false,\r
rep,\r
queryParametersMap,\r
&defaultCallback,\r
// Client app's request to cancel observe request.\r
OCStackResult OCResource::cancelObserve()\r
{\r
- std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+ OCRepresentation rep;\r
+ QueryParamsMap queryParametersMap;\r
\r
- for (auto request : g_requestList)\r
- {\r
- PendingRequest::Ptr pendingRequest = request.second;\r
- if ((pendingRequest->method == OC_REST_OBSERVE) ||\r
- (pendingRequest->method == OC_REST_OBSERVE_ALL))\r
- {\r
- if (pendingRequest->mockOCResource->m_uri.compare(uri()) == 0)\r
- {\r
- g_requestList.erase(pendingRequest->requestNumber);\r
- break;\r
- }\r
- }\r
- }\r
+ OCEntityHandlerResult result = MockEntityHandler(\r
+ OC_OBSERVE_FLAG,\r
+ OC_REST_OBSERVE,\r
+ true,\r
+ rep,\r
+ queryParametersMap,\r
+ &defaultCallback,\r
+ &defaultCallback,\r
+ &defaultObserveCallback,\r
+ &defaultDeleteCallback,\r
+ uri());\r
\r
- return OC_STACK_OK;\r
+ return (result == OC_EH_OK) ? OC_STACK_OK : OC_STACK_ERROR;\r
}\r
\r
// Is resource observable.\r
// Every callback to server app is performed by this function.\r
OCEntityHandlerResult MockEntityHandler(OCEntityHandlerFlag flag,\r
OCMethod method,\r
+ bool isCancelObserve,\r
const OCRepresentation& rep,\r
const QueryParamsMap& queryParametersMap,\r
PostCallback postCallback,\r
DeleteCallback deleteCallback,\r
const std::string& uri)\r
{\r
+ OCObservationId observationIdToCancel = 0;\r
size_t requestNumber;\r
MockOCResource::Ptr mockOCResource = nullptr;\r
{\r
pendingRequest->getCallback = getCallback;\r
pendingRequest->observeCallback = observeCallback;\r
pendingRequest->deleteCallback = deleteCallback;\r
+\r
+ if (!isCancelObserve)\r
{\r
// Store the request for response.\r
std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
g_requestList[requestNumber] = pendingRequest;\r
}\r
+ else\r
+ {\r
+ // Observe request is canceled. Remove the request for observe.\r
+ std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
+ for (auto request : g_requestList)\r
+ {\r
+ PendingRequest::Ptr pendingRequest = request.second;\r
+ if (pendingRequest->method & (OC_REST_OBSERVE | OC_REST_OBSERVE_ALL))\r
+ {\r
+ if (pendingRequest->mockOCResource->m_uri.compare(uri) == 0)\r
+ {\r
+ observationIdToCancel = pendingRequest->observationId;\r
+ g_requestList.erase(pendingRequest->requestNumber);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
auto pRequest = std::make_shared<OC::OCResourceRequest>();\r
if (pRequest == nullptr)\r
if (flag & OC_OBSERVE_FLAG)\r
{\r
std::lock_guard<std::recursive_mutex> lock(g_globalMutex);\r
- entityHandlerRequest.obsInfo.action = OC_OBSERVE_REGISTER;\r
- entityHandlerRequest.obsInfo.obsId = ++g_observationId;\r
+ entityHandlerRequest.obsInfo.action = isCancelObserve ?\r
+ OC_OBSERVE_DEREGISTER : OC_OBSERVE_REGISTER;\r
+ entityHandlerRequest.obsInfo.obsId = isCancelObserve ?\r
+ observationIdToCancel : ++g_observationId;\r
pendingRequest->observationId = entityHandlerRequest.obsInfo.obsId;\r
}\r
\r