//-----------------------------------------------------------------------------
#define _POSIX_C_SOURCE 200112L
#include <string.h>
+#include <ctype.h>
#include "ocstack.h"
#include "ocstackinternal.h"
#include "occlientcb.h"
#include "ocobserve.h"
#include "ocrandom.h"
-#include "debug.h"
-#include "occoap.h"
#include "ocmalloc.h"
#include "ocserverrequest.h"
+#include "ocsecurityinternal.h"
-#ifdef CA_INT
- #include "cacommon.h"
- #include "cainterface.h"
+#include "cacommon.h"
+#include "cainterface.h"
+
+#ifdef WITH_ARDUINO
+#include "Time.h"
+#else
+#include <sys/time.h>
#endif
+#include "coap_time.h"
+#include "utlist.h"
+#include "pdu.h"
+
+#ifndef ARDUINO
+#include <arpa/inet.h>
+#endif
+
//-----------------------------------------------------------------------------
// Typedefs
typedef enum {
OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
} OCStackState;
-
#ifdef WITH_PRESENCE
typedef enum {
OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
//TODO: we should allow the server to define this
#define MAX_OBSERVE_AGE (0x2FFFFUL)
-//-----------------------------------------------------------------------------
-// Externs
-//-----------------------------------------------------------------------------
-extern void DeinitOCSecurityInfo();
+//=============================================================================
+// Helper Functions
+//=============================================================================
+static uint32_t GetTime(float afterSeconds)
+{
+ coap_tick_t now;
+ coap_ticks(&now);
+ return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
+}
+
+static OCStackResult FormOCResponse(OCResponse * * responseLoc,
+ ClientCB * cbNode,
+ uint32_t maxAge,
+ unsigned char * fullUri,
+ unsigned char * rcvdUri,
+ CAToken_t * rcvdToken,
+ OCClientResponse * clientResponse,
+ unsigned char * bufRes)
+{
+ OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
+ if (!response)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ response->cbNode = cbNode;
+ response->maxAge = maxAge;
+ response->fullUri = fullUri;
+ response->rcvdUri = rcvdUri;
+ response->rcvdToken = rcvdToken;
+ response->clientResponse = clientResponse;
+ response->bufRes = bufRes;
+
+ *responseLoc = response;
+ return OC_STACK_OK;
+}
+
+/// This method is used to create the IPv4 dev_addr structure.
+/// TODO: Remove in future. Temporary helper function.
+/// Builds a socket interface address using IP address and port number
+static int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+ uint16_t port, OCDevAddr *ipAddr)
+{
+ if ( !ipAddr ) {
+ OC_LOG(FATAL, TAG, "Invalid argument");
+ return 1;
+ }
+
+ ipAddr->addr[0] = a;
+ ipAddr->addr[1] = b;
+ ipAddr->addr[2] = c;
+ ipAddr->addr[3] = d;
+ *((uint16_t*)&(ipAddr->addr[4])) = port;
+
+ return 0;
+}
//-----------------------------------------------------------------------------
// Internal API function
// This internal function is called to update the stack with the status of
// observers and communication failures
-OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
+OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
{
OCStackResult result = OC_STACK_ERROR;
ResourceObserver * observer = NULL;
{
case OC_OBSERVER_NOT_INTERESTED:
OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
- #ifdef CA_INT
- observer = GetObserverUsingToken (token->token);
- #else
observer = GetObserverUsingToken (token);
- #endif
if(observer)
{
result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
}
//observer is not observing anymore
- #ifdef CA_INT
- result = DeleteObserverUsingToken (token->token);
- #else
result = DeleteObserverUsingToken (token);
- #endif
if(result == OC_STACK_OK)
{
OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
//observer is still interested
OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
notifications, reset the failedCount"));
- #ifdef CA_INT
- observer = GetObserverUsingToken (token->token);
- #else
observer = GetObserverUsingToken (token);
- #endif
if(observer)
{
observer->forceHighQos = 0;
case OC_OBSERVER_FAILED_COMM:
//observer is not reachable
OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
- #ifdef CA_INT
- observer = GetObserverUsingToken (token->token);
- #else
observer = GetObserverUsingToken (token);
- #endif
if(observer)
{
if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
return result;
}
-#ifdef CA_INT
OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
{
OCStackResult ret = OC_STACK_ERROR;
*caConType = CA_LE;
break;
case OC_ALL:
- //TODO-CA Add other connectivity types as they are enabled
- *caConType = (CA_WIFI|CA_ETHERNET);
+ // Currently OC_ALL represents WIFI and ETHERNET
+ // Add other connectivity types as they are enabled in future
+ *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
break;
default:
ret = OC_STACK_INVALID_PARAM;
// update response.addr appropriately from endPoint.addressInfo
OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
{
- struct sockaddr_in sa;
- OCStackResult ret = OC_STACK_INVALID_PARAM;
- //TODO-CA Check validity of the endPoint pointer
- inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
- sa.sin_port = htons(endPoint->addressInfo.IP.port);
- static OCDevAddr address;
- memcpy((void*)&address.addr, &(sa), sizeof(sa));
+ OCStackResult ret = OC_STACK_ERROR;
+ static OCDevAddr address = {0};
+ char * tok = NULL;
+ char * savePtr = NULL;
+ char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
+ if(!cpAddress)
+ {
+ ret = OC_STACK_NO_MEMORY;
+ goto exit;
+ }
+ memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
+ strlen(endPoint->addressInfo.IP.ipAddress) + 1);
+
+ // Grabs the first three numbers from the IPv4 address and replaces dots
+ for(int i=0; i<4; i++)
+ {
+ tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
+
+ if(!tok)
+ {
+ ret = OC_STACK_ERROR;
+ goto exit;
+ }
+ address.addr[i] = atoi(tok);
+ }
+
+ memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
+
if(response)
{
response->addr = &address;
ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
}
+ else
+ {
+ OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
+ }
+exit:
+ OCFree(cpAddress);
return ret;
}
void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
{
char * tok = NULL;
-
+ char * savePtr;
// The format of the payload is {"oc":[%u:%u:%s]}
// %u : sequence number,
// %u : max age
// %s : Resource Type (Optional)
- tok = strtok(payload, "[:]}");
+ tok = strtok_r(payload, "[:]}", &savePtr);
payload[strlen(payload)] = ':';
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}", &savePtr);
payload[strlen((char *)payload)] = ':';
*seqNum = (uint32_t) atoi(tok);
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}", &savePtr);
*maxAge = (uint32_t) atoi(tok);
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}",&savePtr);
if(tok)
{
int presenceSubscribe = 0;
int multicastPresenceSubscribe = 0;
+ if (responseInfo->result != CA_SUCCESS)
+ {
+ OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
+ return OC_STACK_ERROR;
+ }
+
fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
if(NULL == fullUri)
{
- OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for fullUri"));
+ OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
result = OC_STACK_NO_MEMORY;
goto exit;
}
if(NULL == ipAddress)
{
- OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for ipAddress"));
+ OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
result = OC_STACK_NO_MEMORY;
goto exit;
}
snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
OC_PRESENCE_URI);
- cbNode = GetClientCB(NULL, NULL, fullUri);
+ cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
if(cbNode)
{
else
{
snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
- cbNode = GetClientCB(NULL, NULL, fullUri);
+ cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
if(cbNode)
{
multicastPresenceSubscribe = 1;
response.resJSONPayload = NULL;
response.result = OC_STACK_OK;
- UpdateResponseAddr(&response, endPoint);
+ result = UpdateResponseAddr(&response, endPoint);
+ if(result != OC_STACK_OK)
+ {
+ goto exit;
+ }
if(responseInfo->info.payload)
{
// This is the multicast case
OCMulticastNode* mcNode = NULL;
- mcNode = GetMCPresenceNode(fullUri);
+ mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
if(mcNode != NULL)
{
OCFree(fullUri);
OCFree(ipAddress);
OCFree(resourceTypeName);
+return result;
}
{
OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
- OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
+ OCStackApplicationResult appResult = OC_STACK_DELETE_TRANSACTION;
if(NULL == endPoint)
{
return;
}
- ClientCB *cbNode = GetClientCB((CAToken_t *)&responseInfo->info.token, NULL, NULL);
+ ClientCB *cbNode = GetClientCB((CAToken_t *)&(responseInfo->info.token), NULL, NULL);
if (cbNode)
{
if(responseInfo->info.numOptions > 0)
{
int start = 0;
- //First option alwas with option ID COAP_OPTION_OBSERVE if it is availbale
+ //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
{
memcpy (&(response.sequenceNumber),
- &(responseInfo->info.options[0].optionData), 4);
+ &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
start = 1;
}
&(responseInfo->info.options[i]), sizeof(OCHeaderOption));
}
}
- result = cbNode->callBack(cbNode->context,
+ appResult = cbNode->callBack(cbNode->context,
cbNode->handle, &response);
- if (result == OC_STACK_DELETE_TRANSACTION)
+ if (appResult == OC_STACK_DELETE_TRANSACTION)
{
FindAndDeleteClientCB(cbNode);
}
//This function will be called back by CA layer when a request is received
void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
{
- CAInfo_t responseData;
- CAResponseInfo_t responseInfo;
- OCStackResult requestResult = OC_STACK_ERROR;
-
OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
+ if(!endPoint)
+ {
+ OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
+ return;
+ }
+
+ if(!requestInfo)
+ {
+ OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
+ return;
+ }
+
+ OCStackResult requestResult = OC_STACK_ERROR;
-#if 1
if(myStackMode == OC_CLIENT)
{
//TODO: should the client be responding to requests?
return;
}
- OCServerProtocolRequest serverRequest;
+ OCServerProtocolRequest serverRequest = {};
- memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
char * newUri = (char *)endPoint->resourceUri;
unsigned char * query = NULL;
- unsigned char * resourceType = NULL;
getQueryFromUri(endPoint->resourceUri, &query, &newUri);
OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
- //copy URI
- memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
+ if(strlen(newUri) < MAX_URI_LENGTH)
+ {
+ //copy URI
+ memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
+ return;
+ }
//copy query
if(query)
{
- memcpy (&(serverRequest.query), query, strlen(query));
+ if(strlen((char*)query) < MAX_QUERY_LENGTH)
+ {
+ memcpy (&(serverRequest.query), query, strlen((char*)query));
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
+ return;
+ }
}
//copy request payload
if (requestInfo->info.payload)
}
}
- // copy token
- OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", strlen(requestInfo->info.token));
- OC_LOG_BUFFER(INFO, TAG, requestInfo->info.token, strlen(requestInfo->info.token));
- // TODO-CA: For CA integration currently copying CAToken to OCCoapToken:
- // Need to remove OCCoapToken
- memcpy (&(serverRequest.requestToken.token), requestInfo->info.token,
- MAX_TOKEN_LENGTH);
- serverRequest.requestToken.tokenLength = MAX_TOKEN_LENGTH;
+ OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
+ OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
+
+ serverRequest.requestToken = (CAToken_t)OCCalloc(1, CA_MAX_TOKEN_LEN+1);
+ // Module Name
+ if (!serverRequest.requestToken)
+ {
+ OC_LOG(FATAL, TAG, "Server Request Token is NULL");
+ return;
+ }
+ memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
if (requestInfo->info.type == CA_MSG_CONFIRM)
{
// copy the address
serverRequest.addressInfo = endPoint->addressInfo;
serverRequest.connectivityType = endPoint->connectivityType;
- if (requestInfo->info.token)
- {
- strncpy(serverRequest.token, requestInfo->info.token, sizeof(serverRequest.token) - 1);
- }
// copy vendor specific header options
// TODO-CA: CA is including non-vendor header options as well, like observe.
// Need to filter those out
- GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &(requestInfo->info.numOptions));
+ uint8_t tempNum = (requestInfo->info.numOptions);
+ GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
{
- // TODO-CA: Need to send an error indicating the num of options is incorrect
+ OC_LOG(ERROR, TAG,
+ PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
+ OCFree(serverRequest.requestToken);
return;
}
- serverRequest.numRcvdVendorSpecificHeaderOptions = requestInfo->info.numOptions;
+ serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
if (serverRequest.numRcvdVendorSpecificHeaderOptions)
{
memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
- sizeof(CAHeaderOption_t)*requestInfo->info.numOptions);
+ sizeof(CAHeaderOption_t)*tempNum);
}
requestResult = HandleStackRequests (&serverRequest);
-#endif
-
+ if(requestResult != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
+ }
OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
}
-#endif // CA_INT
-
//This function will be called back by occoap layer when a request is received
OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
{
OCStackResult result = OC_STACK_ERROR;
ResourceHandling resHandling;
OCResource *resource;
+ if(!protocolRequest)
+ {
+ OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
+ return OC_STACK_INVALID_PARAM;
+ }
OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
if(!request)
{
OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
-#ifdef CA_INT
- result = AddServerCARequest(&request, protocolRequest->coapID,
- protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
- protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
- protocolRequest->observationOption, protocolRequest->qos,
- protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
- protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
- &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
- protocolRequest->reqTotalSize,
- &protocolRequest->addressInfo, protocolRequest->connectivityType, protocolRequest->token);
-#else
result = AddServerRequest(&request, protocolRequest->coapID,
protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
protocolRequest->observationOption, protocolRequest->qos,
protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
- &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
- protocolRequest->reqTotalSize);
-#endif
+ protocolRequest->resourceUrl,protocolRequest->reqTotalSize,
+ &protocolRequest->addressInfo, protocolRequest->connectivityType);
if (OC_STACK_OK != result)
{
OC_LOG(ERROR, TAG, PCF("Error adding server request"));
OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
uint8_t isObserveNotification = 0;
ClientCB * cbNode = NULL;
- #ifdef WITH_PRESENCE
+ if(!response)
+ {
+ OC_LOG(ERROR, TAG, PCF("response is NULL"));
+ return OC_STACK_INVALID_PARAM;
+ }
+#ifdef WITH_PRESENCE
uint8_t isPresenceNotification = 0;
uint8_t isMulticastPresence = 0;
char * resourceTypeName = NULL;
uint32_t higherBound = 0;
char * tok = NULL;
unsigned char * bufRes = response->bufRes;
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
cbNode = response->cbNode;
if(!cbNode)
result = OC_STACK_INVALID_PARAM;
goto exit;
}
- tok = strtok((char *)bufRes, "[:]}");
+ char * savePtr;
+ tok = strtok_r((char *)bufRes, "[:]}", &savePtr);
bufRes[strlen((char *)bufRes)] = ':';
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}", &savePtr);
bufRes[strlen((char *)bufRes)] = ':';
response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}", &savePtr);
response->maxAge = (uint32_t )atoi(tok);
OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
- tok = strtok(NULL, "[:]}");
+ tok = strtok_r(NULL, "[:]}", &savePtr);
if(tok)
{
resourceTypeName = (char *)OCMalloc(strlen(tok));
OCStackResult result = OC_STACK_ERROR;
OC_LOG(INFO, TAG, PCF("Entering OCInit"));
+ // Validate mode
+ if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
+ {
+ OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+ return OC_STACK_ERROR;
+ }
+
if (ipAddr)
{
OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
}
OCSeedRandom();
-#ifdef CA_INT
CAInitialize();
//It is ok to select network to CA_WIFI for now
+#ifdef WITH_ARDUINO
+ CAResult_t caResult = CASelectNetwork(CA_ETHERNET);
+#else
CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
+#endif
if(caResult == CA_STATUS_OK)
{
OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
- caResult = CARegisterHandler(HandleCARequests, HandleCAResponses);
- if(caResult == CA_STATUS_OK)
+ CARegisterHandler(HandleCARequests, HandleCAResponses);
{
OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
stackState = OC_STACK_INITIALIZED;
result = OC_STACK_ERROR;
}
}
-#else
- switch (mode)
- {
- case OC_CLIENT:
- OC_LOG(INFO, TAG, PCF("Client mode"));
- break;
- case OC_SERVER:
- OC_LOG(INFO, TAG, PCF("Server mode"));
- break;
- case OC_CLIENT_SERVER:
- OC_LOG(INFO, TAG, PCF("Client-server mode"));
- break;
- default:
- OC_LOG(ERROR, TAG, PCF("Invalid mode"));
- return OC_STACK_ERROR;
- break;
- }
-
- // Make call to OCCoAP layer
- result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
-#endif //CA_INT
myStackMode = mode;
defaultDeviceHandler = NULL;
+#if defined(__WITH_DTLS__)
+ caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
+ result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
+#endif // (__WITH_DTLS__)
+
#ifdef WITH_PRESENCE
PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
#endif // WITH_PRESENCE
// Free memory dynamically allocated for resources
deleteAllResources();
DeleteDeviceInfo();
-#ifdef CA_INT
CATerminate();
//CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
result = OC_STACK_OK;
-#else //CA_INT
- result = OCStopCoAP();
-#endif //CA_INT
if (result == OC_STACK_OK)
{
}
/**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource
+ * (specified by that Resource's respective URI).
*
- * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
+ * calling this API.
* @param method - @ref OCMethod to perform on the resource
* @param requiredUri - URI of the resource to interact with
* @param referenceUri - URI of the reference resource
* Note: IN case of CA, when using multicast, the required URI should not contain IP address.
* Instead, it just contains the URI to the resource such as "/oc/core".
*/
-#ifdef CA_INT
-OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
- const char *referenceUri, const char *request, uint8_t conType,
- OCQualityOfService qos, OCCallbackData *cbData,
- OCHeaderOption * options, uint8_t numOptions)
-#else
OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
- const char *referenceUri, const char *request,
- OCQualityOfService qos, OCCallbackData *cbData,
- OCHeaderOption * options, uint8_t numOptions)
-#endif
+ const char *referenceUri, const char *request, OCConnectivityType conType,
+ OCQualityOfService qos, OCCallbackData *cbData,
+ OCHeaderOption * options, uint8_t numOptions)
{
OCStackResult result = OC_STACK_ERROR;
- OCCoAPToken token;
ClientCB *clientCB = NULL;
unsigned char * requestUri = NULL;
unsigned char * resourceType = NULL;
unsigned char * query = NULL;
char * newUri = (char *)requiredUri;
(void) referenceUri;
-#ifdef CA_INT
CARemoteEndpoint_t* endpoint = NULL;
CAResult_t caResult;
- CAToken_t caToken = NULL;
+ CAToken_t token = NULL;
CAInfo_t requestData;
CARequestInfo_t requestInfo;
- CAGroupEndpoint_t grpEnd;
+ CAGroupEndpoint_t grpEnd = {0};
// To track if memory is allocated for additional header options
uint8_t hdrOptionMemAlloc = 0;
-#endif // CA_INT
OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
- TODO ("Need to form the final query by concatenating require and reference URI's");
+ //TODO ("Need to form the final query by concatenating require and reference URI's");
VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
uint16_t uriLen = strlen(requiredUri);
- // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
+ // ToDo: We should also check if the requiredUri has a mutlicast address,
+ // then qos has to be OC_Low_QOS
switch (method)
{
case OC_REST_GET:
goto exit;
}
-#ifdef CA_INT
memset(&requestData, 0, sizeof(CAInfo_t));
memset(&requestInfo, 0, sizeof(CARequestInfo_t));
- memset(&grpEnd, 0, sizeof(CAGroupEndpoint_t));
switch (method)
{
case OC_REST_GET:
}
// create token
- caResult = CAGenerateToken(&caToken);
-
- //TODO-CA Remove this temporary fix (for some reason same token is being generated)
- static count = 0;
- count++;
- caToken[0] += count;
-
+ caResult = CAGenerateToken(&token);
if (caResult != CA_STATUS_OK)
{
OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
- caToken = NULL;
+ CADestroyToken(token);
goto exit;
}
requestData.type = qualityOfServiceToMessageType(qos);
- requestData.token = caToken;
+ requestData.token = token;
if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
{
result = CreateObserveHeaderOption (&(requestData.options), options,
CAConnectivityType_t caConType;
- result = OCToCAConnectivityType(conType, &caConType);
+ result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
if (result != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
grpEnd.connectivityType = caConType;
grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
+ if(!grpEnd.resourceUri)
+ {
+ result = OC_STACK_NO_MEMORY;
+ goto exit;
+ }
strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
caResult = CASendRequestToAll(&grpEnd, &requestInfo);
goto exit;
}
- if((result = AddClientCB(&clientCB, cbData, &caToken, handle, method,
+ if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
requestUri, resourceType)) != OC_STACK_OK)
{
result = OC_STACK_NO_MEMORY;
goto exit;
}
-#else // CA_INT
-
- // Generate token which will be used by OCStack to match responses received
- // with the request
- OCGenerateCoAPToken(&token);
-
- if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
- != OC_STACK_OK)
- {
- result = OC_STACK_NO_MEMORY;
- goto exit;
- }
-
- // Make call to OCCoAP layer
- result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
-#endif // CA_INT
-
exit:
if(newUri != requiredUri)
{
OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
FindAndDeleteClientCB(clientCB);
}
-#ifdef CA_INT
CADestroyRemoteEndpoint(endpoint);
OCFree(grpEnd.resourceUri);
if (hdrOptionMemAlloc)
{
OCFree(requestData.options);
}
-#endif // CA_INT
return result;
}
* Remove the callback associated on client side.
*/
OCStackResult ret = OC_STACK_OK;
-#ifdef CA_INT
CARemoteEndpoint_t* endpoint = NULL;
CAResult_t caResult;
CAInfo_t requestData;
CARequestInfo_t requestInfo;
// Track if memory is allocated for additional header options
uint8_t hdrOptionMemAlloc = 0;
-#endif // CA_INT
if(!handle) {
return OC_STACK_INVALID_PARAM;
{
case OC_REST_OBSERVE:
case OC_REST_OBSERVE_ALL:
- #ifdef CA_INT
//TODO-CA : Why CA_WIFI alone?
caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
&endpoint);
{
ret = OC_STACK_OK;
}
- #else // CA_INT
- if(qos == OC_HIGH_QOS)
- {
- ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
- &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
- numOptions);
- }
- else
- {
- FindAndDeleteClientCB(clientCB);
- }
- break;
- #endif // CA_INT
#ifdef WITH_PRESENCE
case OC_REST_PRESENCE:
FindAndDeleteClientCB(clientCB);
return OC_STACK_INVALID_METHOD;
}
}
-#ifdef CA_INT
CADestroyRemoteEndpoint(endpoint);
if (hdrOptionMemAlloc)
{
OCFree(requestData.options);
}
-#endif // CA_INT
return ret;
}
#ifdef WITH_PRESENCE
-#ifdef CA_INT
OCStackResult OCProcessPresence()
{
OCStackResult result = OC_STACK_OK;
{
OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
&dst);
- result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
- (OCDevAddr *) &dst, 0, NULL);
- if(result != OC_STACK_OK)
- {
- goto exit;
- }
+
+ clientResponse.sequenceNumber = 0;
+ clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
+ clientResponse.addr = (OCDevAddr *) &dst;
+ clientResponse.resJSONPayload = NULL;
+
result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
&cbNode->token, &clientResponse, NULL);
if(result != OC_STACK_OK)
}
return result;
}
-#else
-OCStackResult OCProcessPresence()
-{
- OCStackResult result = OC_STACK_OK;
- uint8_t ipAddr[4] = { 0 };
- uint16_t port = 0;
-
- OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
- ClientCB* cbNode = NULL;
- OCDevAddr dst;
- OCClientResponse clientResponse;
- OCResponse * response = NULL;
-
- LL_FOREACH(cbList, cbNode) {
- if(OC_REST_PRESENCE == cbNode->method)
- {
- if(cbNode->presence)
- {
- uint32_t now = GetTime(0);
- OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
- OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
-
-
- if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
- {
- goto exit;
- }
-
- if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
- OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
- cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
- }
-
- if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
- {
- OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
- if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
- {
- OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
- &dst);
- result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
- (OCDevAddr *) &dst, 0, NULL);
- if(result != OC_STACK_OK)
- {
- goto exit;
- }
- result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
- &cbNode->token, &clientResponse, NULL);
- if(result != OC_STACK_OK)
- {
- goto exit;
- }
-
- // Increment the TTLLevel (going to a next state), so we don't keep
- // sending presence notification to client.
- cbNode->presence->TTLlevel++;
- OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
- cbNode->presence->TTLlevel);
- }
- else
- {
- result = OC_STACK_INVALID_IP;
- goto exit;
- }
- HandleStackResponses(response);
- }
- if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
- {
- OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
-
- OCCoAPToken token;
- OCGenerateCoAPToken(&token);
- result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
- &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
-
- if(result != OC_STACK_OK)
- {
- goto exit;
- }
- cbNode->presence->TTLlevel++;
- OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
- }
- }
- }
- }
-exit:
- if (result != OC_STACK_OK)
- {
- OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
- }
- return result;
-}
-#endif // CA_INT
#endif // WITH_PRESENCE
/**
* OC_STACK_OK - no errors
* OC_STACK_ERROR - stack process error
*/
-OCStackResult OCProcess() {
-
- OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
+OCStackResult OCProcess()
+{
#ifdef WITH_PRESENCE
OCProcessPresence();
#endif
-#ifdef CA_INT
CAHandleRequestResponse();
-#else
- OCProcessCoAP();
-#endif // CA_INT
return OC_STACK_OK;
}
if(OC_PRESENCE_UNINITIALIZED == presenceState)
{
- OCDevAddr multiCastAddr;
- OCCoAPToken token;
-
presenceState = OC_PRESENCE_INITIALIZED;
- OCGenerateCoAPToken(&token);
- OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
-#ifdef CA_INT
+
CAAddress_t addressInfo;
strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
- addressInfo.IP.port = 5298;
+ addressInfo.IP.port = 5683;
+ //TODO make sure there is no memory leak here since another copy
+ //of token is being created inside AddObserver
CAToken_t caToken = NULL;
- CAGenerateToken(&caToken);
+ CAResult_t caResult = CAGenerateToken(&caToken);
+ if (caResult != CA_STATUS_OK)
+ {
+ OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
+ CADestroyToken(caToken);
+ return OC_STACK_ERROR;
+ }
- AddCAObserver(OC_PRESENCE_URI, NULL, 0, &token,
- &multiCastAddr, (OCResource *)presenceResource.handle, OC_LOW_QOS,
- &addressInfo, CA_WIFI, caToken);
-#else
- //add the presence observer
- AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
- (OCResource *)presenceResource.handle, OC_LOW_QOS);
-#endif
+ AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
+ (OCResource *)presenceResource.handle, OC_LOW_QOS,
+ &addressInfo, CA_WIFI);
}
// Each time OCStartPresence is called
/**
* Create a resource
*
- * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
+ * @param handle - pointer to handle to newly created resource. Set by ocstack.
+ * Used to refer to resource
* @param resourceTypeName - name of resource type. Example: "core.led"
* @param resourceInterfaceName - name of resource interface. Example: "core.rw"
* @param uri - URI of the resource. Example: "/a/led"
* @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
* NULL for default entity handler
- * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
+ * @param resourceProperties - properties supported by resource.
+ * Example: OC_DISCOVERABLE|OC_OBSERVABLE
*
* @return
* OC_STACK_OK - no errors
// TODO: Does resource attribute resentation really have to be maintained in stack?
// Is it presented during resource discovery?
- TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
+ //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
// Create the resourcetype and insert it into the resource list
pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
// Validate parameters
VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
- TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
+ //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
// Create the resourceinterface and insert it into the resource list
pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
{
OCDoHandle handle = NULL;
// Generate token here, it will be deleted when the transaction is deleted
- handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+ handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
if (handle)
{
- OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+ OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
}
return handle;
{
if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
{
- *query = (unsigned char *) OCMalloc(strlen(leftToken));
+ *query = (unsigned char *) OCMalloc(strlen(leftToken) + 1);
if(!*query)
{
+ OCFree(tempURI);
goto exit;
}
strcpy((char *)*query, ((const char *)&leftToken[0]));
return buffer;
}
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
+ uint8_t *c, uint8_t *d )
+{
+ if ( !ipAddr || !a || !b || !c || !d ) {
+ OC_LOG(FATAL, TAG, "Invalid argument");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *a = ipAddr->addr[0];
+ *b = ipAddr->addr[1];
+ *c = ipAddr->addr[2];
+ *d = ipAddr->addr[3];
+
+ return OC_STACK_OK;
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
+{
+ if ( !ipAddr || !port ) {
+ OC_LOG(FATAL, TAG, "Invalid argument");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ *port = *((uint16_t*)&ipAddr->addr[4]);
+
+ return OC_STACK_OK;
+}
+