1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //-----------------------------------------------------------------------------
24 //-----------------------------------------------------------------------------
25 #define _POSIX_C_SOURCE 200112L
30 #include "ocstackinternal.h"
31 #include "ocresourcehandler.h"
32 #include "occlientcb.h"
33 #include "ocobserve.h"
36 #include "ocserverrequest.h"
37 #include "ocsecurityinternal.h"
40 #include "cainterface.h"
47 #include "coap_time.h"
52 #include <arpa/inet.h>
55 //-----------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------
59 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
63 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
67 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
70 static OCStackState stackState = OC_STACK_UNINITIALIZED;
72 OCResource *headResource = NULL;
73 static OCResource *tailResource = NULL;
75 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
76 static PresenceResource presenceResource;
77 static uint8_t PresenceTimeOutSize = 0;
78 static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
81 static OCMode myStackMode;
82 OCDeviceEntityHandler defaultDeviceHandler;
83 OCStackResult getQueryFromUri(const char * uri, char** resourceType, char ** newURI);
85 //-----------------------------------------------------------------------------
87 //-----------------------------------------------------------------------------
88 #define TAG PCF("OCStack")
89 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
90 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
91 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
92 TAG, PCF(#arg " is NULL")); return (retVal); } }
93 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
96 //TODO: we should allow the server to define this
97 #define MAX_OBSERVE_AGE (0x2FFFFUL)
99 //=============================================================================
101 //=============================================================================
102 static uint32_t GetTime(float afterSeconds)
106 return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
109 /// This method is used to create the IPv4 dev_addr structure.
110 /// TODO: Remove in future. Temporary helper function.
111 /// Builds a socket interface address using IP address and port number
112 static OCStackResult OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
113 uint16_t port, OCDevAddr *ipAddr)
116 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
117 return OC_STACK_INVALID_PARAM;
124 *((uint16_t*)&(ipAddr->addr[4])) = port;
129 //-----------------------------------------------------------------------------
130 // Internal API function
131 //-----------------------------------------------------------------------------
133 // This internal function is called to update the stack with the status of
134 // observers and communication failures
135 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
137 OCStackResult result = OC_STACK_ERROR;
138 ResourceObserver * observer = NULL;
139 OCEntityHandlerRequest ehRequest = {};
143 case OC_OBSERVER_NOT_INTERESTED:
144 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
145 observer = GetObserverUsingToken (token);
148 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
149 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
150 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
151 if(result != OC_STACK_OK)
155 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
157 //observer is not observing anymore
158 result = DeleteObserverUsingToken (token);
159 if(result == OC_STACK_OK)
161 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
165 result = OC_STACK_OK;
166 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
169 case OC_OBSERVER_STILL_INTERESTED:
170 //observer is still interested
171 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
172 notifications, reset the failedCount"));
173 observer = GetObserverUsingToken (token);
176 observer->forceHighQos = 0;
177 observer->failedCommCount = 0;
178 result = OC_STACK_OK;
182 result = OC_STACK_OBSERVER_NOT_FOUND;
185 case OC_OBSERVER_FAILED_COMM:
186 //observer is not reachable
187 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
188 observer = GetObserverUsingToken (token);
191 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
193 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
194 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
195 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
196 if(result != OC_STACK_OK)
198 return OC_STACK_ERROR;
200 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
201 //observer is unreachable
202 result = DeleteObserverUsingToken (token);
203 if(result == OC_STACK_OK)
205 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
209 result = OC_STACK_OK;
210 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
215 observer->failedCommCount++;
216 result = OC_STACK_CONTINUE;
218 observer->forceHighQos = 1;
219 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
223 OC_LOG(ERROR, TAG, PCF("Unknown status"));
224 result = OC_STACK_ERROR;
230 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
232 OCStackResult ret = OC_STACK_ERROR;
240 ret = OC_STACK_RESOURCE_CREATED;
243 ret = OC_STACK_RESOURCE_DELETED;
246 ret = OC_STACK_INVALID_QUERY;
249 ret = OC_STACK_INVALID_OPTION;
252 ret = OC_STACK_NO_RESOURCE;
260 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
262 OCStackResult ret = OC_STACK_OK;
267 *caConType = CA_ETHERNET;
270 *caConType = CA_WIFI;
279 // Currently OC_ALL represents WIFI and ETHERNET
280 // Add other connectivity types as they are enabled in future
281 *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
284 ret = OC_STACK_INVALID_PARAM;
290 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
292 OCStackResult ret = OC_STACK_OK;
297 *ocConType = OC_ETHERNET;
300 *ocConType = OC_WIFI;
309 ret = OC_STACK_INVALID_PARAM;
315 // update response.addr appropriately from endPoint.addressInfo
316 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
318 OCStackResult ret = OC_STACK_ERROR;
319 static OCDevAddr address = {};
321 char * savePtr = NULL;
322 char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
325 ret = OC_STACK_NO_MEMORY;
328 memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
329 strlen(endPoint->addressInfo.IP.ipAddress) + 1);
331 // Grabs the first three numbers from the IPv4 address and replaces dots
332 for(int i=0; i<4; i++)
334 tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
338 ret = OC_STACK_ERROR;
341 address.addr[i] = atoi(tok);
344 memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
348 response->addr = &address;
349 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
353 OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
360 // Note: Caller should invoke OCFree after done with resType pointer
361 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
364 char * savePtr = NULL;
365 // The format of the payload is {"oc":[%u:%u:%s]}
366 // %u : sequence number,
368 // %s : Resource Type (Optional)
370 if (!payload || !seqNum || !maxAge || !resType)
374 tok = strtok_r(payload, "[:]}", &savePtr);
375 payload[strlen(payload)] = ':';
377 //Retrieve sequence number
378 tok = strtok_r(NULL, "[:]}", &savePtr);
383 payload[strlen((char *)payload)] = ':';
384 *seqNum = (uint32_t) atoi(tok);
387 tok = strtok_r(NULL, "[:]}", &savePtr);
392 *maxAge = (uint32_t) atoi(tok);
394 //Retrieve ResourceType
395 tok = strtok_r(NULL, "[:]}",&savePtr);
401 *resType = (char *)OCMalloc(strlen(tok) + 1);
406 payload[strlen((char *)payload)] = ':';
407 strcpy(*resType, tok);
408 OC_LOG_V(DEBUG, TAG, "resourceTypeName %s", *resType);
410 payload[strlen((char *)payload)] = ']';
413 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
414 const CAResponseInfo_t* responseInfo)
416 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
417 ClientCB * cbNode = NULL;
418 char *resourceTypeName = NULL;
419 OCClientResponse response;
420 OCStackResult result = OC_STACK_ERROR;
421 uint32_t lowerBound = 0;
422 uint32_t higherBound = 0;
425 char *fullUri = NULL;
426 char *ipAddress = NULL;
427 int presenceSubscribe = 0;
428 int multicastPresenceSubscribe = 0;
429 size_t addressLen = 0;
431 if (responseInfo->result != CA_SUCCESS)
433 OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
434 return OC_STACK_ERROR;
437 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
441 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
442 result = OC_STACK_NO_MEMORY;
446 addressLen = strlen(endPoint->addressInfo.IP.ipAddress);
447 ipAddress = (char *) OCMalloc(addressLen + 1);
449 if(NULL == ipAddress)
451 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
452 result = OC_STACK_NO_MEMORY;
456 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress, addressLen);
457 ipAddress[addressLen] = '\0';
459 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
462 cbNode = GetClientCB(NULL, NULL, fullUri);
466 presenceSubscribe = 1;
470 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
471 cbNode = GetClientCB(NULL, NULL, fullUri);
474 multicastPresenceSubscribe = 1;
478 if(!presenceSubscribe && !multicastPresenceSubscribe)
480 OC_LOG(ERROR, TAG, PCF("Received a presence notification, but no callback, ignoring"));
484 // No payload to the application in case of presence
485 response.resJSONPayload = NULL;
486 response.result = OC_STACK_OK;
488 result = UpdateResponseAddr(&response, endPoint);
489 if(result != OC_STACK_OK)
494 if(responseInfo->info.payload)
496 parsePresencePayload(responseInfo->info.payload,
497 &(response.sequenceNumber),
502 if(presenceSubscribe)
504 if(cbNode->sequenceNumber == response.sequenceNumber)
506 OC_LOG(INFO, TAG, PCF("===============No presence change"));
511 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
512 response.result = OC_STACK_PRESENCE_STOPPED;
515 OCFree(cbNode->presence->timeOut);
516 OCFree(cbNode->presence);
517 cbNode->presence = NULL;
522 if(!cbNode->presence)
524 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
525 if(!(cbNode->presence))
527 OC_LOG(ERROR, TAG, PCF("Could not allocate memory for cbNode->presence"));
528 result = OC_STACK_NO_MEMORY;
532 VERIFY_NON_NULL_V(cbNode->presence);
533 cbNode->presence->timeOut = NULL;
534 cbNode->presence->timeOut = (uint32_t *)
535 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
536 if(!(cbNode->presence->timeOut)){
538 PCF("Could not allocate memory for cbNode->presence->timeOut"));
539 OCFree(cbNode->presence);
540 result = OC_STACK_NO_MEMORY;
545 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
546 cbNode->presence->TTL = maxAge;
547 for(int index = 0; index < PresenceTimeOutSize; index++)
549 lowerBound = GetTime(PresenceTimeOut[index]/ 100.0f*cbNode->presence->TTL);
550 higherBound = GetTime(PresenceTimeOut[index + 1]/100.0f*cbNode->presence->TTL);
551 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
552 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
553 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
554 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
555 cbNode->presence->timeOut[index]);
557 cbNode->presence->TTLlevel = 0;
558 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
561 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
562 cbNode->sequenceNumber = response.sequenceNumber;
564 // Ensure that a filter is actually applied.
565 if(resourceTypeName && cbNode->filterResourceType)
567 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
576 // This is the multicast case
578 OCMulticastNode* mcNode = NULL;
579 mcNode = GetMCPresenceNode(fullUri);
583 if(mcNode->nonce == response.sequenceNumber)
585 OC_LOG(INFO, TAG, PCF("No presence change (Multicast)"));
588 mcNode->nonce = response.sequenceNumber;
592 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
593 response.result = OC_STACK_PRESENCE_STOPPED;
598 uint32_t uriLen = strlen(fullUri);
599 char* uri = (char *) OCMalloc(uriLen + 1);
602 memcpy(uri, fullUri, (uriLen + 1));
607 PCF("No Memory for URI to store in the presence node"));
608 result = OC_STACK_NO_MEMORY;
611 result = AddMCPresenceNode(&mcNode, uri, response.sequenceNumber);
612 if(result != OC_STACK_OK)
615 PCF("Unable to add Multicast Presence Node"));
621 // Ensure that a filter is actually applied.
622 if(resourceTypeName && cbNode->filterResourceType)
624 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
631 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
633 if (cbResult == OC_STACK_DELETE_TRANSACTION)
635 FindAndDeleteClientCB(cbNode);
641 OCFree(resourceTypeName);
646 //This function will be called back by CA layer when a response is received
647 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
649 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
653 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
657 if(NULL == responseInfo)
659 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
663 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
665 HandlePresenceResponse(endPoint, responseInfo);
669 ClientCB *cbNode = GetClientCB(&(responseInfo->info.token), NULL, NULL);
673 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
674 OCClientResponse response;
676 OCStackResult result = UpdateResponseAddr(&response, endPoint);
677 if(result != OC_STACK_OK)
679 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
683 response.result = CAToOCStackResult(responseInfo->result);
684 response.resJSONPayload = responseInfo->info.payload;
685 response.numRcvdVendorSpecificHeaderOptions = 0;
686 if(responseInfo->info.options && responseInfo->info.numOptions > 0)
689 //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
690 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
692 memcpy (&(response.sequenceNumber),
693 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
694 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
699 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
702 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
704 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
708 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
710 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
711 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
714 if (cbNode->callBack(cbNode->context,cbNode->handle, &response)
715 == OC_STACK_DELETE_TRANSACTION)
717 FindAndDeleteClientCB(cbNode);
720 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
721 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
724 //This function will be called back by CA layer when a request is received
725 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
727 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
730 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
736 OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
740 OCStackResult requestResult = OC_STACK_ERROR;
742 if(myStackMode == OC_CLIENT)
744 //TODO: should the client be responding to requests?
748 OCServerProtocolRequest serverRequest = {};
750 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
752 char * newUri = NULL;
754 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
755 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
756 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
757 if(strlen(newUri) < MAX_URI_LENGTH)
760 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
764 OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
770 if(strlen((char*)query) < MAX_QUERY_LENGTH)
772 memcpy (&(serverRequest.query), query, strlen((char*)query));
776 OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
780 //copy request payload
781 if (requestInfo->info.payload)
783 size_t payloadLen = strlen(requestInfo->info.payload);
784 serverRequest.reqTotalSize = payloadLen + 1;
785 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
790 serverRequest.reqTotalSize = 1;
791 serverRequest.reqJSONPayload[0] = '\0';
794 switch (requestInfo->method)
798 serverRequest.method = OC_REST_GET;
803 serverRequest.method = OC_REST_PUT;
808 serverRequest.method = OC_REST_POST;
813 serverRequest.method = OC_REST_DELETE;
818 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
823 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
824 OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
826 serverRequest.requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
828 if (!serverRequest.requestToken)
830 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
833 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
835 if (requestInfo->info.type == CA_MSG_CONFIRM)
837 serverRequest.qos = OC_HIGH_QOS;
839 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
841 serverRequest.qos = OC_LOW_QOS;
843 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
845 // TODO-CA: Need to handle this
847 else if (requestInfo->info.type == CA_MSG_RESET)
849 // TODO-CA: Need to handle this
851 // CA does not need the following 3 fields
852 serverRequest.coapID = 0;
853 serverRequest.delayedResNeeded = 0;
854 serverRequest.secured = endPoint->isSecured;
857 serverRequest.addressInfo = endPoint->addressInfo;
858 serverRequest.connectivityType = endPoint->connectivityType;
860 // copy vendor specific header options
861 // TODO-CA: CA is including non-vendor header options as well, like observe.
862 // Need to filter those out
863 uint8_t tempNum = (requestInfo->info.numOptions);
864 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
865 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
868 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
869 OCFree(serverRequest.requestToken);
872 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
873 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
875 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
876 sizeof(CAHeaderOption_t)*tempNum);
879 requestResult = HandleStackRequests (&serverRequest);
880 if(requestResult != OC_STACK_OK)
882 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
884 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
887 //This function will be called back by occoap layer when a request is received
888 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
890 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
891 OCStackResult result = OC_STACK_ERROR;
892 ResourceHandling resHandling;
893 OCResource *resource;
896 OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
897 return OC_STACK_INVALID_PARAM;
900 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
903 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
904 result = AddServerRequest(&request, protocolRequest->coapID,
905 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
906 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
907 protocolRequest->observationOption, protocolRequest->qos,
908 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
909 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
910 protocolRequest->resourceUrl,protocolRequest->reqTotalSize,
911 &protocolRequest->addressInfo, protocolRequest->connectivityType);
912 if (OC_STACK_OK != result)
914 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
920 OC_LOG(ERROR, TAG, PCF("Out of Memory"));
921 return OC_STACK_NO_MEMORY;
924 if(!protocolRequest->reqMorePacket)
926 request->requestComplete = 1;
932 PCF("This is either a repeated Server Request or blocked Server Request"));
935 if(request->requestComplete)
937 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
938 result = DetermineResourceHandling (request, &resHandling, &resource);
939 if (result == OC_STACK_OK)
941 result = ProcessRequest(resHandling, resource, request);
945 result = OC_STACK_ERROR;
950 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
951 result = OC_STACK_CONTINUE;
956 int ParseIPv4Address(char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
960 uint8_t dotCount = 0;
964 /* search for scheme */
966 if (!isdigit((char) *ipAddrStr))
968 coap = OC_COAP_SCHEME;
969 while (*coap && tolower(*itr) == *coap)
978 if (isdigit(*ipAddrStr))
981 ipAddr[index] += *ipAddrStr - '0';
983 else if (*ipAddrStr == '.')
995 if(*ipAddrStr == ':')
999 if (isdigit(*ipAddrStr))
1002 *port += *ipAddrStr - '0';
1023 //-----------------------------------------------------------------------------
1024 // Private internal function prototypes
1025 //-----------------------------------------------------------------------------
1027 static OCDoHandle GenerateInvocationHandle();
1028 static OCStackResult initResources();
1029 static void insertResource(OCResource *resource);
1030 static OCResource *findResource(OCResource *resource);
1031 static void insertResourceType(OCResource *resource,
1032 OCResourceType *resourceType);
1033 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1035 static void insertResourceInterface(OCResource *resource,
1036 OCResourceInterface *resourceInterface);
1037 static OCResourceInterface *findResourceInterfaceAtIndex(
1038 OCResourceHandle handle, uint8_t index);
1039 static void deleteResourceType(OCResourceType *resourceType);
1040 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1041 static void deleteResourceElements(OCResource *resource);
1042 static OCStackResult deleteResource(OCResource *resource);
1043 static void deleteAllResources();
1044 static void incrementSequenceNumber(OCResource * resPtr);
1045 static OCStackResult verifyUriQueryLength(const char * inputUri,
1047 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1048 OCStackResult getResourceType(const char * query, char** resourceType);
1049 static CAResult_t OCSelectNetwork();
1051 //-----------------------------------------------------------------------------
1053 //-----------------------------------------------------------------------------
1056 * Initialize the OC Stack. Must be called prior to starting the stack.
1059 * IP Address of host device
1061 * Port of host device
1063 * Host device is client, server, or client-server
1066 * OC_STACK_OK - no errors
1067 * OC_STACK_ERROR - stack init error
1069 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1073 OCStackResult result = OC_STACK_ERROR;
1074 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1077 if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
1079 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1080 return OC_STACK_ERROR;
1084 defaultDeviceHandler = NULL;
1087 result = CAResultToOCResult(CAInitialize());
1088 VERIFY_SUCCESS(result, OC_STACK_OK);
1090 result = CAResultToOCResult(OCSelectNetwork());
1091 VERIFY_SUCCESS(result, OC_STACK_OK);
1093 CARegisterHandler(HandleCARequests, HandleCAResponses);
1094 switch (myStackMode)
1097 result = CAResultToOCResult(CAStartDiscoveryServer());
1098 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1101 result = CAResultToOCResult(CAStartListeningServer());
1102 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1104 case OC_CLIENT_SERVER:
1105 result = CAResultToOCResult(CAStartListeningServer());
1106 if(result == OC_STACK_OK)
1108 result = CAResultToOCResult(CAStartDiscoveryServer());
1112 VERIFY_SUCCESS(result, OC_STACK_OK);
1114 #if defined(__WITH_DTLS__)
1115 result = (CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials) == CA_STATUS_OK) ?
1116 OC_STACK_OK : OC_STACK_ERROR;
1117 VERIFY_SUCCESS(result, OC_STACK_OK);
1118 #endif // (__WITH_DTLS__)
1120 #ifdef WITH_PRESENCE
1121 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1122 #endif // WITH_PRESENCE
1124 //Update Stack state to initialized
1125 stackState = OC_STACK_INITIALIZED;
1127 // Initialize resource
1128 if(myStackMode != OC_CLIENT)
1130 result = initResources();
1134 if(result != OC_STACK_OK)
1136 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1137 deleteAllResources();
1139 stackState = OC_STACK_UNINITIALIZED;
1145 * Stop the OC stack. Use for a controlled shutdown.
1147 * OC_STACK_OK - no errors
1148 * OC_STACK_ERROR - stack not initialized
1150 OCStackResult OCStop()
1152 OCStackResult result = OC_STACK_ERROR;
1154 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1156 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1158 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1161 else if (stackState != OC_STACK_INITIALIZED)
1163 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1164 return OC_STACK_ERROR;
1167 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1169 #ifdef WITH_PRESENCE
1170 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1171 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1172 presenceResource.presenceTTL = 0;
1173 #endif // WITH_PRESENCE
1175 // Free memory dynamically allocated for resources
1176 deleteAllResources();
1179 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1180 result = OC_STACK_OK;
1182 if (result == OC_STACK_OK)
1184 // Remove all observers
1185 DeleteObserverList();
1186 // Remove all the client callbacks
1187 DeleteClientCBList();
1188 stackState = OC_STACK_UNINITIALIZED;
1189 result = OC_STACK_OK;
1191 stackState = OC_STACK_INITIALIZED;
1192 result = OC_STACK_ERROR;
1195 // Deinit security blob
1196 DeinitOCSecurityInfo();
1198 if (result != OC_STACK_OK) {
1199 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1206 * Map OCQualityOfService to CAMessageType
1208 * @param OCQualityOfService - Input qos.
1210 * Returns CA message type for a given qos.
1212 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1217 return CA_MSG_CONFIRM;
1222 return CA_MSG_NONCONFIRM;
1227 * Verify the lengths of the URI and the query separately
1229 * @param inputUri - Input URI and query.
1230 * @param uriLen - The length of the initial URI with query.
1232 * Note: The '?' that appears after the URI is not considered as
1233 * a part of the query.
1235 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1239 query = strchr (inputUri, '?');
1243 if((query - inputUri) > MAX_URI_LENGTH)
1245 return OC_STACK_INVALID_URI;
1248 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1250 return OC_STACK_INVALID_QUERY;
1253 else if(uriLen > MAX_URI_LENGTH)
1255 return OC_STACK_INVALID_URI;
1261 * Discover or Perform requests on a specified resource
1262 * (specified by that Resource's respective URI).
1264 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
1266 * @param method - @ref OCMethod to perform on the resource
1267 * @param requiredUri - URI of the resource to interact with
1268 * @param referenceUri - URI of the reference resource
1269 * @param request - JSON encoded request
1270 * @param qos - quality of service
1271 * @param cbData - struct that contains asynchronous callback function that is invoked
1272 * by the stack when discovery or resource interaction is complete
1273 * @param options - The address of an array containing the vendor specific header
1274 * header options to be sent with the request
1275 * @param numOptions - Number of vendor specific header options to be included
1278 * OC_STACK_OK - no errors
1279 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1280 * OC_STACK_INVALID_METHOD - invalid resource method
1281 * OC_STACK_INVALID_URI - invalid required or reference URI
1283 * Note: when using multicast, the required URI should not contain IP address.
1284 * Instead, it just contains the URI to the resource such as "/oc/core".
1286 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1287 const char *referenceUri, const char *request, OCConnectivityType conType,
1288 OCQualityOfService qos, OCCallbackData *cbData,
1289 OCHeaderOption * options, uint8_t numOptions)
1291 OCStackResult result = OC_STACK_ERROR;
1292 ClientCB *clientCB = NULL;
1293 char * requestUri = NULL;
1294 char * resourceType = NULL;
1295 char * query = NULL;
1296 char * newUri = (char *)requiredUri;
1297 (void) referenceUri;
1298 CARemoteEndpoint_t* endpoint = NULL;
1299 CAResult_t caResult;
1300 CAToken_t token = NULL;
1301 OCDoHandle resHandle = NULL;
1302 CAInfo_t requestData ={};
1303 CARequestInfo_t requestInfo ={};
1304 CAGroupEndpoint_t grpEnd = {};
1306 // To track if memory is allocated for additional header options
1308 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1310 // Validate input parameters
1311 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1312 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1314 //TODO ("Need to form the final query by concatenating require and reference URI's");
1315 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1317 uint16_t uriLen = strlen(requiredUri);
1319 // ToDo: We should also check if the requiredUri has a mutlicast address,
1320 // then qos has to be OC_Low_QOS
1326 case OC_REST_DELETE:
1327 case OC_REST_OBSERVE:
1328 case OC_REST_OBSERVE_ALL:
1329 case OC_REST_CANCEL_OBSERVE:
1331 #ifdef WITH_PRESENCE
1332 case OC_REST_PRESENCE:
1336 result = OC_STACK_INVALID_METHOD;
1340 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1345 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1347 result = OC_STACK_INVALID_PARAM;
1351 #ifdef WITH_PRESENCE
1352 if(method == OC_REST_PRESENCE)
1354 result = getQueryFromUri(requiredUri, &query, &newUri);
1357 result = getResourceType((char *) query, &resourceType);
1360 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1364 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1369 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1371 if(result != OC_STACK_OK)
1376 #endif // WITH_PRESENCE
1378 requestUri = (char *) OCMalloc(uriLen + 1);
1381 memcpy(requestUri, newUri, (uriLen + 1));
1385 result = OC_STACK_NO_MEMORY;
1389 resHandle = GenerateInvocationHandle();
1392 result = OC_STACK_NO_MEMORY;
1399 case OC_REST_OBSERVE:
1400 case OC_REST_OBSERVE_ALL:
1401 case OC_REST_CANCEL_OBSERVE:
1403 requestInfo.method = CA_GET;
1408 requestInfo.method = CA_PUT;
1413 requestInfo.method = CA_POST;
1416 case OC_REST_DELETE:
1418 requestInfo.method = CA_DELETE;
1421 #ifdef WITH_PRESENCE
1422 case OC_REST_PRESENCE:
1424 // Replacing method type with GET because "presence"
1425 // is a stack layer only implementation.
1426 requestInfo.method = CA_GET;
1431 result = OC_STACK_INVALID_METHOD;
1435 //High QoS is not supported
1436 if(qos == OC_HIGH_QOS)
1438 result = OC_STACK_INVALID_PARAM;
1443 caResult = CAGenerateToken(&token);
1444 if (caResult != CA_STATUS_OK)
1446 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1447 CADestroyToken(token);
1451 requestData.type = qualityOfServiceToMessageType(qos);
1452 requestData.token = token;
1453 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1455 result = CreateObserveHeaderOption (&(requestData.options), options,
1456 numOptions, OC_OBSERVE_REGISTER);
1457 if (result != OC_STACK_OK)
1461 requestData.numOptions = numOptions + 1;
1465 requestData.options = (CAHeaderOption_t*)options;
1466 requestData.numOptions = numOptions;
1468 requestData.payload = (char *)request;
1470 requestInfo.info = requestData;
1472 CAConnectivityType_t caConType;
1474 result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
1475 if (result != OC_STACK_OK)
1477 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1482 if(conType == OC_ALL)
1484 grpEnd.connectivityType = caConType;
1486 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1487 if(!grpEnd.resourceUri)
1489 result = OC_STACK_NO_MEMORY;
1492 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1494 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1498 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1500 if (caResult != CA_STATUS_OK)
1502 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1506 caResult = CASendRequest(endpoint, &requestInfo);
1509 if (caResult != CA_STATUS_OK)
1511 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1515 if((result = AddClientCB(&clientCB, cbData, &token, &resHandle, method,
1516 requestUri, resourceType)) != OC_STACK_OK)
1518 result = OC_STACK_NO_MEMORY;
1524 *handle = resHandle;
1528 if(newUri != requiredUri)
1532 if (result != OC_STACK_OK)
1534 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1535 FindAndDeleteClientCB(clientCB);
1538 CADestroyRemoteEndpoint(endpoint);
1539 OCFree(grpEnd.resourceUri);
1540 if (requestData.options && requestData.numOptions > 0)
1542 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1544 OCFree(requestData.options);
1551 * Cancel a request associated with a specific @ref OCDoResource invocation.
1553 * @param handle - Used to identify a specific OCDoResource invocation.
1554 * @param qos - used to specify Quality of Service (read below for more info)
1555 * @param options- used to specify vendor specific header options when sending
1556 * explicit observe cancellation
1557 * @param numOptions- Number of header options to be included
1560 * OC_STACK_OK - No errors; Success
1561 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1563 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1567 * This ftn is implemented one of two ways in the case of observation:
1569 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1570 * Remove the callback associated on client side.
1571 * When the next notification comes in from server,
1572 * reply with RESET message to server.
1573 * Keep in mind that the server will react to RESET only
1574 * if the last notification was sent ans CON
1576 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1577 * and it is associated with an observe request
1578 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1579 * Send CON Observe request to server with
1580 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1581 * Remove the callback associated on client side.
1583 OCStackResult ret = OC_STACK_OK;
1584 CARemoteEndpoint_t* endpoint = NULL;
1585 CAResult_t caResult= CA_STATUS_OK;
1586 CAInfo_t requestData = {};
1587 CARequestInfo_t requestInfo = {};
1591 return OC_STACK_INVALID_PARAM;
1594 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1596 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1600 switch (clientCB->method)
1602 case OC_REST_OBSERVE:
1603 case OC_REST_OBSERVE_ALL:
1604 //TODO-CA : Why CA_WIFI alone?
1605 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1607 if (caResult != CA_STATUS_OK)
1609 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1610 return OC_STACK_ERROR;
1613 memset(&requestData, 0, sizeof(CAInfo_t));
1614 requestData.type = qualityOfServiceToMessageType(qos);
1615 requestData.token = clientCB->token;
1616 if (CreateObserveHeaderOption (&(requestData.options),
1617 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1619 return OC_STACK_ERROR;
1621 requestData.numOptions = numOptions + 1;
1622 requestInfo.method = CA_GET;
1623 requestInfo.info = requestData;
1625 caResult = CASendRequest(endpoint, &requestInfo);
1626 if (caResult != CA_STATUS_OK)
1628 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1630 if(caResult == CA_STATUS_OK)
1634 #ifdef WITH_PRESENCE
1635 case OC_REST_PRESENCE:
1636 FindAndDeleteClientCB(clientCB);
1640 return OC_STACK_INVALID_METHOD;
1643 CADestroyRemoteEndpoint(endpoint);
1644 if (requestData.numOptions > 0)
1646 OCFree(requestData.options);
1652 #ifdef WITH_PRESENCE
1653 OCStackResult OCProcessPresence()
1655 OCStackResult result = OC_STACK_OK;
1656 uint8_t ipAddr[4] = { 0 };
1659 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1660 ClientCB* cbNode = NULL;
1662 OCClientResponse clientResponse ={};
1663 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1665 LL_FOREACH(cbList, cbNode)
1667 if(OC_REST_PRESENCE == cbNode->method)
1669 if(cbNode->presence)
1671 uint32_t now = GetTime(0);
1672 OC_LOG_V(DEBUG, TAG, "this TTL level %d",
1673 cbNode->presence->TTLlevel);
1674 OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
1677 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1682 if(cbNode->presence->TTLlevel < PresenceTimeOutSize)
1684 OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
1685 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1688 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1690 OC_LOG(DEBUG, TAG, PCF("No more timeout ticks"));
1691 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1693 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1696 clientResponse.sequenceNumber = 0;
1697 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
1698 clientResponse.addr = (OCDevAddr *) &dst;
1699 clientResponse.resJSONPayload = NULL;
1701 // Increment the TTLLevel (going to a next state), so we don't keep
1702 // sending presence notification to client.
1703 cbNode->presence->TTLlevel++;
1704 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
1705 cbNode->presence->TTLlevel);
1709 result = OC_STACK_INVALID_IP;
1713 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1714 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1716 FindAndDeleteClientCB(cbNode);
1720 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1722 CAResult_t caResult = CA_STATUS_OK;
1723 CARemoteEndpoint_t* endpoint = NULL;
1724 CAInfo_t requestData ={};
1725 CARequestInfo_t requestInfo = {};
1727 OC_LOG(DEBUG, TAG, PCF("time to test server presence"));
1729 //TODO-CA : Why CA_WIFI alone?
1730 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1733 if (caResult != CA_STATUS_OK)
1735 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1739 requestData.type = CA_MSG_NONCONFIRM;
1740 requestData.token = cbNode->token;
1742 requestInfo.method = CA_GET;
1743 requestInfo.info = requestData;
1745 caResult = CASendRequest(endpoint, &requestInfo);
1747 if (caResult != CA_STATUS_OK)
1749 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1753 cbNode->presence->TTLlevel++;
1754 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
1755 cbNode->presence->TTLlevel);
1761 if (result != OC_STACK_OK)
1763 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1767 #endif // WITH_PRESENCE
1770 * Called in main loop of OC client or server. Allows low-level processing of
1774 * OC_STACK_OK - no errors
1775 * OC_STACK_ERROR - stack process error
1777 OCStackResult OCProcess()
1779 #ifdef WITH_PRESENCE
1780 OCProcessPresence();
1782 CAHandleRequestResponse();
1787 #ifdef WITH_PRESENCE
1789 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
1790 * presence notifications to clients via multicast. Once this API has been called with a success,
1791 * clients may query for this server's presence and this server's stack will respond via multicast.
1793 * Server can call this function when it comes online for the first time, or when it comes back
1794 * online from offline mode, or when it re enters network.
1796 * @param ttl - Time To Live in seconds
1797 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
1800 * OC_STACK_OK - No errors; Success
1802 OCStackResult OCStartPresence(const uint32_t ttl)
1804 OCChangeResourceProperty(
1805 &(((OCResource *)presenceResource.handle)->resourceProperties),
1810 presenceResource.presenceTTL = ttl;
1813 if(OC_PRESENCE_UNINITIALIZED == presenceState)
1815 presenceState = OC_PRESENCE_INITIALIZED;
1817 CAAddress_t addressInfo;
1818 strncpy(addressInfo.IP.ipAddress, OC_MULTICAST_IP, CA_IPADDR_SIZE);
1819 addressInfo.IP.port = 5683;
1821 //TODO make sure there is no memory leak here since another copy
1822 //of token is being created inside AddObserver
1823 CAToken_t caToken = NULL;
1824 CAResult_t caResult = CAGenerateToken(&caToken);
1825 if (caResult != CA_STATUS_OK)
1827 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1828 CADestroyToken(caToken);
1829 return OC_STACK_ERROR;
1832 CAConnectivityType_t connType;
1833 OCToCAConnectivityType(OC_ALL, &connType );
1834 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
1835 (OCResource *)presenceResource.handle, OC_LOW_QOS,
1836 &addressInfo, connType);
1839 // Each time OCStartPresence is called
1840 // a different random 32-bit integer number is used
1841 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1843 return SendPresenceNotification(NULL);
1847 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
1848 * presence notifications to clients via multicast. Once this API has been called with a success,
1849 * this server's stack will not respond to clients querying for this server's presence.
1851 * Server can call this function when it is terminating, going offline, or when going
1852 * away from network.
1855 * OC_STACK_OK - No errors; Success
1857 OCStackResult OCStopPresence()
1859 OCStackResult result = OC_STACK_ERROR;
1861 if(presenceResource.handle)
1863 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1866 // make resource inactive
1867 result = OCChangeResourceProperty(
1868 &(((OCResource *) presenceResource.handle)->resourceProperties),
1871 if(result != OC_STACK_OK)
1874 PCF("Changing the presence resource properties to ACTIVE not successful"));
1878 return SendStopNotification();
1883 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
1885 defaultDeviceHandler = entityHandler;
1890 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
1892 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
1894 if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
1896 return SaveDeviceInfo(deviceInfo);
1900 return OC_STACK_ERROR;
1907 * @param handle - pointer to handle to newly created resource. Set by ocstack.
1908 * Used to refer to resource
1909 * @param resourceTypeName - name of resource type. Example: "core.led"
1910 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
1911 * @param uri - URI of the resource. Example: "/a/led"
1912 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1913 * NULL for default entity handler
1914 * @param resourceProperties - properties supported by resource.
1915 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
1918 * OC_STACK_OK - no errors
1919 * OC_STACK_ERROR - stack process error
1921 OCStackResult OCCreateResource(OCResourceHandle *handle,
1922 const char *resourceTypeName,
1923 const char *resourceInterfaceName,
1924 const char *uri, OCEntityHandler entityHandler,
1925 uint8_t resourceProperties)
1928 OCResource *pointer = NULL;
1931 OCStackResult result = OC_STACK_ERROR;
1933 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
1935 if(myStackMode == OC_CLIENT)
1937 return OC_STACK_INVALID_PARAM;
1939 // Validate parameters
1940 if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
1942 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
1943 return OC_STACK_INVALID_URI;
1945 // Is it presented during resource discovery?
1946 if (!handle || !resourceTypeName)
1948 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
1949 return OC_STACK_INVALID_PARAM;
1952 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
1954 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
1957 // Make sure resourceProperties bitmask has allowed properties specified
1958 if (resourceProperties
1959 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
1960 OC_LOG(ERROR, TAG, PCF("Invalid property"));
1961 return OC_STACK_INVALID_PARAM;
1964 // If the headResource is NULL, then no resources have been created...
1965 pointer = headResource;
1968 // At least one resources is in the resource list, so we need to search for
1969 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
1972 if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
1974 OC_LOG(ERROR, TAG, PCF("URI already in use"));
1975 return OC_STACK_INVALID_PARAM;
1977 pointer = pointer->next;
1980 // Create the pointer and insert it into the resource list
1981 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
1984 result = OC_STACK_NO_MEMORY;
1987 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
1989 insertResource(pointer);
1992 size = strlen(uri) + 1;
1993 str = (char *) OCMalloc(size);
1996 result = OC_STACK_NO_MEMORY;
1999 strncpy(str, uri, size);
2002 // Set properties. Set OC_ACTIVE
2003 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2006 // Add the resourcetype to the resource
2007 result = BindResourceTypeToResource(pointer, resourceTypeName);
2008 if (result != OC_STACK_OK)
2010 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2014 // Add the resourceinterface to the resource
2015 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2016 if (result != OC_STACK_OK)
2018 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2022 // If an entity handler has been passed, attach it to the newly created
2023 // resource. Otherwise, set the default entity handler.
2026 pointer->entityHandler = entityHandler;
2030 pointer->entityHandler = defaultResourceEHandler;
2034 result = OC_STACK_OK;
2036 #ifdef WITH_PRESENCE
2037 if(presenceResource.handle)
2039 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2040 SendPresenceNotification(pointer->rsrcType);
2044 if (result != OC_STACK_OK)
2046 // Deep delete of resource and other dynamic elements that it contains
2047 deleteResource(pointer);
2056 * Create a resource. with host ip address for remote resource
2058 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2059 * Used to refer to resource
2060 * @param resourceTypeName - name of resource type. Example: "core.led"
2061 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2062 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2063 * @param uri - URI of the resource. Example: "/a/led"
2064 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2065 * NULL for default entity handler
2066 * @param resourceProperties - properties supported by resource.
2067 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2070 * OC_STACK_OK - no errors
2071 * OC_STACK_ERROR - stack process error
2074 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2075 const char *resourceTypeName,
2076 const char *resourceInterfaceName,
2079 OCEntityHandler entityHandler,
2080 uint8_t resourceProperties)
2087 return OC_STACK_INVALID_PARAM;
2090 OCStackResult result = OC_STACK_ERROR;
2092 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2093 uri, entityHandler, resourceProperties);
2095 if (result != OC_STACK_ERROR)
2098 size = strlen(host) + 1;
2099 str = (char *) OCMalloc(size);
2102 return OC_STACK_NO_MEMORY;
2104 strncpy(str, host, size);
2105 ((OCResource *) *handle)->host = str;
2112 * Add a resource to a collection resource.
2114 * @param collectionHandle - handle to the collection resource
2115 * @param resourceHandle - handle to resource to be added to the collection resource
2118 * OC_STACK_OK - no errors
2119 * OC_STACK_ERROR - stack process error
2120 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2122 OCStackResult OCBindResource(
2123 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2125 OCResource *resource = NULL;
2128 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2130 // Validate parameters
2131 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2132 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2133 // Container cannot contain itself
2134 if (collectionHandle == resourceHandle)
2136 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2137 return OC_STACK_INVALID_PARAM;
2140 // Use the handle to find the resource in the resource linked list
2141 resource = findResource((OCResource *) collectionHandle);
2144 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2145 return OC_STACK_INVALID_PARAM;
2148 // Look for an open slot to add add the child resource.
2149 // If found, add it and return success
2150 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2152 if (!resource->rsrcResources[i])
2154 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2155 OC_LOG(INFO, TAG, PCF("resource bound"));
2157 #ifdef WITH_PRESENCE
2158 if(presenceResource.handle)
2160 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2161 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2169 // Unable to add resourceHandle, so return error
2170 return OC_STACK_ERROR;
2174 * Remove a resource from a collection resource.
2176 * @param collectionHandle - handle to the collection resource
2177 * @param resourceHandle - handle to resource to be added to the collection resource
2180 * OC_STACK_OK - no errors
2181 * OC_STACK_ERROR - stack process error
2182 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2184 OCStackResult OCUnBindResource(
2185 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2187 OCResource *resource = NULL;
2190 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2192 // Validate parameters
2193 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2194 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2195 // Container cannot contain itself
2196 if (collectionHandle == resourceHandle)
2198 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2199 return OC_STACK_INVALID_PARAM;
2202 // Use the handle to find the resource in the resource linked list
2203 resource = findResource((OCResource *) collectionHandle);
2206 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2207 return OC_STACK_INVALID_PARAM;
2210 // Look for an open slot to add add the child resource.
2211 // If found, add it and return success
2212 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2214 if (resourceHandle == resource->rsrcResources[i])
2216 resource->rsrcResources[i] = (OCResource *) NULL;
2217 OC_LOG(INFO, TAG, PCF("resource unbound"));
2219 // Send notification when resource is unbounded successfully.
2220 #ifdef WITH_PRESENCE
2221 if(presenceResource.handle)
2223 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2224 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2231 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2233 // Unable to add resourceHandle, so return error
2234 return OC_STACK_ERROR;
2237 OCStackResult BindResourceTypeToResource(OCResource* resource,
2238 const char *resourceTypeName)
2240 OCResourceType *pointer = NULL;
2243 OCStackResult result = OC_STACK_ERROR;
2245 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2247 // Validate parameters
2248 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2249 // TODO: Does resource attribute resentation really have to be maintained in stack?
2250 // Is it presented during resource discovery?
2252 //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2254 // Create the resourcetype and insert it into the resource list
2255 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2258 result = OC_STACK_NO_MEMORY;
2262 // Set the resourceTypeName
2263 size = strlen(resourceTypeName) + 1;
2264 str = (char *) OCMalloc(size);
2267 result = OC_STACK_NO_MEMORY;
2270 strncpy(str, resourceTypeName, size);
2271 pointer->resourcetypename = str;
2273 insertResourceType(resource, pointer);
2274 result = OC_STACK_OK;
2277 if (result != OC_STACK_OK)
2286 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2287 const char *resourceInterfaceName)
2289 OCResourceInterface *pointer = NULL;
2292 OCStackResult result = OC_STACK_ERROR;
2294 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2296 // Validate parameters
2297 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2299 //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2301 // Create the resourceinterface and insert it into the resource list
2302 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2305 result = OC_STACK_NO_MEMORY;
2309 // Set the resourceinterface name
2310 size = strlen(resourceInterfaceName) + 1;
2311 str = (char *) OCMalloc(size);
2314 result = OC_STACK_NO_MEMORY;
2317 strncpy(str, resourceInterfaceName, size);
2318 pointer->name = str;
2320 // Bind the resourceinterface to the resource
2321 insertResourceInterface(resource, pointer);
2323 result = OC_STACK_OK;
2326 if (result != OC_STACK_OK)
2336 * Bind a resourcetype to a resource.
2338 * @param handle - handle to the resource
2339 * @param resourceTypeName - name of resource type. Example: "core.led"
2342 * OC_STACK_OK - no errors
2343 * OC_STACK_ERROR - stack process error
2345 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2346 const char *resourceTypeName)
2349 OCStackResult result = OC_STACK_ERROR;
2350 OCResource *resource = NULL;
2352 // Make sure resource exists
2353 resource = findResource((OCResource *) handle);
2356 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2357 return OC_STACK_ERROR;
2360 // call internal function
2361 result = BindResourceTypeToResource(resource, resourceTypeName);
2363 #ifdef WITH_PRESENCE
2364 if(presenceResource.handle)
2366 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2367 SendPresenceNotification(resource->rsrcType);
2375 * Bind a resourceinterface to a resource.
2377 * @param handle - handle to the resource
2378 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2381 * OC_STACK_OK - no errors
2382 * OC_STACK_ERROR - stack process error
2385 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2386 const char *resourceInterfaceName)
2389 OCStackResult result = OC_STACK_ERROR;
2390 OCResource *resource = NULL;
2392 // Make sure resource exists
2393 resource = findResource((OCResource *) handle);
2396 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2397 return OC_STACK_ERROR;
2400 // call internal function
2401 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2403 #ifdef WITH_PRESENCE
2404 if(presenceResource.handle)
2406 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2407 SendPresenceNotification(resource->rsrcType);
2415 * Get the number of resources that have been created in the stack.
2417 * @param numResources - pointer to count variable
2420 * OC_STACK_OK - no errors
2421 * OC_STACK_ERROR - stack process error
2424 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
2426 OCResource *pointer = headResource;
2428 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2429 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2433 *numResources = *numResources + 1;
2434 pointer = pointer->next;
2440 * Get a resource handle by index.
2442 * @param index - index of resource, 0 to Count - 1
2445 * Resource handle - if found
2446 * NULL - if not found
2448 OCResourceHandle OCGetResourceHandle(uint8_t index)
2450 OCResource *pointer = headResource;
2452 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2454 // Iterate through the list
2455 for( uint8_t i = 0; i < index && pointer; ++i)
2457 pointer = pointer->next;
2459 return (OCResourceHandle) pointer;
2463 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2466 * @param handle - handle of resource to be deleted
2469 * OC_STACK_OK - no errors
2470 * OC_STACK_ERROR - stack process error
2471 * OC_STACK_NO_RESOURCE - resource not found
2472 * OC_STACK_INVALID_PARAM - invalid param
2474 OCStackResult OCDeleteResource(OCResourceHandle handle)
2476 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2480 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2481 return OC_STACK_INVALID_PARAM;
2484 OCResource *resource = findResource((OCResource *) handle);
2485 if (resource == NULL)
2487 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2488 return OC_STACK_NO_RESOURCE;
2491 if (deleteResource((OCResource *) handle) != OC_STACK_OK)
2493 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2494 return OC_STACK_ERROR;
2501 * Get the URI of the resource specified by handle.
2503 * @param handle - handle of resource
2505 * URI string - if resource found
2506 * NULL - resource not found
2508 const char *OCGetResourceUri(OCResourceHandle handle)
2510 OCResource *resource = NULL;
2511 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2513 resource = findResource((OCResource *) handle);
2516 return resource->uri;
2518 return (const char *) NULL;
2522 * Get the properties of the resource specified by handle.
2523 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2524 * for the resource by the stack.
2526 * @param handle - handle of resource
2528 * OCResourceProperty Bitmask
2529 * -1 if resource is not found
2531 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
2533 OCResource *resource = NULL;
2534 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2536 resource = findResource((OCResource *) handle);
2539 return resource->resourceProperties;
2541 return (OCResourceProperty)-1;
2545 * Get the number of resource types of the resource.
2547 * @param handle - handle of resource
2548 * @param numResourceTypes - pointer to count variable
2551 * OC_STACK_OK - no errors
2552 * OC_STACK_ERROR - stack process error
2554 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2555 uint8_t *numResourceTypes)
2557 OCResource *resource = NULL;
2558 OCResourceType *pointer = NULL;
2560 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2561 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2562 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2564 *numResourceTypes = 0;
2566 resource = findResource((OCResource *) handle);
2569 pointer = resource->rsrcType;
2572 *numResourceTypes = *numResourceTypes + 1;
2573 pointer = pointer->next;
2580 * Get name of resource type of the resource.
2582 * @param handle - handle of resource
2583 * @param index - index of resource, 0 to Count - 1
2586 * resource type name - if resource found
2587 * NULL - resource not found
2589 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
2591 OCResourceType *resourceType = NULL;
2593 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2595 resourceType = findResourceTypeAtIndex(handle, index);
2598 return resourceType->resourcetypename;
2600 return (const char *) NULL;
2606 * Get the number of resource interfaces of the resource.
2608 * @param handle - handle of resource
2609 * @param numResources - pointer to count variable
2612 * OC_STACK_OK - no errors
2613 * OC_STACK_ERROR - stack process error
2615 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2616 uint8_t *numResourceInterfaces)
2618 OCResourceInterface *pointer = NULL;
2619 OCResource *resource = NULL;
2621 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2623 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2624 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2626 *numResourceInterfaces = 0;
2627 resource = findResource((OCResource *) handle);
2630 pointer = resource->rsrcInterface;
2633 *numResourceInterfaces = *numResourceInterfaces + 1;
2634 pointer = pointer->next;
2641 * Get name of resource interface of the resource.
2643 * @param handle - handle of resource
2644 * @param index - index of resource, 0 to Count - 1
2647 * resource interface name - if resource found
2648 * NULL - resource not found
2650 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
2652 OCResourceInterface *resourceInterface = NULL;
2654 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2656 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2657 if (resourceInterface)
2659 return resourceInterface->name;
2661 return (const char *) NULL;
2665 * Get resource handle from the collection resource by index.
2667 * @param collectionHandle - handle of collection resource
2668 * @param index - index of contained resource, 0 to Count - 1
2671 * handle to resource - if resource found
2672 * NULL - resource not found
2674 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2677 OCResource *resource = NULL;
2679 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2681 if (index >= MAX_CONTAINED_RESOURCES)
2686 resource = findResource((OCResource *) collectionHandle);
2692 return resource->rsrcResources[index];
2696 * Bind an entity handler to the resource.
2698 * @param handle - handle to the resource that the contained resource is to be bound
2699 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2701 * OC_STACK_OK - no errors
2702 * OC_STACK_ERROR - stack process error
2704 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2705 OCEntityHandler entityHandler)
2707 OCResource *resource = NULL;
2709 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2711 // Validate parameters
2712 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2714 // Use the handle to find the resource in the resource linked list
2715 resource = findResource((OCResource *)handle);
2718 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2719 return OC_STACK_ERROR;
2723 resource->entityHandler = entityHandler;
2725 #ifdef WITH_PRESENCE
2726 if(presenceResource.handle)
2728 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2729 SendPresenceNotification(resource->rsrcType);
2737 * Get the entity handler for a resource.
2739 * @param handle - handle of resource
2742 * entity handler - if resource found
2743 * NULL - resource not found
2745 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
2747 OCResource *resource = NULL;
2749 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2751 // Use the handle to find the resource in the resource linked list
2752 resource = findResource((OCResource *)handle);
2755 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2760 return resource->entityHandler;
2763 void incrementSequenceNumber(OCResource * resPtr)
2765 // Increment the sequence number
2766 resPtr->sequenceNum += 1;
2767 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2769 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2775 * Notify Presence subscribers that a resource has been modified
2777 * @param resourceType - Handle to the resourceType linked list of resource
2778 * that was modified.
2779 * @param qos - Quality Of Service
2782 * OC_STACK_OK - no errors
2783 * OC_STACK_ERROR - stack process error
2785 #ifdef WITH_PRESENCE
2788 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2790 OCResource *resPtr = NULL;
2791 OCStackResult result = OC_STACK_ERROR;
2792 OCMethod method = OC_REST_PRESENCE;
2793 uint32_t maxAge = 0;
2794 resPtr = findResource((OCResource *) presenceResource.handle);
2797 return OC_STACK_NO_RESOURCE;
2800 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2802 maxAge = presenceResource.presenceTTL;
2804 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2811 * Send Stop Notification to Presence subscribers
2814 * OC_STACK_OK - no errors
2815 * OC_STACK_ERROR - stack process error
2819 OCStackResult SendStopNotification()
2821 OCResource *resPtr = NULL;
2822 OCStackResult result = OC_STACK_ERROR;
2823 OCMethod method = OC_REST_PRESENCE;
2824 resPtr = findResource((OCResource *) presenceResource.handle);
2827 return OC_STACK_NO_RESOURCE;
2830 // maxAge is 0. ResourceType is NULL.
2831 result = SendAllObserverNotification(method, resPtr, 0, NULL, OC_LOW_QOS);
2836 #endif // WITH_PRESENCE
2838 * Notify observers that an observed value has changed.
2840 * @param handle - handle of resource
2843 * OC_STACK_OK - no errors
2844 * OC_STACK_NO_RESOURCE - invalid resource handle
2845 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2847 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
2850 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2852 OCResource *resPtr = NULL;
2853 OCStackResult result = OC_STACK_ERROR;
2854 OCMethod method = OC_REST_NOMETHOD;
2855 uint32_t maxAge = 0;
2857 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2858 #ifdef WITH_PRESENCE
2859 if(handle == presenceResource.handle)
2863 #endif // WITH_PRESENCE
2864 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2866 // Verify that the resource exists
2867 resPtr = findResource ((OCResource *) handle);
2870 return OC_STACK_NO_RESOURCE;
2874 //only increment in the case of regular observing (not presence)
2875 incrementSequenceNumber(resPtr);
2876 method = OC_REST_OBSERVE;
2877 maxAge = MAX_OBSERVE_AGE;
2878 #ifdef WITH_PRESENCE
2879 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
2881 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
2888 OCNotifyListOfObservers (OCResourceHandle handle,
2889 OCObservationId *obsIdList,
2890 uint8_t numberOfIds,
2891 const char *notificationJSONPayload,
2892 OCQualityOfService qos)
2894 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
2896 OCResource *resPtr = NULL;
2897 //TODO: we should allow the server to define this
2898 uint32_t maxAge = MAX_OBSERVE_AGE;
2900 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2901 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
2902 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
2904 // Verify that the resource exists
2905 resPtr = findResource ((OCResource *) handle);
2906 if (NULL == resPtr || myStackMode == OC_CLIENT)
2908 return OC_STACK_NO_RESOURCE;
2912 incrementSequenceNumber(resPtr);
2914 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
2915 notificationJSONPayload, maxAge, qos));
2919 * Send a response to a request.
2920 * The response can be a regular, slow, or block (i.e. a response that
2921 * is too large to be sent in a single PDU and must span multiple transmissions)
2923 * @param response - pointer to structure that contains response parameters
2926 * OC_STACK_OK - No errors; Success
2927 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
2928 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
2929 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
2930 * persistent response buffer is necessary
2932 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
2934 OCStackResult result = OC_STACK_ERROR;
2935 OCServerRequest *serverRequest = NULL;
2937 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
2939 // Validate input parameters
2940 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
2941 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
2943 // TODO: Placeholder for creating a response entry when implementing
2944 // block transfer feature
2946 // If a response payload is present, check if block transfer is required
2947 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
2948 (const char *)ehResponse->payload, ehResponse->payloadSize))
2950 OC_LOG(INFO, TAG, PCF("Block transfer required"));
2952 // Persistent response buffer is needed for block transfer
2953 if (!ehResponse->persistentBufferFlag)
2955 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
2956 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
2958 // TODO: Placeholder for block transfer handling
2959 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
2960 // when implementing the block transfer feature
2965 // Get pointer to request info
2966 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
2969 result = serverRequest->ehResponseHandler(ehResponse);
2976 * Cancel a response. Applies to a block response
2978 * @param responseHandle - response handle set by stack in OCServerResponse after
2979 * OCDoResponse is called
2982 * OC_STACK_OK - No errors; Success
2983 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
2985 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
2987 OCStackResult result = OC_STACK_NOTIMPL;
2989 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
2991 // TODO: validate response handle
2996 //-----------------------------------------------------------------------------
2997 // Private internal function definitions
2998 //-----------------------------------------------------------------------------
3000 * Generate handle of OCDoResource invocation for callback management.
3002 static OCDoHandle GenerateInvocationHandle()
3004 OCDoHandle handle = NULL;
3005 // Generate token here, it will be deleted when the transaction is deleted
3006 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3009 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3014 #ifdef WITH_PRESENCE
3015 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3016 OCResourceProperty resourceProperties, uint8_t enable)
3018 if (resourceProperties
3019 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3021 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3022 return OC_STACK_INVALID_PARAM;
3026 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3030 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3037 * Initialize resource data structures, variables, etc.
3039 OCStackResult initResources()
3041 OCStackResult result = OC_STACK_OK;
3042 // Init application resource vars
3043 headResource = NULL;
3044 tailResource = NULL;
3045 // Init Virtual Resources
3046 #ifdef WITH_PRESENCE
3047 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3048 //presenceResource.token = OCGenerateCoAPToken();
3049 result = OCCreateResource(&presenceResource.handle,
3050 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3055 //make resource inactive
3056 result = OCChangeResourceProperty(
3057 &(((OCResource *) presenceResource.handle)->resourceProperties),
3064 * Add a resource to the end of the linked list of resources.
3066 * @param resource - resource to be added
3068 void insertResource(OCResource *resource)
3070 OCResource *pointer = NULL;
3072 if (!headResource) {
3073 headResource = resource;
3074 tailResource = resource;
3078 tailResource->next = resource;
3079 tailResource = resource;
3081 resource->next = NULL;
3085 * Find a resource in the linked list of resources.
3087 * @param resource - resource to be found
3089 * NULL - resource not found
3090 * pointer to resource - pointer to resource that was found in the linked list
3092 OCResource *findResource(OCResource *resource)
3094 OCResource *pointer = headResource;
3098 if (pointer == resource)
3102 pointer = pointer->next;
3107 void deleteAllResources()
3109 OCResource *pointer = headResource;
3110 OCResource *temp = NULL;
3114 temp = pointer->next;
3115 #ifdef WITH_PRESENCE
3116 if(pointer != (OCResource *) presenceResource.handle)
3118 #endif // WITH_PRESENCE
3119 deleteResource(pointer);
3120 #ifdef WITH_PRESENCE
3122 #endif // WITH_PRESENCE
3126 #ifdef WITH_PRESENCE
3127 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3128 // presence notification attributed to their deletion to be processed.
3129 deleteResource((OCResource *) presenceResource.handle);
3130 #endif // WITH_PRESENCE
3134 * Delete the resource from the linked list.
3136 * @param resource - resource to be deleted
3138 * OC_STACK_ERROR - error
3139 * OC_STACK_OK - success
3141 OCStackResult deleteResource(OCResource *resource)
3143 OCResource *prev = NULL;
3144 OCResource *temp = NULL;
3146 temp = headResource;
3149 if (temp == resource)
3151 // Invalidate all Resource Properties.
3152 resource->resourceProperties = (OCResourceProperty) 0;
3153 #ifdef WITH_PRESENCE
3154 if(resource != (OCResource *) presenceResource.handle)
3156 #endif // WITH_PRESENCE
3157 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3158 #ifdef WITH_PRESENCE
3161 if(presenceResource.handle)
3163 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3164 if(resource != (OCResource *) presenceResource.handle)
3166 SendPresenceNotification(resource->rsrcType);
3170 SendPresenceNotification(NULL);
3174 // Only resource in list.
3175 if (temp == headResource && temp == tailResource)
3177 headResource = NULL;
3178 tailResource = NULL;
3181 else if (temp == headResource)
3183 headResource = temp->next;
3186 else if (temp == tailResource)
3188 tailResource = prev;
3189 tailResource->next = NULL;
3193 prev->next = temp->next;
3196 deleteResourceElements(temp);
3207 return OC_STACK_ERROR;
3211 * Delete all of the dynamically allocated elements that were created for the resource.
3213 * @param resource - specified resource
3215 void deleteResourceElements(OCResource *resource)
3223 OCFree(resource->uri);
3225 // Delete resourcetype linked list
3226 deleteResourceType(resource->rsrcType);
3228 // Delete resourceinterface linked list
3229 deleteResourceInterface(resource->rsrcInterface);
3233 * Delete all of the dynamically allocated elements that were created for the resource type.
3235 * @param resourceType - specified resource type
3237 void deleteResourceType(OCResourceType *resourceType)
3239 OCResourceType *pointer = resourceType;
3240 OCResourceType *next = NULL;
3244 next = pointer->next;
3245 OCFree(pointer->resourcetypename);
3252 * Delete all of the dynamically allocated elements that were created for the resource interface.
3254 * @param resourceInterface - specified resource interface
3256 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3258 OCResourceInterface *pointer = resourceInterface;
3259 OCResourceInterface *next = NULL;
3263 next = pointer->next;
3264 OCFree(pointer->name);
3271 * Insert a resource type into a resource's resource type linked list.
3273 * @param resource - resource where resource type is to be inserted
3274 * @param resourceType - resource type to be inserted
3276 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3278 OCResourceType *pointer = NULL;
3280 if (resource && !resource->rsrcType)
3282 resource->rsrcType = resourceType;
3288 pointer = resource->rsrcType;
3292 pointer = resourceType;
3294 while (pointer->next)
3296 pointer = pointer->next;
3298 pointer->next = resourceType;
3300 resourceType->next = NULL;
3304 * Get a resource type at the specified index within a resource.
3306 * @param handle - handle of resource
3307 * @param index - index of resource type
3310 * resourcetype - if found
3313 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3315 OCResource *resource = NULL;
3316 OCResourceType *pointer = NULL;
3318 // Find the specified resource
3319 resource = findResource((OCResource *) handle);
3325 // Make sure a resource has a resourcetype
3326 if (!resource->rsrcType)
3331 // Iterate through the list
3332 pointer = resource->rsrcType;
3333 for(uint8_t i = 0; i< index && pointer; ++i)
3335 pointer = pointer->next;
3341 * Finds a resource type in an OCResourceType link-list.
3343 * @param resourceTypeList - the link-list to be searched through
3344 * @param resourceTypeName - the key to search for
3347 * resourceType that matches the key (ie. resourceTypeName)
3348 * NULL - either an invalid parameter or this function was unable to find the key.
3350 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3352 if(resourceTypeList && resourceTypeName)
3354 OCResourceType * rtPointer = resourceTypeList;
3355 while(resourceTypeName && rtPointer)
3357 if(rtPointer->resourcetypename &&
3358 strcmp(resourceTypeName, (const char *)
3359 (rtPointer->resourcetypename)) == 0)
3363 rtPointer = rtPointer->next;
3370 * Insert a resource interface into a resource's resource interface linked list.
3372 * @param resource - resource where resource interface is to be inserted
3373 * @param resourceInterface - resource interface to be inserted
3375 void insertResourceInterface(OCResource *resource,
3376 OCResourceInterface *resourceInterface)
3378 OCResourceInterface *pointer = NULL;
3379 if (!resource->rsrcInterface)
3381 resource->rsrcInterface = resourceInterface;
3385 pointer = resource->rsrcInterface;
3386 while (pointer->next)
3388 pointer = pointer->next;
3390 pointer->next = resourceInterface;
3392 resourceInterface->next = NULL;
3396 * Get a resource interface at the specified index within a resource.
3398 * @param handle - handle of resource
3399 * @param index - index of resource interface
3402 * resourceinterface - if found
3405 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3408 OCResource *resource = NULL;
3409 OCResourceInterface *pointer = NULL;
3411 // Find the specified resource
3412 resource = findResource((OCResource *) handle);
3418 // Make sure a resource has a resourceinterface
3419 if (!resource->rsrcInterface)
3424 // Iterate through the list
3425 pointer = resource->rsrcInterface;
3427 for (uint8_t i = 0; i < index && pointer; ++i)
3429 pointer = pointer->next;
3435 * Determine if a request/response must be sent in a block transfer because it is too large to be
3436 * sent in a single PDU. This function can be used for either a request or a response
3438 * @param request - NULL or pointer to request
3439 * @param response - NULL or pointer to response
3440 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3441 * the length of the request/response
3444 * 0 - packet transfer NOT required (i.e. normal request/response)
3445 * 1 - packet transfer required (i.e. block transfer needed)
3447 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3451 // Determine if we are checking a request or a response
3454 // If size is greater than 0, use it for the request size value, otherwise
3455 // assume request is null terminated and use strlen for size value
3456 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3463 // If size is greater than 0, use it for the response size value, otherwise
3464 // assume response is null terminated and use strlen for size value
3465 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3474 * Retrieves a resource type based upon a query contains only just one
3475 * resource attribute (and that has to be of type "rt").
3477 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3478 * before passing in.
3480 * @param query - The query part of the URI
3481 * @param resourceType - The resource type to be populated; pass by reference.
3484 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3485 * OC_STACK_OK - Success
3487 OCStackResult getResourceType(const char * query, char** resourceType)
3491 return OC_STACK_INVALID_PARAM;
3494 OCStackResult result = OC_STACK_ERROR;
3496 if(strncmp(query, "rt=", 3) == 0)
3498 *resourceType = (char *) OCMalloc(strlen(query)-3 + 1);
3501 result = OC_STACK_NO_MEMORY;
3504 strcpy((char *)*resourceType, ((const char *)&query[3]));
3505 result = OC_STACK_OK;
3511 OCStackResult getQueryFromUri(const char * uri, char** query, char ** newURI)
3515 return OC_STACK_INVALID_URI;
3517 if(!query || !newURI)
3519 return OC_STACK_INVALID_PARAM;
3521 char* strTokPtr = NULL;
3522 char * leftToken = NULL;
3523 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3528 strcpy(tempURI, uri);
3530 leftToken = strtok_r(tempURI, "?", &strTokPtr);
3532 //TODO-CA: This could be simplified. Clean up required.
3533 while(leftToken != NULL)
3535 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3537 *query = (char *) OCMalloc(strlen(leftToken) + 1);
3543 strcpy(*query, leftToken);
3546 leftToken = strtok_r(NULL, "?", &strTokPtr);
3554 return OC_STACK_NO_MEMORY;
3557 const ServerID OCGetServerInstanceID(void)
3559 static bool generated = false;
3560 static ServerID sid;
3566 sid = OCGetRandom();
3571 const char* OCGetServerInstanceIDString(void)
3573 // max printed length of a base 10
3574 // uint32 is 10 characters, so 11 includes null.
3575 // This will change as the representation gets switched
3577 static char buffer[11];
3579 if (snprintf(buffer, sizeof(buffer),"%u", OCGetServerInstanceID()) < 0)
3587 /// Retrieve the IPv4 address embedded inside OCDev address data structure
3588 int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
3589 uint8_t *c, uint8_t *d )
3591 if ( !ipAddr || !a || !b || !c || !d )
3593 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
3594 return OC_STACK_INVALID_PARAM;
3597 *a = ipAddr->addr[0];
3598 *b = ipAddr->addr[1];
3599 *c = ipAddr->addr[2];
3600 *d = ipAddr->addr[3];
3606 /// Retrieve the IPv4 address embedded inside OCDev address data structure
3607 int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
3609 if ( !ipAddr || !port )
3611 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
3612 return OC_STACK_INVALID_PARAM;
3615 *port = *((uint16_t*)&ipAddr->addr[4]);
3621 * Attempts to initialize every network interface that the CA Layer might have compiled in.
3623 * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork
3624 * return something other than @ref CA_STATUS_OK, then this function fails.
3627 * CA_STATUS_OK - Success
3628 * CA_NOT_SUPPORTED or CA_STATUS_FAILED - None of the transports successfully initialized.
3630 CAResult_t OCSelectNetwork()
3632 CAResult_t retResult = CA_STATUS_FAILED;
3633 CAResult_t caResult = CA_STATUS_OK;
3635 CAConnectivityType_t connTypes[] = {
3640 int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
3642 for(int i = 0; i<numConnTypes; i++)
3644 // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
3645 if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
3647 caResult = CASelectNetwork(connTypes[i]);
3648 if(caResult == CA_STATUS_OK)
3650 retResult = CA_STATUS_OK;
3655 if(retResult != CA_STATUS_OK)
3657 return caResult; // Returns error of appropriate transport that failed fatally.
3664 * Takes a @ref CAResult_t and converts it to a similar or equivalent @ref OCStackResult value.
3666 * @return @ref OCStackResult - The equivalent or similar result code to the in-param caResult.
3668 OCStackResult CAResultToOCResult(CAResult_t caResult)
3674 case CA_STATUS_INVALID_PARAM:
3675 return OC_STACK_INVALID_PARAM;
3676 case CA_ADAPTER_NOT_ENABLED:
3677 return OC_STACK_ADAPTER_NOT_ENABLED;
3678 case CA_SERVER_STARTED_ALREADY:
3680 case CA_SERVER_NOT_STARTED:
3681 return OC_STACK_ERROR;
3682 case CA_DESTINATION_NOT_REACHABLE:
3683 return OC_STACK_COMM_ERROR;
3684 case CA_SOCKET_OPERATION_FAILED:
3685 return OC_STACK_COMM_ERROR;
3686 case CA_SEND_FAILED:
3687 return OC_STACK_COMM_ERROR;
3688 case CA_RECEVIE_FAILED:
3689 return OC_STACK_COMM_ERROR;
3690 case CA_MEMORY_ALLOC_FAILED:
3691 return OC_STACK_NO_MEMORY;
3692 case CA_REQUEST_TIMEOUT:
3693 return OC_STACK_TIMEOUT;
3694 case CA_DESTINATION_DISCONNECTED:
3695 return OC_STACK_COMM_ERROR;
3696 case CA_STATUS_FAILED:
3697 return OC_STACK_ERROR;
3698 case CA_NOT_SUPPORTED:
3699 return OC_STACK_NOTIMPL;
3701 return OC_STACK_ERROR;