#include "oic_string.h"
#include "ocpayload.h"
#include "ocpayloadcbor.h"
+#include "logger.h"
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+#include "routingutility.h"
+#endif
#include "cacommon.h"
#include "cainterface.h"
// Module Name
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
-#define TAG PCF("ocserverrequest")
+#define TAG "ocserverrequest"
static struct OCServerRequest * serverRequestList = NULL;
static struct OCServerResponse * serverResponseList = NULL;
*/
static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
{
+ if (!response)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCServerResponse * serverResponse = NULL;
serverResponse = (OCServerResponse *) OICCalloc(1, sizeof(OCServerResponse));
serverResponse->requestHandle = requestHandle;
*response = serverResponse;
- OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+ OC_LOG(INFO, TAG, "Server Response Added!!");
LL_APPEND (serverResponseList, serverResponse);
return OC_STACK_OK;
OICFree(serverRequest->requestToken);
OICFree(serverRequest);
serverRequest = NULL;
- OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+ OC_LOG(INFO, TAG, "Server Request Removed!!");
}
}
LL_DELETE(serverResponseList, serverResponse);
OICFree(serverResponse->payload);
OICFree(serverResponse);
- OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+ OC_LOG(INFO, TAG, "Server Response Removed!!");
}
}
}
}
+/**
+ * Ensure no accept header option is included when sending responses and add routing info to
+ * outgoing response.
+ *
+ * @param object CA remote endpoint.
+ * @param requestInfo CA request info.
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+static OCStackResult OCSendResponse(const CAEndpoint_t *object, CAResponseInfo_t *responseInfo)
+{
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ // Add route info in RM option.
+ OCStackResult rmResult = RMAddInfo(object->routeData, &(responseInfo->info.options),
+ &(responseInfo->info.numOptions));
+ if(OC_STACK_OK != rmResult)
+ {
+ OC_LOG(ERROR, TAG, "Add option failed");
+ return rmResult;
+ }
+#endif
+
+ // Do not include the accept header option
+ responseInfo->info.acceptFormat = CA_FORMAT_UNDEFINED;
+ CAResult_t result = CASendResponse(object, responseInfo);
+ if(CA_STATUS_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "CASendResponse failed with CA error %u", result);
+ return CAResultToOCResult(result);
+ }
+ return OC_STACK_OK;
+}
+
//-------------------------------------------------------------------------------------------------
// Internal APIs
//-------------------------------------------------------------------------------------------------
{
if(!token)
{
- OC_LOG(ERROR, TAG, PCF("Invalid Parameter Token"));
+ OC_LOG(ERROR, TAG, "Invalid Parameter Token");
return NULL;
}
OCServerRequest * out = NULL;
- OC_LOG(INFO, TAG,PCF("Get server request with token"));
+ OC_LOG(INFO, TAG,"Get server request with token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
- OC_LOG(INFO, TAG,PCF("Found token"));
+ OC_LOG(INFO, TAG,"Found token");
LL_FOREACH (serverRequestList, out)
{
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->requestToken, tokenLength);
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, "Server Request not found!!");
return NULL;
}
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, "Server Request not found!!");
return NULL;
}
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Response not found!!"));
+ OC_LOG(ERROR, TAG, "Server Response not found!!");
return NULL;
}
OCQualityOfService qos, char * query,
OCHeaderOption * rcvdVendorSpecificHeaderOptions,
uint8_t * payload, CAToken_t requestToken, uint8_t tokenLength,
- char * resourceUrl, size_t reqTotalSize, const OCDevAddr *devAddr)
+ char * resourceUrl, size_t reqTotalSize, OCPayloadFormat acceptFormat,
+ const OCDevAddr *devAddr)
{
+ if (!request)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCServerRequest * serverRequest = NULL;
+ OC_LOG_V(INFO, TAG, "addserverrequest entry!! [%s:%u]", devAddr->addr, devAddr->port);
+
serverRequest = (OCServerRequest *) OICCalloc(1, sizeof(OCServerRequest) +
(reqTotalSize ? reqTotalSize : 1) - 1);
VERIFY_NON_NULL(devAddr);
serverRequest->observationOption = observationOption;
serverRequest->observeResult = OC_STACK_ERROR;
serverRequest->qos = qos;
+ serverRequest->acceptFormat = acceptFormat;
serverRequest->ehResponseHandler = HandleSingleResponse;
serverRequest->numResponses = 1;
serverRequest->devAddr = *devAddr;
*request = serverRequest;
- OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
+ OC_LOG(INFO, TAG, "Server Request Added!!");
LL_APPEND (serverRequestList, serverRequest);
return OC_STACK_OK;
OCDevAddr *endpoint,
OCResourceHandle resource,
char * queryBuf,
+ OCPayloadType payloadType,
uint8_t * payload,
size_t payloadSize,
uint8_t numVendorOptions,
if(payload && payloadSize)
{
- if(OCParsePayload(&entityHandlerRequest->payload, payload, payloadSize) != OC_STACK_OK)
+ if(OCParsePayload(&entityHandlerRequest->payload, payloadType,
+ payload, payloadSize) != OC_STACK_OK)
{
return OC_STACK_ERROR;
}
}
}
-CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result)
+CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result, OCMethod method)
{
- CAResponseResult_t caResult = CA_BAD_REQ;
+ CAResponseResult_t caResult;
switch (result)
{
case OC_EH_OK:
- caResult = CA_SUCCESS;
+ switch (method)
+ {
+ case OC_REST_PUT:
+ case OC_REST_POST:
+ // This Response Code is like HTTP 204 "No Content" but only used in
+ // response to POST and PUT requests.
+ caResult = CA_CHANGED;
+ break;
+ case OC_REST_GET:
+ // This Response Code is like HTTP 200 "OK" but only used in response to
+ // GET requests.
+ caResult = CA_CONTENT;
+ break;
+ default:
+ // This should not happen but,
+ // give it a value just in case but output an error
+ caResult = CA_CONTENT;
+ OC_LOG_V(ERROR, TAG, "Unexpected OC_EH_OK return code for method [d].", method);
+ }
break;
case OC_EH_ERROR:
caResult = CA_BAD_REQ;
caResult = CA_DELETED;
break;
case OC_EH_SLOW:
- caResult = CA_SUCCESS;
+ caResult = CA_CONTENT;
break;
case OC_EH_FORBIDDEN:
caResult = CA_UNAUTHORIZED_REQ;
* @return
* OCStackResult
*/
-
OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult result = OC_STACK_ERROR;
- CAEndpoint_t responseEndpoint = {};
- CAResponseInfo_t responseInfo = {};
+ CAEndpoint_t responseEndpoint = {.adapter = CA_DEFAULT_ADAPTER};
+ CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
CAHeaderOption_t* optionsPointer = NULL;
if(!ehResponse || !ehResponse->requestHandle)
CopyDevAddrToEndpoint(&serverRequest->devAddr, &responseEndpoint);
responseInfo.info.resourceUri = serverRequest->resourceUrl;
- responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult);
+ responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult, serverRequest->method);
if(serverRequest->notificationFlag && serverRequest->qos == OC_HIGH_QOS)
{
{
responseInfo.info.type = CA_MSG_NONCONFIRM;
}
+ else
+ {
+ OC_LOG(ERROR, TAG, "default responseInfo type is NON");
+ responseInfo.info.type = CA_MSG_NONCONFIRM;
+ }
char rspToken[CA_MAX_TOKEN_LEN + 1] = {};
responseInfo.info.messageId = serverRequest->coapID;
if(!responseInfo.info.options)
{
- OC_LOG(FATAL, TAG, PCF("Memory alloc for options failed"));
+ OC_LOG(FATAL, TAG, "Memory alloc for options failed");
return OC_STACK_NO_MEMORY;
}
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));
+ uint8_t* observationData = (uint8_t*)responseInfo.info.options[0].optionData;
+ uint32_t observationOption= serverRequest->observationOption;
+
+ for (size_t i=sizeof(uint32_t); i; --i)
+ {
+ observationData[i-1] = observationOption & 0xFF;
+ observationOption >>=8;
+ }
// Point to the next header option before copying vender specific header options
optionsPointer += 1;
responseInfo.info.options = NULL;
}
+ responseInfo.isMulticast = false;
+ responseInfo.info.payload = NULL;
+ responseInfo.info.payloadSize = 0;
+ responseInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
+
// Put the JSON prefix and suffix around the payload
if(ehResponse->payload)
{
- OCStackResult result;
- if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
- &responseInfo.info.payloadSize))
- != OC_STACK_OK)
+ if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
{
- OC_LOG(ERROR, TAG, "Error converting payload");
- return result;
+ responseInfo.isMulticast = true;
+ }
+ else
+ {
+ responseInfo.isMulticast = false;
}
- if(responseInfo.info.payloadSize > MAX_RESPONSE_LENGTH)
+ switch(serverRequest->acceptFormat)
{
- OICFree(responseInfo.info.payload);
- OC_LOG(ERROR, TAG, "Payload too long!");
- return OC_STACK_INVALID_PARAM;
+ case OC_FORMAT_UNDEFINED:
+ // No preference set by the client, so default to CBOR then
+ case OC_FORMAT_CBOR:
+ if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
+ &responseInfo.info.payloadSize))
+ != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error converting payload");
+ OICFree(responseInfo.info.options);
+ return result;
+ }
+ responseInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
+ break;
+ default:
+ responseInfo.result = CA_NOT_ACCEPTABLE;
}
}
- else
- {
- responseInfo.info.payload = NULL;
- responseInfo.info.payloadSize = 0;
- }
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
CATransportAdapter_t CAConnTypes[] = {
CA_ADAPTER_IP,
CA_ADAPTER_GATT_BTLE,
CA_ADAPTER_RFCOMM_BTEDR
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
, CA_ADAPTER_REMOTE_ACCESS
- #endif
+#endif
+ , CA_ADAPTER_TCP
};
- const char * connTypes[] = {"ip" , "ble", "edr"
- #ifdef RA_ADAPTER
- , "ra"
- #endif
- };
- int size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
- CATransportAdapter_t adapter = responseEndpoint.adapter;
- CAResult_t caResult = CA_STATUS_FAILED;
- result = OC_STACK_OK;
+ size_t size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
+ CATransportAdapter_t adapter = responseEndpoint.adapter;
// Default adapter, try to send response out on all adapters.
if (adapter == CA_DEFAULT_ADAPTER)
{
CA_ADAPTER_GATT_BTLE |
CA_ADAPTER_RFCOMM_BTEDR
- #ifdef RA_ADAP
+#ifdef RA_ADAP
| CA_ADAPTER_REMOTE_ACCESS
- #endif
+#endif
+ | CA_ADAPTER_TCP
);
}
- for(int i = 0; i < size; i++ )
+ result = OC_STACK_OK;
+ OCStackResult tempResult = OC_STACK_OK;
+
+ for(size_t i = 0; i < size; i++ )
{
responseEndpoint.adapter = (CATransportAdapter_t)(adapter & CAConnTypes[i]);
if(responseEndpoint.adapter)
{
- //The result is set to OC_STACK_OK only if CASendResponse succeeds in sending the
+ //The result is set to OC_STACK_OK only if OCSendResponse 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 with CA error %u", caResult);
- result = CAResultToOCResult(caResult);
- }
+ tempResult = OCSendResponse(&responseEndpoint, &responseInfo);
+ }
+ if(OC_STACK_OK != tempResult)
+ {
+ result = tempResult;
}
}
- #else
+#else
- OC_LOG(INFO, TAG, PCF("Calling CASendResponse with:"));
+ OC_LOG(INFO, TAG, "Calling OCSendResponse with:");
OC_LOG_V(INFO, TAG, "\tEndpoint address: %s", responseEndpoint.addr);
OC_LOG_V(INFO, TAG, "\tEndpoint adapter: %s", responseEndpoint.adapter);
OC_LOG_V(INFO, TAG, "\tResponse result : %s", responseInfo.result);
OC_LOG_V(INFO, TAG, "\tResponse for uri: %s", responseInfo.info.resourceUri);
- CAResult_t caResult = CASendResponse(&responseEndpoint, &responseInfo);
- if(caResult != CA_STATUS_OK)
- {
- OC_LOG(ERROR, TAG, PCF("CASendResponse failed"));
- result = CAResultToOCResult(caResult);
- }
- else
- {
- result = OC_STACK_OK;
- }
- #endif
+ result = OCSendResponse(&responseEndpoint, &responseInfo);
+#endif
OICFree(responseInfo.info.payload);
OICFree(responseInfo.info.options);
*/
OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
{
- OCStackResult stackRet = OC_STACK_ERROR;
- OCServerRequest * serverRequest = NULL;
- OCServerResponse * serverResponse = NULL;
-
if(!ehResponse || !ehResponse->payload)
{
- OC_LOG(ERROR, TAG, PCF("HandleAggregateResponse invalid parameters"));
+ OC_LOG(ERROR, TAG, "HandleAggregateResponse invalid parameters");
return OC_STACK_INVALID_PARAM;
}
OC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
- serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
- serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+ OCServerRequest *serverRequest = GetServerRequestUsingHandle((OCServerRequest *)
+ ehResponse->requestHandle);
+ OCServerResponse *serverResponse = GetServerResponseUsingHandle((OCServerRequest *)
+ ehResponse->requestHandle);
+ OCStackResult stackRet = OC_STACK_ERROR;
if(serverRequest)
{
if(!serverResponse)
{
- OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
+ OC_LOG(INFO, TAG, "This is the first response fragment");
stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
if (OC_STACK_OK != stackRet)
{
- OC_LOG(ERROR, TAG, PCF("Error adding server response"));
+ OC_LOG(ERROR, TAG, "Error adding server response");
return stackRet;
}
VERIFY_NON_NULL(serverResponse);
if(ehResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
{
stackRet = OC_STACK_ERROR;
- OC_LOG(ERROR, TAG, PCF("Error adding payload, as it was the incorrect type"));
+ OC_LOG(ERROR, TAG, "Error adding payload, as it was the incorrect type");
goto exit;
}
if(!serverResponse->payload)
{
- serverResponse->payload = (OCPayload*)OCRepPayloadCreate();
serverResponse->payload = ehResponse->payload;
}
else
if(serverRequest->numResponses == 0)
{
- OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+ OC_LOG(INFO, TAG, "This is the last response fragment");
ehResponse->payload = serverResponse->payload;
stackRet = HandleSingleResponse(ehResponse);
//Delete the request and response
}
else
{
- OC_LOG(INFO, TAG, PCF("More response fragments to come"));
+ OC_LOG(INFO, TAG, "More response fragments to come");
stackRet = OC_STACK_OK;
}
}