// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <string.h>
#include "ocstack.h"
#include "ocserverrequest.h"
#include "ocresourcehandler.h"
+#include "ocmalloc.h"
+
+#include "cacommon.h"
+#include "cainterface.h"
+
+#include "utlist.h"
+#include "pdu.h"
// Module Name
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
static struct OCServerRequest * serverRequestList = NULL;
static struct OCServerResponse * serverResponseList = NULL;
-OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token)
+//-------------------------------------------------------------------------------------------------
+// Local functions
+//-------------------------------------------------------------------------------------------------
+
+/**
+ * Add a server response to the server response list
+ *
+ * @param response initialized server response that is created by this function
+ * @param requestHandle - handle of the response
+ *
+ * @return
+ * OCStackResult
+ */
+static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
{
+ OCServerResponse * serverResponse = NULL;
+
+ serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
+ VERIFY_NON_NULL(serverResponse);
+
+ serverResponse->payload = (char *) OCCalloc(1, MAX_RESPONSE_LENGTH);
+ VERIFY_NON_NULL(serverResponse->payload);
+
+ serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
+ serverResponse->requestHandle = requestHandle;
+
+ *response = serverResponse;
+ OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+ LL_APPEND (serverResponseList, serverResponse);
+ return OC_STACK_OK;
+
+exit:
+ if (serverResponse)
+ {
+ OCFree(serverResponse);
+ serverResponse = NULL;
+ }
+ *response = NULL;
+ return OC_STACK_NO_MEMORY;
+}
+
+/**
+ * Delete a server request from the server request list
+ *
+ * @param serverRequest - server request to delete
+ */
+static void DeleteServerRequest(OCServerRequest * serverRequest)
+{
+ if(serverRequest)
+ {
+ LL_DELETE(serverRequestList, serverRequest);
+ OCFree(serverRequest->requestToken);
+ OCFree(serverRequest);
+ serverRequest = NULL;
+ OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+ }
+}
+
+/**
+ * Delete a server response from the server response list
+ *
+ * @param serverResponse - server response to delete
+ */
+static void DeleteServerResponse(OCServerResponse * serverResponse)
+{
+ if(serverResponse)
+ {
+ LL_DELETE(serverResponseList, serverResponse);
+ OCFree(serverResponse->payload);
+ OCFree(serverResponse);
+ OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+ }
+}
+
+/**
+ * Find a server response and delete it from the server response list
+ *
+ * @param serverResponse - server response to find and delete
+ */
+static void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
+{
+ OCServerResponse* tmp;
+ if(serverResponse)
+ {
+ LL_FOREACH(serverResponseList, tmp)
+ {
+ if (serverResponse == tmp)
+ {
+ DeleteServerResponse(tmp);
+ return;
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+// Internal APIs
+//-------------------------------------------------------------------------------------------------
+
+/**
+ * Get a server request from the server request list using the specified token.
+ *
+ * @param token - token of server request
+ * @param tokenLength - length of token
+ *
+ * @return
+ * OCServerRequest*
+ */
+OCServerRequest * GetServerRequestUsingToken (const CAToken_t token, uint8_t tokenLength)
+{
+ if(!token)
+ {
+ OC_LOG(ERROR, TAG, PCF("Invalid Parameter Token"));
+ return NULL;
+ }
+
OCServerRequest * out = NULL;
LL_FOREACH (serverRequestList, out)
{
OC_LOG(INFO, TAG,PCF("comparing tokens"));
- OC_LOG_BUFFER(INFO, TAG, token.token, token.tokenLength);
- OC_LOG_BUFFER(INFO, TAG, out->requestToken.token, out->requestToken.tokenLength);
- if((out->requestToken.tokenLength == token.tokenLength) &&
- (memcmp(out->requestToken.token, token.token, token.tokenLength) == 0))
+ OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
+ OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->requestToken, tokenLength);
+ if(memcmp(out->requestToken, token, tokenLength) == 0)
{
return out;
}
}
- OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
return NULL;
}
+/**
+ * Get a server request from the server request list using the specified handle
+ *
+ * @param handle - handle of server request
+ * @return
+ * OCServerRequest*
+ */
OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
{
OCServerRequest * out = NULL;
return out;
}
}
- OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
return NULL;
}
+/**
+ * Get a server response from the server response list using the specified handle
+ *
+ * @param handle - handle of server response
+ *
+ * @return
+ * OCServerResponse*
+ */
OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
{
OCServerResponse * out = NULL;
return out;
}
}
- OC_LOG(INFO, TAG, PCF("Server Response not found!!"));
+ OC_LOG(ERROR, TAG, PCF("Server Response not found!!"));
return NULL;
}
+/**
+ * Add a server request to the server request list
+ *
+ * @param request - initialized server request that is created by this function
+ * @param coapID - ID of CoAP pdu
+ * @param delayedResNeeded - delayed response required 0=no 1=yes
+ * @param secured - secure endpoint 0=no 1=yes
+ * @param notificationFlag - //TODO: remove - does not appear to be used any longer
+ * @param method - RESTful method
+ * @param numRcvdVendorSpecificHeaderOptions - number of received vendor specific header options
+ * @param observationOption - value of observation option
+ * @param qos - request QOS
+ * @param query - request query
+ * @param rcvdVendorSpecificHeaderOptions - received vendor specific header options
+ * @param reqJSONPayload - request JSON payload
+ * @param requestToken - request token
+ * @param tokenLength - request token length
+ * @param resourceUrl - URL of resource
+ * @param reqTotalSize - total size of the request
+ * @param addressInfo - CA Address
+ * @param connectivityType - connection type
+ *
+ * @return
+ * OCStackResult
+ */
OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
- OCQualityOfService qos, unsigned char * query,
+ OCQualityOfService qos, char * query,
OCHeaderOption * rcvdVendorSpecificHeaderOptions,
- unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
- OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize)
+ char * reqJSONPayload, CAToken_t requestToken,
+ uint8_t tokenLength,
+ char * resourceUrl, size_t reqTotalSize,
+ CAAddress_t *addressInfo, CATransportType_t connectivityType)
{
OCServerRequest * serverRequest = NULL;
- serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
+ //Note: OCServerRequest includes 1 byte for the JSON Payload. payloadSize is calculated
+ //as the required length of the string, so this will result in enough room for the
+ //null terminator as well.
+ serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) +
+ (reqTotalSize ? reqTotalSize : 1) - 1);
VERIFY_NON_NULL(serverRequest);
serverRequest->coapID = coapID;
serverRequest->qos = qos;
serverRequest->ehResponseHandler = HandleSingleResponse;
serverRequest->numResponses = 1;
+
if(query)
{
- memcpy(serverRequest->query, query, strlen((const char *)query) + 1);
+ strncpy((char*)serverRequest->query,
+ (const char*)query, sizeof(serverRequest->query) - 1);
}
+
if(rcvdVendorSpecificHeaderOptions)
{
memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
}
- if(reqJSONPayload)
+ if(reqJSONPayload && reqTotalSize)
{
- memcpy((void *)serverRequest->reqJSONPayload, (void *)reqJSONPayload,
- strlen((const char *)reqJSONPayload) + 1);
+ // destination is at least 1 greater than the source, so a NULL always exists in the
+ // last character
+ strncpy((char*)serverRequest->reqJSONPayload,
+ (const char*)reqJSONPayload, reqTotalSize - 1);
}
serverRequest->requestComplete = 0;
if(requestToken)
{
- memcpy(&serverRequest->requestToken, requestToken, sizeof(OCCoAPToken));
+ // If tokenLength is zero, the return value depends on the
+ // particular library implementation (it may or may not be a null pointer).
+ if (tokenLength)
+ {
+ serverRequest->requestToken = (CAToken_t) OCMalloc(tokenLength);
+ VERIFY_NON_NULL(serverRequest->requestToken);
+ memcpy(serverRequest->requestToken, requestToken, tokenLength);
+ }
+
}
- if(requesterAddr)
+ serverRequest->tokenLength = tokenLength;
+
+ if(resourceUrl)
{
- memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr));
+ strncpy((char*)serverRequest->resourceUrl,
+ (const char*)resourceUrl, sizeof(serverRequest->resourceUrl) - 1);
}
- if(resourceUrl)
+
+ if (addressInfo)
{
- memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1);
+ serverRequest->addressInfo = *addressInfo;
}
+ serverRequest->connectivityType = connectivityType;
+
*request = serverRequest;
OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
LL_APPEND (serverRequestList, serverRequest);
return OC_STACK_NO_MEMORY;
}
-OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
-{
- OCServerResponse * serverResponse = NULL;
-
- serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
- VERIFY_NON_NULL(serverResponse);
-
- serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
- VERIFY_NON_NULL(serverResponse->payload);
- memset(serverResponse->payload, 0, sizeof(MAX_RESPONSE_LENGTH));
-
- serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
- serverResponse->requestHandle = requestHandle;
-
- *response = serverResponse;
- OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
- LL_APPEND (serverResponseList, serverResponse);
- return OC_STACK_OK;
-
-exit:
- if (serverResponse)
- {
- OCFree(serverResponse);
- serverResponse = NULL;
- }
- *response = NULL;
- return OC_STACK_NO_MEMORY;
-}
-
-// Form the OCEntityHandlerRequest struct
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
- OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
- uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+/**
+ * Form the OCEntityHandlerRequest struct that is passed to a resource's entity handler
+ *
+ * @param entityHandlerRequest - pointer to the OCEntityHandlerRequest struct that is created
+ * @param request - request handle
+ * @param method - RESTful method
+ * @param resource - resource handle
+ * @param queryBuf - resource query of request
+ * @param bufReqPayload - JSON payload of request
+ * @param numVendorOptions - number of vendor options
+ * @param vendorOptions - vendor options
+ * @param observeAction - observe action flag
+ * @param observeID - observe ID
+ *
+ * @return
+ * OCStackResult
+ */
+OCStackResult FormOCEntityHandlerRequest(
+ OCEntityHandlerRequest * entityHandlerRequest,
+ OCRequestHandle request,
+ OCMethod method,
+ OCResourceHandle resource,
+ char * queryBuf,
+ char * bufReqPayload,
+ uint8_t numVendorOptions,
+ OCHeaderOption * vendorOptions,
+ OCObserveAction observeAction,
OCObservationId observeID)
{
if (entityHandlerRequest)
return OC_STACK_INVALID_PARAM;
}
-void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
-{
- OCServerResponse* tmp;
- if(serverResponse)
- {
- LL_FOREACH(serverResponseList, tmp)
- {
- if (serverResponse == tmp)
- {
- DeleteServerResponse(tmp);
- return;
- }
- }
- }
-}
-
-void DeleteServerResponse(OCServerResponse * serverResponse)
-{
- if(serverResponse) {
- LL_DELETE(serverResponseList, serverResponse);
- OCFree(serverResponse->payload);
- OCFree(serverResponse);
- OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
- }
-}
-
+/**
+ * Find a server request in the server request list and delete
+ *
+ * @param serverRequest - server request to find and delete
+ */
void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
{
OCServerRequest* tmp;
}
}
-void DeleteServerRequest(OCServerRequest * serverRequest)
+CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result)
{
- if(serverRequest) {
- LL_DELETE(serverRequestList, serverRequest);
- OCFree(serverRequest);
- serverRequest = NULL;
- OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+ CAResponseResult_t caResult = CA_BAD_REQ;
+
+ switch (result)
+ {
+ case OC_EH_OK:
+ caResult = CA_SUCCESS;
+ break;
+ case OC_EH_ERROR:
+ caResult = CA_BAD_REQ;
+ break;
+ case OC_EH_RESOURCE_CREATED:
+ caResult = CA_CREATED;
+ break;
+ case OC_EH_RESOURCE_DELETED:
+ caResult = CA_DELETED;
+ break;
+ case OC_EH_SLOW:
+ caResult = CA_SUCCESS;
+ break;
+ case OC_EH_FORBIDDEN:
+ caResult = CA_BAD_REQ;
+ break;
+ case OC_EH_RESOURCE_NOT_FOUND:
+ caResult = CA_NOT_FOUND;
+ break;
+ default:
+ caResult = CA_BAD_REQ;
+ break;
}
+ return caResult;
}
+
+/**
+ * Handler function for sending a response from a single resource
+ *
+ * @param ehResponse - pointer to the response from the resource
+ *
+ * @return
+ * OCStackResult
+ */
+
OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult result = OC_STACK_ERROR;
- OCServerProtocolResponse protocolResponse = {0};
+ CARemoteEndpoint_t responseEndpoint = {};
+ CAResponseInfo_t responseInfo = {};
+ CAHeaderOption_t* optionsPointer = NULL;
OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
+ if(!ehResponse || !ehResponse->requestHandle)
+ {
+ return OC_STACK_ERROR;
+ }
+
+ if(ehResponse->payloadSize >= (MAX_RESPONSE_LENGTH))// - OC_JSON_PREFIX_LEN - OC_JSON_SUFFIX_LEN))
+ {
+ OC_LOG_V(ERROR, TAG, "Response payload size was too large. Max is %hu, payload size was %hu",
+ (MAX_RESPONSE_LENGTH - OC_JSON_PREFIX_LEN - OC_JSON_SUFFIX_LEN), ehResponse->payloadSize);
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
- // Format protocol response structure with data needed for
- // sending the response
- protocolResponse.qos = serverRequest->qos;
-
- if((OCResource *)ehResponse->resourceHandle &&
- ((OCResource *)ehResponse->resourceHandle)->resourceProperties == (OCResourceProperty) 0)
- {
- ehResponse->ehResult = OC_EH_RESOURCE_DELETED;
- }
- protocolResponse.result = EntityHandlerCodeToOCStackCode(ehResponse->ehResult);
- protocolResponse.requesterAddr = &serverRequest->requesterAddr;
- protocolResponse.requestToken = &serverRequest->requestToken;
- protocolResponse.numSendVendorSpecificHeaderOptions = ehResponse->numSendVendorSpecificHeaderOptions;
- protocolResponse.sendVendorSpecificHeaderOptions = ehResponse->sendVendorSpecificHeaderOptions;
- protocolResponse.resourceUri = ehResponse->resourceUri;
- protocolResponse.delayedResNeeded = serverRequest->delayedResNeeded;
- protocolResponse.secured = serverRequest->secured;
- protocolResponse.slowFlag = serverRequest->slowFlag;
- protocolResponse.notificationFlag = serverRequest->notificationFlag;
-
- //should we put the prefix and suffix here?
- protocolResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
- if(!protocolResponse.payload)
- {
- return OC_STACK_NO_MEMORY;
- }
- strcpy((char *)protocolResponse.payload, (const char *)OC_JSON_PREFIX);
- strcat((char *)protocolResponse.payload, (const char *)ehResponse->payload);
- strcat((char *)protocolResponse.payload, (const char *)OC_JSON_SUFFIX);
- protocolResponse.payloadSize = strlen((const char *)protocolResponse.payload) + 1;
- protocolResponse.resourceUri = ehResponse->resourceUri;
-
- //revise the following
- protocolResponse.coapID = serverRequest->coapID;
+
+ // Copy the address
+ responseEndpoint.resourceUri = (CAURI_t) serverRequest->resourceUrl;
+ responseEndpoint.addressInfo = serverRequest->addressInfo;
+ responseEndpoint.transportType = serverRequest->connectivityType;
+ responseEndpoint.isSecured = serverRequest->secured;
+
+ responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult);
+
+ if(serverRequest->notificationFlag && serverRequest->qos == OC_HIGH_QOS)
+ {
+ responseInfo.info.type = CA_MSG_CONFIRM;
+ }
+ else if(serverRequest->notificationFlag && serverRequest->qos != OC_HIGH_QOS)
+ {
+ responseInfo.info.type = CA_MSG_NONCONFIRM;
+ }
+ else if(!serverRequest->notificationFlag && !serverRequest->slowFlag &&
+ serverRequest->qos == OC_HIGH_QOS)
+ {
+ responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
+ }
+ else if(!serverRequest->notificationFlag && serverRequest->slowFlag &&
+ serverRequest->qos == OC_HIGH_QOS)
+ {
+ responseInfo.info.type = CA_MSG_CONFIRM;
+ }
+ else if(!serverRequest->notificationFlag)
+ {
+ responseInfo.info.type = CA_MSG_NONCONFIRM;
+ }
+
+ responseInfo.info.messageId = serverRequest->coapID;
+ responseInfo.info.token = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
+ if (!responseInfo.info.token)
+ {
+ OC_LOG(FATAL, TAG, "Response Info Token is NULL");
+ return result;
+ }
+
+ memcpy(responseInfo.info.token, serverRequest->requestToken, serverRequest->tokenLength);
+ responseInfo.info.tokenLength = serverRequest->tokenLength;
+
if(serverRequest->observeResult == OC_STACK_OK)
{
- protocolResponse.observationOption = serverRequest->observationOption;
+ responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions + 1;
+ }
+ else
+ {
+ responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions;
+ }
+
+ if(responseInfo.info.numOptions > 0)
+ {
+ responseInfo.info.options = (CAHeaderOption_t *)
+ OCCalloc(responseInfo.info.numOptions,
+ sizeof(CAHeaderOption_t));
+
+ if(!responseInfo.info.options)
+ {
+ OC_LOG(FATAL, TAG, PCF("options is NULL"));
+ OCFree(responseInfo.info.token);
+ return OC_STACK_NO_MEMORY;
+ }
+
+ optionsPointer = responseInfo.info.options;
+
+ // TODO: This exposes CoAP specific details. At some point, this should be
+ // re-factored and handled in the CA layer.
+ if(serverRequest->observeResult == OC_STACK_OK)
+ {
+ responseInfo.info.options[0].protocolID = CA_COAP_ID;
+ responseInfo.info.options[0].optionID = COAP_OPTION_OBSERVE;
+ responseInfo.info.options[0].optionLength = sizeof(uint32_t);
+ memcpy(responseInfo.info.options[0].optionData,
+ &(serverRequest->observationOption), sizeof(uint32_t));
+
+ // Point to the next header option before copying vender specific header options
+ optionsPointer += 1;
+ }
+
+ if (ehResponse->numSendVendorSpecificHeaderOptions)
+ {
+ memcpy(optionsPointer, ehResponse->sendVendorSpecificHeaderOptions,
+ sizeof(OCHeaderOption) *
+ ehResponse->numSendVendorSpecificHeaderOptions);
+ }
+ }
+ else
+ {
+ responseInfo.info.options = NULL;
+ }
+
+ char payload[MAX_RESPONSE_LENGTH + OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN] = {};
+
+ // Put the JSON prefix and suffix around the payload
+ strcpy(payload, (const char *)OC_JSON_PREFIX);
+ strncat(payload, (const char *)ehResponse->payload, ehResponse->payloadSize);
+ strcat(payload, (const char *)OC_JSON_SUFFIX);
+ responseInfo.info.payload = (CAPayload_t)payload;
+
+ #ifdef WITH_PRESENCE
+ //TODO: Add other connectivity types to CAConnTypes[] when enabled
+ CATransportType_t CAConnTypes[] = {CA_IPV4};
+ const char * connTypes[] = {"ip transport"};
+ int size = sizeof(CAConnTypes)/ sizeof(CATransportType_t);
+ CATransportType_t connType = responseEndpoint.transportType;
+ CAResult_t caResult = CA_STATUS_FAILED;
+ result = OC_STACK_OK;
+
+ //Sending response on all n/w interfaces
+ for(int i = 0; i < size; i++ )
+ {
+ responseEndpoint.transportType = (CATransportType_t)(connType & CAConnTypes[i]);
+ if(responseEndpoint.transportType)
+ {
+ //The result is set to OC_STACK_OK only if CASendResponse succeeds in sending the
+ //response on all the n/w interfaces else it is set to OC_STACK_ERROR
+ caResult = CASendResponse(&responseEndpoint, &responseInfo);
+ if(caResult != CA_STATUS_OK)
+ {
+ OC_LOG_V(ERROR, TAG, "CASendResponse failed on %s", connTypes[i]);
+ result = CAResultToOCResult(caResult);
+ }
+ else
+ {
+ OC_LOG_V(INFO, TAG, "CASendResponse succeeded on %s", connTypes[i]);
+ }
+ }
+ }
+ #else
+ CAResult_t caResult = CASendResponse(&responseEndpoint, &responseInfo);
+ if(caResult != CA_STATUS_OK)
+ {
+ OC_LOG(ERROR, TAG, PCF("CASendResponse failed"));
+ result = CAResultToOCResult(caResult);
}
else
{
- protocolResponse.observationOption = OC_OBSERVE_NO_OPTION;
+ result = OC_STACK_OK;
}
- // Make call to OCCoAP layer
- result = OCDoCoAPResponse(&protocolResponse);
+ #endif
- OCFree(protocolResponse.payload);
+ OCFree(responseInfo.info.token);
+ OCFree(responseInfo.info.options);
//Delete the request
FindAndDeleteServerRequest(serverRequest);
return result;
}
+/**
+ * Handler function for sending a response from multiple resources, such as a collection.
+ * Aggregates responses from multiple resource until all responses are received then sends the
+ * concatenated response
+ *
+ * TODO: Need to add a timeout in case a (remote?) resource does not respond
+ *
+ * @param ehResponse - pointer to the response from the resource
+ *
+ * @return
+ * OCStackResult
+ */
OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult stackRet = OC_STACK_ERROR;
OCServerRequest * serverRequest = NULL;
OCServerResponse * serverResponse = NULL;
+ uint16_t bufferNeeded = 0;
+
+ if(!ehResponse || !ehResponse->payload)
+ {
+ OC_LOG(ERROR, TAG, PCF("HandleAggregateResponse invalid parameters"));
+ return OC_STACK_INVALID_PARAM;
+ }
OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
VERIFY_NON_NULL(serverResponse->payload);
}
- if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 &&
- serverRequest->numResponses == 1) ||
- (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 &&
- serverRequest->numResponses > 1))
+ // If there is more than 1 response, then we need to allow for a null-termination
+ // in the server response payload buffer AND the JSON response separator
+ bufferNeeded = ehResponse->payloadSize + 1;
+ if (serverRequest->numResponses > 1)
{
- OC_LOG(INFO, TAG, PCF("There is room in response buffer"));
+ bufferNeeded += strlen(OC_JSON_SEPARATOR_STR);
+ }
+ if(serverResponse->remainingPayloadSize >= bufferNeeded)
+ {
+ OC_LOG(ERROR, TAG, PCF("There is room in response buffer"));
// append
- snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload);
+ strncat((char *)serverResponse->payload,
+ (char *)ehResponse->payload,
+ serverResponse->remainingPayloadSize);
OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload);
- serverResponse->remainingPayloadSize -= ehResponse->payloadSize;
+ serverResponse->remainingPayloadSize -= strlen((char *)ehResponse->payload);
(serverRequest->numResponses)--;
if(serverRequest->numResponses == 0)
{
}
else
{
- OC_LOG(INFO, TAG, PCF("More response fragment to come"));
- // TODO: we should consider using strcat rather than setting a char by char here!
- snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR);
+ OC_LOG(INFO, TAG, PCF("More response fragments to come"));
+ strncat((char *)serverResponse->payload,
+ OC_JSON_SEPARATOR_STR,
+ serverResponse->remainingPayloadSize);
OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload);
- (serverResponse->remainingPayloadSize)--;
+ serverResponse->remainingPayloadSize -= strlen(OC_JSON_SEPARATOR_STR);
stackRet = OC_STACK_OK;
}
}
else
{
- OC_LOG(INFO, TAG, PCF("No room in response buffer"));
+ OC_LOG(ERROR, TAG, PCF("No room in response buffer"));
//Delete the request and response
FindAndDeleteServerRequest(serverRequest);
FindAndDeleteServerResponse(serverResponse);
exit:
return stackRet;
}
+