Fixed some line endings.
Fixed some line lengths.
Fixed a series of memory leaks in C++ callbacks which assumed the C stack owned/deleted OCCallbackData
Patch 2: Removed deletion of function pointers becaues GCC says this violates the C spec.
Patch 3: Comments from Joey regarding the comment on the OCClientContextDeleter typedef
Patch 4: changed deleter to deleteCallback per sashi's suggestion
Change-Id: I0fb71896afac93356c1bd2f4916eb9f3eaa0ad13
OCClientResponseHandler callBack;
// callback context data
void * context;
+ // callback method to delete context data
+ OCClientContextDeleter deleteCallback;
// when a response is recvd with this token, above callback will be invoked
OCCoAPToken * token;
// Invocation handle tied to original call to OCDoResource()
OCDoHandle handle;
- // This is used to determine if all responses should be consumed or not. (For now, only pertains to OC_REST_OBSERVE_ALL Vs. OC_REST_OBSERVE functionality)
+ // This is used to determine if all responses should be consumed or not.
+ // (For now, only pertains to OC_REST_OBSERVE_ALL Vs. OC_REST_OBSERVE functionality)
OCMethod method;
// This is the sequence identifier the server applies to the invocation tied to 'handle'.
uint32_t sequenceNumber;
/**
* Client applications implement this callback to consume responses received from Servers.
*/
-typedef OCStackApplicationResult (* OCClientResponseHandler)(void *context, OCDoHandle handle, OCClientResponse * clientResponse);
+typedef OCStackApplicationResult (* OCClientResponseHandler)(void *context, OCDoHandle handle,
+ OCClientResponse * clientResponse);
+/**
+ * Client applications using a context pointer implement this callback to delete the
+ * context upon removal of the callback/context pointer from the internal callback-list
+ */
+typedef void (* OCClientContextDeleter)(void *context);
/*
* This info is passed from application to OC Stack when initiating a request to Server
typedef struct {
void *context;
OCClientResponseHandler cb;
+ OCClientContextDeleter cd;
} OCCallbackData;
/**
cbData.cb = cb;
cbData.context = (void*)CTX_VAL;
-
+ cbData.cd = NULL;
ret = OCDoResource(&handle, method, query.str().c_str(), 0,
(method == OC_REST_PUT) ? putPayload.c_str() : NULL,
qos, &cbData);
}
cbData.cb = discoveryReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
{
getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
cbData.cb = getReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
{
obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
cbData.cb = getReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
"/a/sroom?if=oc.mi.b";
cbData.cb = putReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(), OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
cbData.cb = getReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
{
cbData.cb = discoveryReqCB;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
if (ret != OC_STACK_OK)
{
if (cbNode) {
cbNode->callBack = cbData->cb;
cbNode->context = cbData->context;
+ cbNode->deleteCallback = cbData->cd;
cbNode->token = token;
cbNode->handle = handle;
cbNode->method = method;
OCFree(cbNode->token);
OCFree(cbNode->handle);
OCFree(cbNode->requestUri);
+ if(cbNode->deleteCallback)
+ {
+ cbNode->deleteCallback(cbNode->context);
+ }
+
#ifdef WITH_PRESENCE
if(cbNode->presence) {
OCFree(cbNode->presence->timeOut);
ClientCB* out = NULL;
if(token) {
LL_FOREACH(cbList, out) {
- if((out->token->tokenLength == token->tokenLength) && (memcmp(out->token->token, token->token, token->tokenLength) == 0) ) {
+ if((out->token->tokenLength == token->tokenLength) &&
+ (memcmp(out->token->token, token->token, token->tokenLength) == 0) ) {
return out;
}
}
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
cbData.cb = asyncDoResourcesCallback;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
//EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
EXPECT_EQ(OC_STACK_OK, OCStop());
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
cbData.cb = asyncDoResourcesCallback;
cbData.context = (void*)CTX_VAL;
+ cbData.cd = NULL;
EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
//EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
EXPECT_EQ(OC_STACK_OK, OCStop());
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <new>
#include "InProcClientWrapper.h"
#include "ocstack.h"
{
OCStackResult result;
- OCCallbackData* cbdata = new OCCallbackData();
+ OCCallbackData cbdata = {0};
ListenContext* context = new ListenContext();
context->callback = callback;
context->clientWrapper = shared_from_this();
- cbdata->context = static_cast<void*>(context);
- cbdata->cb = listenCallback;
+ cbdata.context = static_cast<void*>(context);
+ cbdata.cb = listenCallback;
+ cbdata.cd = [](void* c){delete static_cast<ListenContext*>(c);};
auto cLock = m_csdkLock.lock();
if(cLock)
resourceType.c_str(),
nullptr, nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- cbdata);
+ &cbdata);
}
else
{
const std::string& uri, const QueryParamsMap& queryParams, GetCallback& callback)
{
OCStackResult result;
- OCCallbackData* cbdata = new OCCallbackData();
+ OCCallbackData cbdata = {0};
+
GetContext* ctx = new GetContext();
ctx->callback = callback;
- cbdata->context = static_cast<void*>(ctx);
- cbdata->cb = &getResourceCallback;
+ cbdata.context = static_cast<void*>(ctx);
+ cbdata.cb = &getResourceCallback;
+ cbdata.cd = [](void* c){delete static_cast<GetContext*>(c);};
// TODO: in the future the cstack should be combining these two strings!
ostringstream os;
result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(),
nullptr, nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- cbdata);
+ &cbdata);
}
else
{
const QueryParamsMap& queryParams, PutCallback& callback)
{
OCStackResult result;
- OCCallbackData* cbdata = new OCCallbackData();
+ OCCallbackData cbdata = {0};
+
SetContext* ctx = new SetContext();
ctx->callback = callback;
- cbdata->cb = &setResourceCallback;
+ cbdata.cb = &setResourceCallback;
+ cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.context = static_cast<void*>(ctx);
// TODO: in the future the cstack should be combining these two strings!
ostringstream os;
os << host << assembleSetResourceUri(uri, queryParams).c_str();
// TODO: end of above
- cbdata->context = static_cast<void*>(ctx);
auto cLock = m_csdkLock.lock();
if(cLock)
os.str().c_str(), nullptr,
assembleSetResourcePayload(attributes).c_str(),
static_cast<OCQualityOfService>(m_cfg.QoS),
- cbdata);
+ &cbdata);
}
else
{
ObserveCallback& callback)
{
OCStackResult result;
- OCCallbackData* cbdata = new OCCallbackData();
+ OCCallbackData cbdata = {0};
+
ObserveContext* ctx = new ObserveContext();
ctx->callback = callback;
- cbdata->context = static_cast<void*>(ctx);
- cbdata->cb = &observeResourceCallback;
+ cbdata.context = static_cast<void*>(ctx);
+ cbdata.cb = &observeResourceCallback;
+ cbdata.cd = [](void* c){delete static_cast<ObserveContext*>(c);};
OCMethod method;
if (observeType == ObserveType::Observe)
os.str().c_str(), nullptr,
nullptr,
static_cast<OCQualityOfService>(m_cfg.QoS),
- cbdata);
+ &cbdata);
}
else
{
const std::string& host, SubscribeCallback& presenceHandler)
{
OCStackResult result;
- OCCallbackData* cbdata = new OCCallbackData();
+ OCCallbackData cbdata = {0};
+
SubscribePresenceContext* ctx = new SubscribePresenceContext();
ctx->callback = presenceHandler;
- cbdata->cb = &subscribePresenceCallback;
- cbdata->context = static_cast<void*>(ctx);
-
+ cbdata.cb = &subscribePresenceCallback;
+ cbdata.context = static_cast<void*>(ctx);
+ cbdata.cd = [](void* c){delete static_cast<SubscribePresenceContext*>(c);};
auto cLock = m_csdkLock.lock();
std::ostringstream os;
if(cLock)
{
result = OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
- OC_NON_CONFIRMABLE, cbdata);
+ OC_NON_CONFIRMABLE, &cbdata);
}
else
{