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
29 #include "ocstackinternal.h"
30 #include "ocresourcehandler.h"
31 #include "occlientcb.h"
32 #include "ocobserve.h"
37 #include "ocserverrequest.h"
38 #include "ocsecurityinternal.h"
42 #include "cainterface.h"
46 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
50 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
55 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
59 //-----------------------------------------------------------------------------
61 //-----------------------------------------------------------------------------
62 static OCStackState stackState = OC_STACK_UNINITIALIZED;
64 OCResource *headResource = NULL;
66 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
67 static PresenceResource presenceResource;
68 uint8_t PresenceTimeOutSize = 0;
69 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
73 OCDeviceEntityHandler defaultDeviceHandler;
74 OCStackResult getQueryFromUri(const char * uri, unsigned char** resourceType, char ** newURI);
76 //-----------------------------------------------------------------------------
78 //-----------------------------------------------------------------------------
79 #define TAG PCF("OCStack")
80 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
81 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
82 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
83 TAG, PCF(#arg " is NULL")); return (retVal); } }
84 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
87 //TODO: we should allow the server to define this
88 #define MAX_OBSERVE_AGE (0x2FFFFUL)
91 //-----------------------------------------------------------------------------
92 // Internal API function
93 //-----------------------------------------------------------------------------
95 // This internal function is called to update the stack with the status of
96 // observers and communication failures
98 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
100 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
103 OCStackResult result = OC_STACK_ERROR;
104 ResourceObserver * observer = NULL;
105 OCEntityHandlerRequest ehRequest = {0};
109 case OC_OBSERVER_NOT_INTERESTED:
110 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
111 observer = GetObserverUsingToken (token);
114 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
115 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
116 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
117 if(result != OC_STACK_OK)
121 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
123 //observer is not observing anymore
124 result = DeleteObserverUsingToken (token);
125 if(result == OC_STACK_OK)
127 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
131 result = OC_STACK_OK;
132 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
135 case OC_OBSERVER_STILL_INTERESTED:
136 //observer is still interested
137 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
138 notifications, reset the failedCount"));
139 observer = GetObserverUsingToken (token);
142 observer->forceHighQos = 0;
143 observer->failedCommCount = 0;
144 result = OC_STACK_OK;
148 result = OC_STACK_OBSERVER_NOT_FOUND;
151 case OC_OBSERVER_FAILED_COMM:
152 //observer is not reachable
153 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
154 observer = GetObserverUsingToken (token);
157 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
159 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
160 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
161 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
162 if(result != OC_STACK_OK)
164 return OC_STACK_ERROR;
166 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
167 //observer is unreachable
168 result = DeleteObserverUsingToken (token);
169 if(result == OC_STACK_OK)
171 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
175 result = OC_STACK_OK;
176 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
181 observer->failedCommCount++;
182 result = OC_STACK_CONTINUE;
184 observer->forceHighQos = 1;
185 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
189 OC_LOG(ERROR, TAG, PCF("Unknown status"));
190 result = OC_STACK_ERROR;
197 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
199 OCStackResult ret = OC_STACK_ERROR;
207 ret = OC_STACK_RESOURCE_CREATED;
210 ret = OC_STACK_RESOURCE_DELETED;
213 ret = OC_STACK_INVALID_QUERY;
216 ret = OC_STACK_INVALID_OPTION;
219 ret = OC_STACK_NO_RESOURCE;
227 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
229 OCStackResult ret = OC_STACK_OK;
234 *caConType = CA_ETHERNET;
237 *caConType = CA_WIFI;
246 //TODO-CA Add other connectivity types as they are enabled
247 *caConType = (CA_WIFI|CA_ETHERNET);
250 ret = OC_STACK_INVALID_PARAM;
256 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
258 OCStackResult ret = OC_STACK_OK;
263 *ocConType = OC_ETHERNET;
266 *ocConType = OC_WIFI;
275 ret = OC_STACK_INVALID_PARAM;
281 // update response.addr appropriately from endPoint.addressInfo
282 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
284 struct sockaddr_in sa;
285 OCStackResult ret = OC_STACK_INVALID_PARAM;
286 //TODO-CA Check validity of the endPoint pointer
287 inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
288 sa.sin_port = htons(endPoint->addressInfo.IP.port);
289 static OCDevAddr address;
290 memcpy((void*)&address.addr, &(sa), sizeof(sa));
293 response->addr = &address;
294 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
299 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
303 // The format of the payload is {"oc":[%u:%u:%s]}
304 // %u : sequence number,
306 // %s : Resource Type (Optional)
307 tok = strtok(payload, "[:]}");
308 payload[strlen(payload)] = ':';
309 tok = strtok(NULL, "[:]}");
310 payload[strlen((char *)payload)] = ':';
311 *seqNum = (uint32_t) atoi(tok);
312 tok = strtok(NULL, "[:]}");
313 *maxAge = (uint32_t) atoi(tok);
314 tok = strtok(NULL, "[:]}");
318 *resType = (char *)OCMalloc(strlen(tok));
323 payload[strlen((char *)payload)] = ':';
324 strcpy(*resType, tok);
325 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", *resType);
327 payload[strlen((char *)payload)] = ']';
330 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
331 const CAResponseInfo_t* responseInfo)
333 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
334 ClientCB * cbNode = NULL;
335 char *resourceTypeName = NULL;
336 OCClientResponse response;
337 OCStackResult result = OC_STACK_ERROR;
338 uint32_t lowerBound = 0;
339 uint32_t higherBound = 0;
342 char *fullUri = NULL;
343 char *ipAddress = NULL;
344 int presenceSubscribe = 0;
345 int multicastPresenceSubscribe = 0;
347 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
351 OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for fullUri"));
352 result = OC_STACK_NO_MEMORY;
356 ipAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
358 if(NULL == ipAddress)
360 OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for ipAddress"));
361 result = OC_STACK_NO_MEMORY;
365 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress,
366 strlen(endPoint->addressInfo.IP.ipAddress));
367 ipAddress[strlen(endPoint->addressInfo.IP.ipAddress)] = '\0';
369 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
372 cbNode = GetClientCB(NULL, NULL, fullUri);
376 presenceSubscribe = 1;
380 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
381 cbNode = GetClientCB(NULL, NULL, fullUri);
384 multicastPresenceSubscribe = 1;
388 if(!presenceSubscribe && !multicastPresenceSubscribe)
390 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
391 ------------ ignoring"));
395 // No payload to the application in case of presence
396 response.resJSONPayload = NULL;
397 response.result = OC_STACK_OK;
399 UpdateResponseAddr(&response, endPoint);
401 if(responseInfo->info.payload)
403 parsePresencePayload(responseInfo->info.payload,
404 &(response.sequenceNumber),
411 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
412 response.result = OC_STACK_PRESENCE_STOPPED;
415 OCFree(cbNode->presence->timeOut);
416 OCFree(cbNode->presence);
417 cbNode->presence = NULL;
420 else if(presenceSubscribe)
422 if(!cbNode->presence)
424 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
425 VERIFY_NON_NULL_V(cbNode->presence);
426 cbNode->presence->timeOut = NULL;
427 cbNode->presence->timeOut = (uint32_t *)
428 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
429 if(!(cbNode->presence->timeOut)){
430 OCFree(cbNode->presence);
431 result = OC_STACK_NO_MEMORY;
435 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
436 cbNode->presence->TTL = maxAge;
437 for(int index = 0; index < PresenceTimeOutSize; index++)
439 lowerBound = GetTime(((float)(PresenceTimeOut[index])
440 /(float)100)*(float)cbNode->presence->TTL);
441 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
442 /(float)100)*(float)cbNode->presence->TTL);
443 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
444 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
445 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
446 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
447 cbNode->presence->timeOut[index]);
449 cbNode->presence->TTLlevel = 0;
450 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
451 if(cbNode->sequenceNumber == response.sequenceNumber)
453 OC_LOG(INFO, TAG, PCF("===============No presence change"));
456 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
457 cbNode->sequenceNumber = response.sequenceNumber;
459 // Ensure that a filter is actually applied.
460 if(resourceTypeName && cbNode->filterResourceType)
462 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
470 // This is the multicast case
472 OCMulticastNode* mcNode = NULL;
473 mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
477 if(mcNode->nonce == response.sequenceNumber)
479 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
482 mcNode->nonce = response.sequenceNumber;
486 uint32_t uriLen = strlen((char*)fullUri);
487 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
490 memcpy(uri, fullUri, (uriLen + 1));
495 PCF("===============No Memory for URI to store in the presence node"));
496 result = OC_STACK_NO_MEMORY;
499 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, response.sequenceNumber);
500 if(result == OC_STACK_NO_MEMORY)
503 PCF("===============No Memory for Multicast Presence Node"));
504 result = OC_STACK_NO_MEMORY;
509 // Ensure that a filter is actually applied.
510 if(resourceTypeName && cbNode->filterResourceType)
512 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
519 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
521 if (cbResult == OC_STACK_DELETE_TRANSACTION)
523 FindAndDeleteClientCB(cbNode);
529 OCFree(resourceTypeName);
534 //This function will be called back by CA layer when a response is received
535 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
537 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
541 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
545 if(NULL == responseInfo)
547 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
551 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
553 HandlePresenceResponse(endPoint, responseInfo);
557 ClientCB *cbNode = GetClientCB(&(responseInfo->info.token), NULL, NULL);
561 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
562 OCClientResponse response;
564 OCStackResult result = UpdateResponseAddr(&response, endPoint);
565 if(result != OC_STACK_OK)
567 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
571 response.result = CAToOCStackResult(responseInfo->result);
572 response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
573 response.numRcvdVendorSpecificHeaderOptions = 0;
574 if(responseInfo->info.numOptions > 0)
577 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
578 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
580 memcpy (&(response.sequenceNumber),
581 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
582 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
587 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
590 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
592 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
596 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
598 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
599 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
602 result = cbNode->callBack(cbNode->context,
603 cbNode->handle, &response);
604 if (result == OC_STACK_DELETE_TRANSACTION)
606 FindAndDeleteClientCB(cbNode);
609 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
610 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
613 //This function will be called back by CA layer when a request is received
614 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
616 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
618 if(myStackMode == OC_CLIENT)
620 //TODO: should the client be responding to requests?
624 OCServerProtocolRequest serverRequest;
626 memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
627 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
629 char * newUri = (char *)endPoint->resourceUri;
630 unsigned char * query = NULL;
631 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
632 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
633 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
635 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
639 memcpy (&(serverRequest.query), query, strlen((char*)query));
641 //copy request payload
642 if (requestInfo->info.payload)
644 serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
645 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
646 strlen(requestInfo->info.payload));
647 serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
651 serverRequest.reqTotalSize = 1;
654 switch (requestInfo->method)
658 serverRequest.method = OC_REST_GET;
663 serverRequest.method = OC_REST_PUT;
668 serverRequest.method = OC_REST_POST;
673 serverRequest.method = OC_REST_DELETE;
678 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
683 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
684 OC_LOG_BUFFER(INFO, TAG, requestInfo->info.token, CA_MAX_TOKEN_LEN);
686 serverRequest.requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
688 if (!serverRequest.requestToken)
690 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
693 memset(serverRequest.requestToken, 0, CA_MAX_TOKEN_LEN + 1);
694 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
696 if (requestInfo->info.type == CA_MSG_CONFIRM)
698 serverRequest.qos = OC_HIGH_QOS;
700 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
702 serverRequest.qos = OC_LOW_QOS;
704 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
706 // TODO-CA: Need to handle this
708 else if (requestInfo->info.type == CA_MSG_RESET)
710 // TODO-CA: Need to handle this
712 // CA does not need the following 3 fields
713 serverRequest.coapID = 0;
714 serverRequest.delayedResNeeded = 0;
715 serverRequest.secured = endPoint->isSecured;
718 serverRequest.addressInfo = endPoint->addressInfo;
719 serverRequest.connectivityType = endPoint->connectivityType;
721 // copy vendor specific header options
722 // TODO-CA: CA is including non-vendor header options as well, like observe.
723 // Need to filter those out
724 GetObserveHeaderOption(&serverRequest.observationOption,
725 requestInfo->info.options, &(requestInfo->info.numOptions));
726 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
729 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
732 serverRequest.numRcvdVendorSpecificHeaderOptions = requestInfo->info.numOptions;
733 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
735 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
736 sizeof(CAHeaderOption_t)*requestInfo->info.numOptions);
739 if(HandleStackRequests (&serverRequest) != OC_STACK_OK)
741 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
744 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
749 //This function will be called back by occoap layer when a request is received
750 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
752 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
753 OCStackResult result = OC_STACK_ERROR;
754 ResourceHandling resHandling;
755 OCResource *resource;
757 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
760 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
762 result = AddServerRequest(&request, protocolRequest->coapID,
763 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
764 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
765 protocolRequest->observationOption, protocolRequest->qos,
766 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
767 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
768 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
769 protocolRequest->reqTotalSize,
770 &protocolRequest->addressInfo, protocolRequest->connectivityType);
772 result = AddServerRequest(&request, protocolRequest->coapID,
773 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
774 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
775 protocolRequest->observationOption, protocolRequest->qos,
776 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
777 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
778 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
779 protocolRequest->reqTotalSize);
781 if (OC_STACK_OK != result)
783 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
786 VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
788 if(!protocolRequest->reqMorePacket)
790 request->requestComplete = 1;
795 OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
798 if(request->requestComplete)
800 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
801 result = DetermineResourceHandling (request, &resHandling, &resource);
802 if (result == OC_STACK_OK)
804 result = ProcessRequest(resHandling, resource, request);
808 result = OC_STACK_ERROR;
813 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
814 result = OC_STACK_CONTINUE;
819 //This function will be called back by occoap layer when a response is received
820 OCStackResult HandleStackResponses(OCResponse * response)
822 OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
823 OCStackResult result = OC_STACK_OK;
824 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
825 uint8_t isObserveNotification = 0;
826 ClientCB * cbNode = NULL;
828 uint8_t isPresenceNotification = 0;
829 uint8_t isMulticastPresence = 0;
830 char * resourceTypeName = NULL;
831 uint32_t lowerBound = 0;
832 uint32_t higherBound = 0;
834 unsigned char * bufRes = response->bufRes;
835 #endif // WITH_PRESENCE
837 cbNode = response->cbNode;
840 cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
843 if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
845 isObserveNotification = 1;
846 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
849 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
850 response->clientResponse->sequenceNumber);
851 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
852 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
855 if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
856 isPresenceNotification = 1;
859 result = OC_STACK_INVALID_PARAM;
862 tok = strtok((char *)bufRes, "[:]}");
863 bufRes[strlen((char *)bufRes)] = ':';
864 tok = strtok(NULL, "[:]}");
865 bufRes[strlen((char *)bufRes)] = ':';
866 response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
867 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
868 tok = strtok(NULL, "[:]}");
869 response->maxAge = (uint32_t )atoi(tok);
870 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
871 tok = strtok(NULL, "[:]}");
874 resourceTypeName = (char *)OCMalloc(strlen(tok));
875 if(!resourceTypeName)
879 bufRes[strlen((char *)bufRes)] = ':';
880 strcpy(resourceTypeName, tok);
881 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
884 bufRes[strlen((char *)bufRes)] = ']';
887 // Check if the application subcribed for presence
890 cbNode = GetClientCB(NULL, NULL, response->fullUri);
893 // Check if application subscribed for multicast presence
896 snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
897 OC_MULTICAST_IP, response->rcvdUri);
898 cbNode = GetClientCB(NULL, NULL, response->fullUri);
901 isMulticastPresence = 1;
902 isPresenceNotification = 0;
906 if(cbNode && isPresenceNotification)
908 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
909 if(!cbNode->presence)
911 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
912 VERIFY_NON_NULL_V(cbNode->presence);
913 cbNode->presence->timeOut = NULL;
914 cbNode->presence->timeOut = (uint32_t *)
915 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
916 if(!(cbNode->presence->timeOut)){
917 OCFree(cbNode->presence);
918 result = OC_STACK_NO_MEMORY;
921 if(response->maxAge == 0)
923 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
924 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
927 OCFree(cbNode->presence->timeOut);
928 OCFree(cbNode->presence);
929 cbNode->presence = NULL;
934 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
935 cbNode->presence->TTL = response->maxAge;
936 for(int index = 0; index < PresenceTimeOutSize; index++)
938 lowerBound = GetTime(((float)(PresenceTimeOut[index])
939 /(float)100)*(float)cbNode->presence->TTL);
940 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
941 /(float)100)*(float)cbNode->presence->TTL);
942 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
943 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
944 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
945 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
946 cbNode->presence->timeOut[index]);
948 cbNode->presence->TTLlevel = 0;
949 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
950 if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
952 OC_LOG(INFO, TAG, PCF("===============No presence change"));
955 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
956 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
959 // Ensure that a filter is actually applied.
960 if(resourceTypeName && cbNode->filterResourceType)
962 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
968 else if(cbNode && isMulticastPresence)
970 // Check if the same nonce for a given host
971 OCMulticastNode* mcNode = NULL;
972 mcNode = GetMCPresenceNode(response->fullUri);
974 if(response->maxAge == 0)
976 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
977 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
980 OCFree(cbNode->presence->timeOut);
981 OCFree(cbNode->presence);
982 cbNode->presence = NULL;
985 else if(mcNode != NULL)
987 if(mcNode->nonce == response->clientResponse->sequenceNumber)
989 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
990 result = OC_STACK_NO_MEMORY;
993 mcNode->nonce = response->clientResponse->sequenceNumber;
997 uint32_t uriLen = strlen((char*)response->fullUri);
998 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
1001 memcpy(uri, response->fullUri, (uriLen + 1));
1006 PCF("===============No Memory for URI to store in the presence node"));
1007 result = OC_STACK_NO_MEMORY;
1010 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
1011 response->clientResponse->sequenceNumber);
1012 if(result == OC_STACK_NO_MEMORY)
1015 PCF("===============No Memory for Multicast Presence Node"));
1016 result = OC_STACK_NO_MEMORY;
1021 // Ensure that a filter is actually applied.
1022 if(resourceTypeName && cbNode->filterResourceType)
1024 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1031 else if(!cbNode && isPresenceNotification)
1033 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
1034 ------------ ignoring"));
1036 #endif // WITH_PRESENCE
1040 if(isObserveNotification)
1042 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
1043 //TODO: check the standard for methods to detect wrap around condition
1044 if(cbNode->method == OC_REST_OBSERVE &&
1045 (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
1046 (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
1047 response->clientResponse->sequenceNumber ==
1048 MAX_SEQUENCE_NUMBER)))
1050 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
1051 Ignoring Incoming:%d Against Current:%d.",
1052 response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
1055 if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
1056 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
1060 response->clientResponse->resJSONPayload = bufRes;
1062 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
1064 if (cbResult == OC_STACK_DELETE_TRANSACTION ||
1065 response->clientResponse->result == OC_STACK_COMM_ERROR ||
1066 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
1067 !isPresenceNotification && !isMulticastPresence))
1069 FindAndDeleteClientCB(cbNode);
1074 result = OC_STACK_ERROR;
1078 #ifdef WITH_PRESENCE
1079 OCFree(resourceTypeName);
1084 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
1087 unsigned char *itr, *coap;
1088 uint8_t dotCount = 0;
1092 /* search for scheme */
1094 if (!isdigit((unsigned char) *ipAddrStr))
1096 coap = (unsigned char *) OC_COAP_SCHEME;
1097 while (*coap && tolower(*itr) == *coap)
1105 while (*ipAddrStr) {
1106 if (isdigit((unsigned char) *ipAddrStr))
1108 ipAddr[index] *= 10;
1109 ipAddr[index] += *ipAddrStr - '0';
1111 else if ((unsigned char) *ipAddrStr == '.')
1123 if(*ipAddrStr == ':')
1127 if (isdigit((unsigned char) *ipAddrStr))
1130 *port += *ipAddrStr - '0';
1141 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
1152 //-----------------------------------------------------------------------------
1153 // Private internal function prototypes
1154 //-----------------------------------------------------------------------------
1156 static OCDoHandle GenerateInvocationHandle();
1157 static OCStackResult initResources();
1158 static void insertResource(OCResource *resource);
1159 static OCResource *findResource(OCResource *resource);
1160 static void insertResourceType(OCResource *resource,
1161 OCResourceType *resourceType);
1162 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1164 static void insertResourceInterface(OCResource *resource,
1165 OCResourceInterface *resourceInterface);
1166 static OCResourceInterface *findResourceInterfaceAtIndex(
1167 OCResourceHandle handle, uint8_t index);
1168 static void deleteResourceType(OCResourceType *resourceType);
1169 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1170 static void deleteResourceElements(OCResource *resource);
1171 static int deleteResource(OCResource *resource);
1172 static void deleteAllResources();
1173 static void incrementSequenceNumber(OCResource * resPtr);
1174 static OCStackResult verifyUriQueryLength(const char * inputUri,
1176 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1177 OCStackResult getResourceType(const char * query, unsigned char** resourceType);
1179 //-----------------------------------------------------------------------------
1181 //-----------------------------------------------------------------------------
1184 * Initialize the OC Stack. Must be called prior to starting the stack.
1187 * IP Address of host device
1189 * Port of host device
1191 * Host device is client, server, or client-server
1194 * OC_STACK_OK - no errors
1195 * OC_STACK_ERROR - stack init error
1197 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1199 OCStackResult result = OC_STACK_ERROR;
1200 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1204 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
1210 //It is ok to select network to CA_WIFI for now
1211 CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
1212 if(caResult == CA_STATUS_OK)
1214 OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
1215 CARegisterHandler(HandleCARequests, HandleCAResponses);
1217 OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
1218 stackState = OC_STACK_INITIALIZED;
1219 result = OC_STACK_OK;
1223 caResult = CAStartDiscoveryServer();
1224 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1227 caResult = CAStartListeningServer();
1228 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1230 case OC_CLIENT_SERVER:
1231 caResult = CAStartListeningServer();
1232 if(caResult == CA_STATUS_OK)
1234 caResult = CAStartDiscoveryServer();
1236 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1239 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1240 return OC_STACK_ERROR;
1245 if (caResult == CA_STATUS_OK)
1247 result = OC_STACK_OK;
1251 result = OC_STACK_ERROR;
1258 OC_LOG(INFO, TAG, PCF("Client mode"));
1261 OC_LOG(INFO, TAG, PCF("Server mode"));
1263 case OC_CLIENT_SERVER:
1264 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1267 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1268 return OC_STACK_ERROR;
1272 // Make call to OCCoAP layer
1273 result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
1277 defaultDeviceHandler = NULL;
1279 #if defined(CA_INT) && defined(__WITH_DTLS__)
1280 caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
1281 result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
1282 #endif //(CA_INT) && (__WITH_DTLS__)
1283 #ifdef WITH_PRESENCE
1284 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1285 #endif // WITH_PRESENCE
1287 if (result == OC_STACK_OK)
1289 stackState = OC_STACK_INITIALIZED;
1291 // Initialize resource
1292 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
1294 result = initResources();
1296 if(result != OC_STACK_OK)
1298 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1304 * Stop the OC stack. Use for a controlled shutdown.
1306 * OC_STACK_OK - no errors
1307 * OC_STACK_ERROR - stack not initialized
1309 OCStackResult OCStop()
1311 OCStackResult result = OC_STACK_ERROR;
1313 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1315 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1317 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1320 else if (stackState != OC_STACK_INITIALIZED)
1322 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1323 return OC_STACK_ERROR;
1326 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1328 #ifdef WITH_PRESENCE
1329 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1330 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1331 presenceResource.presenceTTL = 0;
1332 #endif // WITH_PRESENCE
1334 // Free memory dynamically allocated for resources
1335 deleteAllResources();
1339 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1340 result = OC_STACK_OK;
1342 result = OCStopCoAP();
1345 if (result == OC_STACK_OK)
1347 // Remove all observers
1348 DeleteObserverList();
1349 // Remove all the client callbacks
1350 DeleteClientCBList();
1351 stackState = OC_STACK_UNINITIALIZED;
1352 result = OC_STACK_OK;
1354 stackState = OC_STACK_INITIALIZED;
1355 result = OC_STACK_ERROR;
1358 // Deinit security blob
1359 DeinitOCSecurityInfo();
1361 if (result != OC_STACK_OK) {
1362 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1369 * Map OCQualityOfService to CAMessageType
1371 * @param OCQualityOfService - Input qos.
1373 * Returns CA message type for a given qos.
1375 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1380 return CA_MSG_CONFIRM;
1385 return CA_MSG_NONCONFIRM;
1390 * Verify the lengths of the URI and the query separately
1392 * @param inputUri - Input URI and query.
1393 * @param uriLen - The length of the initial URI with query.
1395 * Note: The '?' that appears after the URI is not considered as
1396 * a part of the query.
1398 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1402 query = strchr (inputUri, '?');
1406 if((query - inputUri) > MAX_URI_LENGTH)
1408 return OC_STACK_INVALID_URI;
1411 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1413 return OC_STACK_INVALID_QUERY;
1416 else if(uriLen > MAX_URI_LENGTH)
1418 return OC_STACK_INVALID_URI;
1424 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
1426 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
1427 * @param method - @ref OCMethod to perform on the resource
1428 * @param requiredUri - URI of the resource to interact with
1429 * @param referenceUri - URI of the reference resource
1430 * @param request - JSON encoded request
1431 * @param qos - quality of service
1432 * @param cbData - struct that contains asynchronous callback function that is invoked
1433 * by the stack when discovery or resource interaction is complete
1434 * @param options - The address of an array containing the vendor specific header
1435 * header options to be sent with the request
1436 * @param numOptions - Number of vendor specific header options to be included
1439 * OC_STACK_OK - no errors
1440 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1441 * OC_STACK_INVALID_METHOD - invalid resource method
1442 * OC_STACK_INVALID_URI - invalid required or reference URI
1444 * Note: IN case of CA, when using multicast, the required URI should not contain IP address.
1445 * Instead, it just contains the URI to the resource such as "/oc/core".
1448 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1449 const char *referenceUri, const char *request, uint8_t conType,
1450 OCQualityOfService qos, OCCallbackData *cbData,
1451 OCHeaderOption * options, uint8_t numOptions)
1453 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1454 const char *referenceUri, const char *request,
1455 OCQualityOfService qos, OCCallbackData *cbData,
1456 OCHeaderOption * options, uint8_t numOptions)
1459 OCStackResult result = OC_STACK_ERROR;
1460 ClientCB *clientCB = NULL;
1461 unsigned char * requestUri = NULL;
1462 unsigned char * resourceType = NULL;
1463 unsigned char * query = NULL;
1464 char * newUri = (char *)requiredUri;
1465 (void) referenceUri;
1467 CARemoteEndpoint_t* endpoint = NULL;
1468 CAResult_t caResult;
1469 CAToken_t token = NULL;
1470 CAInfo_t requestData;
1471 CARequestInfo_t requestInfo;
1472 CAGroupEndpoint_t grpEnd;
1474 // To track if memory is allocated for additional header options
1475 uint8_t hdrOptionMemAlloc = 0;
1480 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1482 // Validate input parameters
1483 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1484 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1486 TODO ("Need to form the final query by concatenating require and reference URI's");
1487 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1489 uint16_t uriLen = strlen(requiredUri);
1491 // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
1497 case OC_REST_DELETE:
1498 case OC_REST_OBSERVE:
1499 case OC_REST_OBSERVE_ALL:
1500 case OC_REST_CANCEL_OBSERVE:
1502 #ifdef WITH_PRESENCE
1503 case OC_REST_PRESENCE:
1507 result = OC_STACK_INVALID_METHOD;
1511 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1516 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1518 result = OC_STACK_INVALID_PARAM;
1522 #ifdef WITH_PRESENCE
1523 if(method == OC_REST_PRESENCE)
1525 result = getQueryFromUri(requiredUri, &query, &newUri);
1528 result = getResourceType((char *) query, &resourceType);
1531 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1535 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1540 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1542 if(result != OC_STACK_OK)
1547 #endif // WITH_PRESENCE
1549 requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1552 memcpy(requestUri, newUri, (uriLen + 1));
1556 result = OC_STACK_NO_MEMORY;
1560 *handle = GenerateInvocationHandle();
1563 result = OC_STACK_NO_MEMORY;
1568 memset(&requestData, 0, sizeof(CAInfo_t));
1569 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1570 memset(&grpEnd, 0, sizeof(CAGroupEndpoint_t));
1574 case OC_REST_OBSERVE:
1575 case OC_REST_OBSERVE_ALL:
1576 case OC_REST_CANCEL_OBSERVE:
1578 requestInfo.method = CA_GET;
1583 requestInfo.method = CA_PUT;
1588 requestInfo.method = CA_POST;
1591 case OC_REST_DELETE:
1593 requestInfo.method = CA_DELETE;
1596 #ifdef WITH_PRESENCE
1597 case OC_REST_PRESENCE:
1599 // Replacing method type with GET because "presence"
1600 // is a stack layer only implementation.
1601 requestInfo.method = CA_GET;
1606 result = OC_STACK_INVALID_METHOD;
1610 //High QoS is not supported
1611 if(qos == OC_HIGH_QOS)
1613 result = OC_STACK_INVALID_PARAM;
1619 caResult = CAGenerateToken(&token);
1620 if (caResult != CA_STATUS_OK)
1622 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1623 CADestroyToken(token);
1627 requestData.type = qualityOfServiceToMessageType(qos);
1628 requestData.token = token;
1629 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1631 result = CreateObserveHeaderOption (&(requestData.options), options,
1632 numOptions, OC_OBSERVE_REGISTER);
1633 if (result != OC_STACK_OK)
1637 hdrOptionMemAlloc = 1;
1638 requestData.numOptions = numOptions + 1;
1642 requestData.options = (CAHeaderOption_t*)options;
1643 requestData.numOptions = numOptions;
1645 requestData.payload = (char *)request;
1647 requestInfo.info = requestData;
1649 CAConnectivityType_t caConType;
1651 result = OCToCAConnectivityType(conType, &caConType);
1652 if (result != OC_STACK_OK)
1654 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1659 if(conType == OC_ALL)
1661 grpEnd.connectivityType = caConType;
1663 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1664 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1666 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1670 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1672 if (caResult != CA_STATUS_OK)
1674 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1678 caResult = CASendRequest(endpoint, &requestInfo);
1681 if (caResult != CA_STATUS_OK)
1683 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1687 if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
1688 requestUri, resourceType)) != OC_STACK_OK)
1690 result = OC_STACK_NO_MEMORY;
1696 // Generate token which will be used by OCStack to match responses received
1698 OCGenerateCoAPToken(&token);
1700 if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
1703 result = OC_STACK_NO_MEMORY;
1707 // Make call to OCCoAP layer
1708 result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
1712 if(newUri != requiredUri)
1716 if (result != OC_STACK_OK)
1718 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1719 FindAndDeleteClientCB(clientCB);
1722 CADestroyRemoteEndpoint(endpoint);
1723 OCFree(grpEnd.resourceUri);
1724 if (hdrOptionMemAlloc)
1726 OCFree(requestData.options);
1733 * Cancel a request associated with a specific @ref OCDoResource invocation.
1735 * @param handle - Used to identify a specific OCDoResource invocation.
1736 * @param qos - used to specify Quality of Service (read below for more info)
1737 * @param options- used to specify vendor specific header options when sending
1738 * explicit observe cancellation
1739 * @param numOptions- Number of header options to be included
1742 * OC_STACK_OK - No errors; Success
1743 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1745 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1749 * This ftn is implemented one of two ways in the case of observation:
1751 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1752 * Remove the callback associated on client side.
1753 * When the next notification comes in from server,
1754 * reply with RESET message to server.
1755 * Keep in mind that the server will react to RESET only
1756 * if the last notification was sent ans CON
1758 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1759 * and it is associated with an observe request
1760 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1761 * Send CON Observe request to server with
1762 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1763 * Remove the callback associated on client side.
1765 OCStackResult ret = OC_STACK_OK;
1767 CARemoteEndpoint_t* endpoint = NULL;
1768 CAResult_t caResult;
1769 CAInfo_t requestData;
1770 CARequestInfo_t requestInfo;
1771 // Track if memory is allocated for additional header options
1772 uint8_t hdrOptionMemAlloc = 0;
1776 return OC_STACK_INVALID_PARAM;
1779 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1781 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1784 switch (clientCB->method)
1786 case OC_REST_OBSERVE:
1787 case OC_REST_OBSERVE_ALL:
1789 //TODO-CA : Why CA_WIFI alone?
1790 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1792 if (caResult != CA_STATUS_OK)
1794 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1795 return OC_STACK_ERROR;
1798 memset(&requestData, 0, sizeof(CAInfo_t));
1799 requestData.type = qualityOfServiceToMessageType(qos);
1800 requestData.token = clientCB->token;
1801 if (CreateObserveHeaderOption (&(requestData.options),
1802 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1804 return OC_STACK_ERROR;
1806 hdrOptionMemAlloc = 1;
1807 requestData.numOptions = numOptions + 1;
1808 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1809 requestInfo.method = CA_GET;
1810 requestInfo.info = requestData;
1812 caResult = CASendRequest(endpoint, &requestInfo);
1813 if (caResult != CA_STATUS_OK)
1815 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1817 if(caResult == CA_STATUS_OK)
1822 if(qos == OC_HIGH_QOS)
1824 ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
1825 &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
1830 FindAndDeleteClientCB(clientCB);
1834 #ifdef WITH_PRESENCE
1835 case OC_REST_PRESENCE:
1836 FindAndDeleteClientCB(clientCB);
1840 return OC_STACK_INVALID_METHOD;
1844 CADestroyRemoteEndpoint(endpoint);
1845 if (hdrOptionMemAlloc)
1847 OCFree(requestData.options);
1854 #ifdef WITH_PRESENCE
1856 OCStackResult OCProcessPresence()
1858 OCStackResult result = OC_STACK_OK;
1859 uint8_t ipAddr[4] = { 0 };
1862 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1863 ClientCB* cbNode = NULL;
1865 OCClientResponse clientResponse;
1866 OCResponse * response = NULL;
1867 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1869 LL_FOREACH(cbList, cbNode) {
1870 if(OC_REST_PRESENCE == cbNode->method)
1872 if(cbNode->presence)
1874 uint32_t now = GetTime(0);
1875 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d",
1876 cbNode->presence->TTLlevel);
1877 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1880 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1885 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1886 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1887 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1890 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1892 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1893 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1895 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1897 result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
1898 (OCDevAddr *) &dst, 0, NULL);
1899 if(result != OC_STACK_OK)
1903 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1904 &cbNode->token, &clientResponse, NULL);
1905 if(result != OC_STACK_OK)
1910 // Increment the TTLLevel (going to a next state), so we don't keep
1911 // sending presence notification to client.
1912 cbNode->presence->TTLlevel++;
1913 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1914 cbNode->presence->TTLlevel);
1918 result = OC_STACK_INVALID_IP;
1922 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1923 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1925 FindAndDeleteClientCB(cbNode);
1929 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1931 CAResult_t caResult;
1932 CARemoteEndpoint_t* endpoint = NULL;
1933 CAInfo_t requestData;
1934 CARequestInfo_t requestInfo;
1936 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1938 //TODO-CA : Why CA_WIFI alone?
1939 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1942 if (caResult != CA_STATUS_OK)
1944 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1948 memset(&requestData, 0, sizeof(CAInfo_t));
1949 requestData.type = CA_MSG_NONCONFIRM;
1950 requestData.token = cbNode->token;
1952 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1953 requestInfo.method = CA_GET;
1954 requestInfo.info = requestData;
1956 caResult = CASendRequest(endpoint, &requestInfo);
1958 if (caResult != CA_STATUS_OK)
1960 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1964 cbNode->presence->TTLlevel++;
1965 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1966 cbNode->presence->TTLlevel);
1972 if (result != OC_STACK_OK)
1974 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1979 OCStackResult OCProcessPresence()
1981 OCStackResult result = OC_STACK_OK;
1982 uint8_t ipAddr[4] = { 0 };
1985 ClientCB* cbNode = NULL;
1987 OCClientResponse clientResponse;
1988 OCResponse * response = NULL;
1990 LL_FOREACH(cbList, cbNode) {
1991 if(OC_REST_PRESENCE == cbNode->method)
1993 if(cbNode->presence)
1995 uint32_t now = GetTime(0);
1996 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1997 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
2000 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
2005 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
2006 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
2007 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2010 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2012 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
2013 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
2015 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
2017 result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
2018 (OCDevAddr *) &dst, 0, NULL);
2019 if(result != OC_STACK_OK)
2023 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
2024 &cbNode->token, &clientResponse, NULL);
2025 if(result != OC_STACK_OK)
2030 // Increment the TTLLevel (going to a next state), so we don't keep
2031 // sending presence notification to client.
2032 cbNode->presence->TTLlevel++;
2033 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
2034 cbNode->presence->TTLlevel);
2038 result = OC_STACK_INVALID_IP;
2041 HandleStackResponses(response);
2043 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2045 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
2048 CAToken_t token = NULL;
2049 CAResult_t caResult = CAGenerateToken(&token);
2050 if (caResult != CA_STATUS_OK)
2052 CADestroyToken(token);
2057 OCGenerateCoAPToken(&token);
2059 result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
2060 &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
2062 if(result != OC_STACK_OK)
2067 cbNode->presence->TTLlevel++;
2068 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
2074 if (result != OC_STACK_OK)
2076 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
2081 #endif // WITH_PRESENCE
2084 * Called in main loop of OC client or server. Allows low-level processing of
2088 * OC_STACK_OK - no errors
2089 * OC_STACK_ERROR - stack process error
2091 OCStackResult OCProcess()
2093 #ifdef WITH_PRESENCE
2094 OCProcessPresence();
2097 CAHandleRequestResponse();
2105 #ifdef WITH_PRESENCE
2107 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
2108 * presence notifications to clients via multicast. Once this API has been called with a success,
2109 * clients may query for this server's presence and this server's stack will respond via multicast.
2111 * Server can call this function when it comes online for the first time, or when it comes back
2112 * online from offline mode, or when it re enters network.
2114 * @param ttl - Time To Live in seconds
2115 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
2118 * OC_STACK_OK - No errors; Success
2120 OCStackResult OCStartPresence(const uint32_t ttl)
2122 OCChangeResourceProperty(
2123 &(((OCResource *)presenceResource.handle)->resourceProperties),
2128 presenceResource.presenceTTL = ttl;
2131 if(OC_PRESENCE_UNINITIALIZED == presenceState)
2133 OCDevAddr multiCastAddr;
2134 presenceState = OC_PRESENCE_INITIALIZED;
2136 OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
2139 CAAddress_t addressInfo;
2140 strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
2141 addressInfo.IP.port = 5683;
2143 //TODO make sure there is no memory leak here since another copy
2144 //of token is being created inside AddObserver
2145 CAToken_t caToken = NULL;
2146 CAResult_t caResult = CAGenerateToken(&caToken);
2147 if (caResult != CA_STATUS_OK)
2149 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2150 CADestroyToken(caToken);
2151 return OC_STACK_ERROR;
2154 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
2155 &multiCastAddr, (OCResource *)presenceResource.handle, OC_LOW_QOS,
2156 &addressInfo, CA_WIFI);
2159 OCGenerateCoAPToken(&token);
2160 //add the presence observer
2161 AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
2162 (OCResource *)presenceResource.handle, OC_LOW_QOS);
2166 // Each time OCStartPresence is called
2167 // a different random 32-bit integer number is used
2168 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2170 return SendPresenceNotification(NULL);
2174 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
2175 * presence notifications to clients via multicast. Once this API has been called with a success,
2176 * this server's stack will not respond to clients querying for this server's presence.
2178 * Server can call this function when it is terminating, going offline, or when going
2179 * away from network.
2182 * OC_STACK_OK - No errors; Success
2184 OCStackResult OCStopPresence()
2186 OCStackResult result = OC_STACK_ERROR;
2187 //make resource inactive
2188 result = OCChangeResourceProperty(
2189 &(((OCResource *) presenceResource.handle)->resourceProperties),
2191 result = SendPresenceNotification(NULL);
2198 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
2200 defaultDeviceHandler = entityHandler;
2205 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2207 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
2209 if(myStackMode == OC_CLIENT)
2211 return OC_STACK_ERROR;
2214 return SaveDeviceInfo(deviceInfo);
2220 * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
2221 * @param resourceTypeName - name of resource type. Example: "core.led"
2222 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2223 * @param uri - URI of the resource. Example: "/a/led"
2224 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2225 * NULL for default entity handler
2226 * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
2229 * OC_STACK_OK - no errors
2230 * OC_STACK_ERROR - stack process error
2232 OCStackResult OCCreateResource(OCResourceHandle *handle,
2233 const char *resourceTypeName,
2234 const char *resourceInterfaceName,
2235 const char *uri, OCEntityHandler entityHandler,
2236 uint8_t resourceProperties) {
2238 OCResource *pointer = NULL;
2241 OCStackResult result = OC_STACK_ERROR;
2243 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
2245 if(myStackMode == OC_CLIENT)
2249 // Validate parameters
2250 if(!uri || (strlen(uri) == 0))
2252 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
2253 return OC_STACK_INVALID_URI;
2255 // Is it presented during resource discovery?
2256 if (!handle || !resourceTypeName) {
2257 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
2258 return OC_STACK_INVALID_PARAM;
2261 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
2262 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2265 // Make sure resourceProperties bitmask has allowed properties specified
2266 if (resourceProperties
2267 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
2268 OC_LOG(ERROR, TAG, PCF("Invalid property"));
2269 return OC_STACK_INVALID_PARAM;
2272 // If the headResource is NULL, then no resources have been created...
2273 pointer = headResource;
2275 // At least one resources is in the resource list, so we need to search for
2276 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2278 if (strcmp(uri, pointer->uri) == 0) {
2279 OC_LOG(ERROR, TAG, PCF("URI already in use"));
2280 return OC_STACK_INVALID_PARAM;
2282 pointer = pointer->next;
2285 // Create the pointer and insert it into the resource list
2286 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
2290 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2292 insertResource(pointer);
2295 size = strlen(uri) + 1;
2296 str = (char *) OCMalloc(size);
2300 strncpy(str, uri, size);
2303 // Set properties. Set OC_ACTIVE
2304 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2307 // Add the resourcetype to the resource
2308 result = BindResourceTypeToResource(pointer, resourceTypeName);
2309 if (result != OC_STACK_OK) {
2310 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2314 // Add the resourceinterface to the resource
2315 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2316 if (result != OC_STACK_OK) {
2317 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2321 // If an entity handler has been passed, attach it to the newly created
2322 // resource. Otherwise, set the default entity handler.
2325 pointer->entityHandler = entityHandler;
2329 pointer->entityHandler = defaultResourceEHandler;
2333 result = OC_STACK_OK;
2335 #ifdef WITH_PRESENCE
2336 if(presenceResource.handle)
2338 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2339 SendPresenceNotification(pointer->rsrcType);
2343 if (result != OC_STACK_OK)
2345 // Deep delete of resource and other dynamic elements that it contains
2346 deleteResource(pointer);
2355 * Create a resource. with host ip address for remote resource
2357 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2358 * Used to refer to resource
2359 * @param resourceTypeName - name of resource type. Example: "core.led"
2360 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2361 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2362 * @param uri - URI of the resource. Example: "/a/led"
2363 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2364 * NULL for default entity handler
2365 * @param resourceProperties - properties supported by resource.
2366 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2369 * OC_STACK_OK - no errors
2370 * OC_STACK_ERROR - stack process error
2373 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2374 const char *resourceTypeName,
2375 const char *resourceInterfaceName,
2378 OCEntityHandler entityHandler,
2379 uint8_t resourceProperties)
2383 OCStackResult result = OC_STACK_ERROR;
2385 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2386 uri, entityHandler, resourceProperties);
2388 if (result != OC_STACK_ERROR)
2391 size = strlen(host) + 1;
2392 str = (char *) OCMalloc(size);
2395 return OC_STACK_ERROR;
2397 strncpy(str, host, size);
2398 ((OCResource *) *handle)->host = str;
2405 * Add a resource to a collection resource.
2407 * @param collectionHandle - handle to the collection resource
2408 * @param resourceHandle - handle to resource to be added to the collection resource
2411 * OC_STACK_OK - no errors
2412 * OC_STACK_ERROR - stack process error
2413 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2415 OCStackResult OCBindResource(
2416 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2417 OCResource *resource;
2420 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2422 // Validate parameters
2423 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2424 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2425 // Container cannot contain itself
2426 if (collectionHandle == resourceHandle) {
2427 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2428 return OC_STACK_INVALID_PARAM;
2431 // Use the handle to find the resource in the resource linked list
2432 resource = findResource((OCResource *) collectionHandle);
2434 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2435 return OC_STACK_INVALID_PARAM;
2438 // Look for an open slot to add add the child resource.
2439 // If found, add it and return success
2440 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2441 if (!resource->rsrcResources[i]) {
2442 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2443 OC_LOG(INFO, TAG, PCF("resource bound"));
2448 #ifdef WITH_PRESENCE
2449 if(presenceResource.handle)
2451 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2452 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2456 // Unable to add resourceHandle, so return error
2457 return OC_STACK_ERROR;
2461 * Remove a resource from a collection resource.
2463 * @param collectionHandle - handle to the collection resource
2464 * @param resourceHandle - handle to resource to be added to the collection resource
2467 * OC_STACK_OK - no errors
2468 * OC_STACK_ERROR - stack process error
2469 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2471 OCStackResult OCUnBindResource(
2472 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2473 OCResource *resource;
2476 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2478 // Validate parameters
2479 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2480 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2481 // Container cannot contain itself
2482 if (collectionHandle == resourceHandle) {
2483 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2484 return OC_STACK_INVALID_PARAM;
2487 // Use the handle to find the resource in the resource linked list
2488 resource = findResource((OCResource *) collectionHandle);
2490 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2491 return OC_STACK_INVALID_PARAM;
2494 // Look for an open slot to add add the child resource.
2495 // If found, add it and return success
2496 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2497 if (resourceHandle == resource->rsrcResources[i]) {
2498 resource->rsrcResources[i] = (OCResource *) NULL;
2499 OC_LOG(INFO, TAG, PCF("resource unbound"));
2504 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2506 #ifdef WITH_PRESENCE
2507 if(presenceResource.handle)
2509 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2510 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2514 // Unable to add resourceHandle, so return error
2515 return OC_STACK_ERROR;
2518 OCStackResult BindResourceTypeToResource(OCResource* resource,
2519 const char *resourceTypeName)
2521 OCResourceType *pointer = NULL;
2524 OCStackResult result = OC_STACK_ERROR;
2526 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2528 // Validate parameters
2529 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2530 // TODO: Does resource attribute resentation really have to be maintained in stack?
2531 // Is it presented during resource discovery?
2533 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2535 // Create the resourcetype and insert it into the resource list
2536 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2541 // Set the resourceTypeName
2542 size = strlen(resourceTypeName) + 1;
2543 str = (char *) OCMalloc(size);
2547 strncpy(str, resourceTypeName, size);
2548 pointer->resourcetypename = str;
2550 insertResourceType(resource, pointer);
2551 result = OC_STACK_OK;
2553 exit: if (result != OC_STACK_OK) {
2561 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2562 const char *resourceInterfaceName)
2564 OCResourceInterface *pointer = NULL;
2567 OCStackResult result = OC_STACK_ERROR;
2569 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2571 // Validate parameters
2572 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2574 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2576 // Create the resourceinterface and insert it into the resource list
2577 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2582 // Set the resourceinterface name
2583 size = strlen(resourceInterfaceName) + 1;
2584 str = (char *) OCMalloc(size);
2588 strncpy(str, resourceInterfaceName, size);
2589 pointer->name = str;
2591 // Bind the resourceinterface to the resource
2592 insertResourceInterface(resource, pointer);
2594 result = OC_STACK_OK;
2596 exit: if (result != OC_STACK_OK) {
2605 * Bind a resourcetype to a resource.
2607 * @param handle - handle to the resource
2608 * @param resourceTypeName - name of resource type. Example: "core.led"
2611 * OC_STACK_OK - no errors
2612 * OC_STACK_ERROR - stack process error
2614 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2615 const char *resourceTypeName) {
2617 OCStackResult result = OC_STACK_ERROR;
2618 OCResource *resource;
2620 // Make sure resource exists
2621 resource = findResource((OCResource *) handle);
2623 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2624 return OC_STACK_ERROR;
2627 // call internal function
2628 result = BindResourceTypeToResource(resource, resourceTypeName);
2630 #ifdef WITH_PRESENCE
2631 if(presenceResource.handle)
2633 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2634 SendPresenceNotification(resource->rsrcType);
2642 * Bind a resourceinterface to a resource.
2644 * @param handle - handle to the resource
2645 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2648 * OC_STACK_OK - no errors
2649 * OC_STACK_ERROR - stack process error
2652 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2653 const char *resourceInterfaceName) {
2655 OCStackResult result = OC_STACK_ERROR;
2656 OCResource *resource;
2658 // Make sure resource exists
2659 resource = findResource((OCResource *) handle);
2661 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2662 return OC_STACK_ERROR;
2665 // call internal function
2666 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2668 #ifdef WITH_PRESENCE
2669 if(presenceResource.handle)
2671 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2672 SendPresenceNotification(resource->rsrcType);
2680 * Get the number of resources that have been created in the stack.
2682 * @param numResources - pointer to count variable
2685 * OC_STACK_OK - no errors
2686 * OC_STACK_ERROR - stack process error
2689 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2690 OCResource *pointer = headResource;
2692 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2693 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2696 *numResources = *numResources + 1;
2697 pointer = pointer->next;
2703 * Get a resource handle by index.
2705 * @param index - index of resource, 0 to Count - 1
2708 * Resource handle - if found
2709 * NULL - if not found
2711 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2712 OCResource *pointer = headResource;
2715 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2717 // Iterate through the list
2718 while ((i < index) && pointer) {
2720 pointer = pointer->next;
2722 return (OCResourceHandle) pointer;
2726 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2729 * @param handle - handle of resource to be deleted
2732 * OC_STACK_OK - no errors
2733 * OC_STACK_ERROR - stack process error
2734 * OC_STACK_NO_RESOURCE - resource not found
2735 * OC_STACK_INVALID_PARAM - invalid param
2737 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2738 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2741 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2742 return OC_STACK_INVALID_PARAM;
2745 OCResource *resource = findResource((OCResource *) handle);
2746 if (resource == NULL) {
2747 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2748 return OC_STACK_NO_RESOURCE;
2751 if (deleteResource((OCResource *) handle) == 0) {
2752 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2753 return OC_STACK_ERROR;
2760 * Get the URI of the resource specified by handle.
2762 * @param handle - handle of resource
2764 * URI string - if resource found
2765 * NULL - resource not found
2767 const char *OCGetResourceUri(OCResourceHandle handle) {
2768 OCResource *resource;
2769 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2771 resource = findResource((OCResource *) handle);
2773 return resource->uri;
2775 return (const char *) NULL;
2779 * Get the properties of the resource specified by handle.
2780 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2781 * for the resource by the stack.
2783 * @param handle - handle of resource
2785 * property bitmap - if resource found
2786 * NULL - resource not found
2788 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2789 OCResource *resource;
2790 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2792 resource = findResource((OCResource *) handle);
2794 return resource->resourceProperties;
2800 * Get the number of resource types of the resource.
2802 * @param handle - handle of resource
2803 * @param numResourceTypes - pointer to count variable
2806 * OC_STACK_OK - no errors
2807 * OC_STACK_ERROR - stack process error
2809 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2810 uint8_t *numResourceTypes) {
2811 OCResource *resource;
2812 OCResourceType *pointer;
2814 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2815 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2816 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2818 *numResourceTypes = 0;
2820 resource = findResource((OCResource *) handle);
2822 pointer = resource->rsrcType;
2824 *numResourceTypes = *numResourceTypes + 1;
2825 pointer = pointer->next;
2832 * Get name of resource type of the resource.
2834 * @param handle - handle of resource
2835 * @param index - index of resource, 0 to Count - 1
2838 * resource type name - if resource found
2839 * NULL - resource not found
2841 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2842 OCResourceType *resourceType;
2844 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2846 resourceType = findResourceTypeAtIndex(handle, index);
2848 return resourceType->resourcetypename;
2850 return (const char *) NULL;
2856 * Get the number of resource interfaces of the resource.
2858 * @param handle - handle of resource
2859 * @param numResources - pointer to count variable
2862 * OC_STACK_OK - no errors
2863 * OC_STACK_ERROR - stack process error
2865 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2866 uint8_t *numResourceInterfaces) {
2867 OCResourceInterface *pointer;
2868 OCResource *resource;
2870 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2872 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2873 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2875 *numResourceInterfaces = 0;
2876 resource = findResource((OCResource *) handle);
2878 pointer = resource->rsrcInterface;
2880 *numResourceInterfaces = *numResourceInterfaces + 1;
2881 pointer = pointer->next;
2888 * Get name of resource interface of the resource.
2890 * @param handle - handle of resource
2891 * @param index - index of resource, 0 to Count - 1
2894 * resource interface name - if resource found
2895 * NULL - resource not found
2897 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2898 OCResourceInterface *resourceInterface;
2900 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2902 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2903 if (resourceInterface) {
2904 return resourceInterface->name;
2906 return (const char *) NULL;
2910 * Get resource handle from the collection resource by index.
2912 * @param collectionHandle - handle of collection resource
2913 * @param index - index of contained resource, 0 to Count - 1
2916 * handle to resource - if resource found
2917 * NULL - resource not found
2919 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2921 OCResource *resource;
2923 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2925 if (index >= MAX_CONTAINED_RESOURCES) {
2929 resource = findResource((OCResource *) collectionHandle);
2934 return resource->rsrcResources[index];
2938 * Bind an entity handler to the resource.
2940 * @param handle - handle to the resource that the contained resource is to be bound
2941 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2943 * OC_STACK_OK - no errors
2944 * OC_STACK_ERROR - stack process error
2946 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2947 OCEntityHandler entityHandler) {
2948 OCResource *resource;
2950 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2952 // Validate parameters
2953 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2954 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2956 // Use the handle to find the resource in the resource linked list
2957 resource = findResource((OCResource *)handle);
2959 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2960 return OC_STACK_ERROR;
2964 resource->entityHandler = entityHandler;
2966 #ifdef WITH_PRESENCE
2967 if(presenceResource.handle)
2969 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2970 SendPresenceNotification(resource->rsrcType);
2978 * Get the entity handler for a resource.
2980 * @param handle - handle of resource
2983 * entity handler - if resource found
2984 * NULL - resource not found
2986 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2987 OCResource *resource;
2989 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2991 // Use the handle to find the resource in the resource linked list
2992 resource = findResource((OCResource *)handle);
2994 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2999 return resource->entityHandler;
3002 void incrementSequenceNumber(OCResource * resPtr)
3004 // Increment the sequence number
3005 resPtr->sequenceNum += 1;
3006 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3008 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3014 * Notify Presence subscribers that a resource has been modified
3016 * @param resourceType - Handle to the resourceType linked list of resource
3017 * that was modified.
3018 * @param qos - Quality Of Service
3021 #ifdef WITH_PRESENCE
3022 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
3024 OCResource *resPtr = NULL;
3025 OCStackResult result;
3026 OCMethod method = OC_REST_PRESENCE;
3027 uint32_t maxAge = 0;
3028 resPtr = findResource((OCResource *) presenceResource.handle);
3031 return OC_STACK_NO_RESOURCE;
3033 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3035 maxAge = presenceResource.presenceTTL;
3042 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
3046 #endif // WITH_PRESENCE
3048 * Notify observers that an observed value has changed.
3050 * @param handle - handle of resource
3053 * OC_STACK_OK - no errors
3054 * OC_STACK_NO_RESOURCE - invalid resource handle
3055 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
3057 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
3059 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
3061 OCResource *resPtr = NULL;
3062 OCStackResult result;
3063 OCMethod method = OC_REST_NOMETHOD;
3064 uint32_t maxAge = 0;
3066 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
3067 #ifdef WITH_PRESENCE
3068 if(handle == presenceResource.handle)
3072 #endif // WITH_PRESENCE
3073 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3075 // Verify that the resource exists
3076 resPtr = findResource ((OCResource *) handle);
3079 return OC_STACK_NO_RESOURCE;
3083 //only increment in the case of regular observing (not presence)
3084 incrementSequenceNumber(resPtr);
3085 method = OC_REST_OBSERVE;
3086 maxAge = MAX_OBSERVE_AGE;
3087 #ifdef WITH_PRESENCE
3088 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
3090 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3097 OCNotifyListOfObservers (OCResourceHandle handle,
3098 OCObservationId *obsIdList,
3099 uint8_t numberOfIds,
3100 unsigned char *notificationJSONPayload,
3101 OCQualityOfService qos)
3103 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
3105 OCResource *resPtr = NULL;
3106 //TODO: we should allow the server to define this
3107 uint32_t maxAge = MAX_OBSERVE_AGE;
3109 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3110 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3111 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
3113 // Verify that the resource exists
3114 resPtr = findResource ((OCResource *) handle);
3115 if (NULL == resPtr || myStackMode == OC_CLIENT)
3117 return OC_STACK_NO_RESOURCE;
3121 incrementSequenceNumber(resPtr);
3123 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3124 notificationJSONPayload, maxAge, qos));
3128 * Send a response to a request.
3129 * The response can be a regular, slow, or block (i.e. a response that
3130 * is too large to be sent in a single PDU and must span multiple transmissions)
3132 * @param response - pointer to structure that contains response parameters
3135 * OC_STACK_OK - No errors; Success
3136 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
3137 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
3138 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
3139 * persistent response buffer is necessary
3141 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3143 OCStackResult result = OC_STACK_ERROR;
3144 OCServerRequest *serverRequest = NULL;
3146 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
3148 // Validate input parameters
3149 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3150 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3152 // TODO: Placeholder for creating a response entry when implementing
3153 // block transfer feature
3155 // If a response payload is present, check if block transfer is required
3156 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
3157 (const char *)ehResponse->payload, ehResponse->payloadSize))
3159 OC_LOG(INFO, TAG, PCF("Block transfer required"));
3161 // Persistent response buffer is needed for block transfer
3162 if (!ehResponse->persistentBufferFlag)
3164 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
3165 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
3167 // TODO: Placeholder for block transfer handling
3168 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
3169 // when implementing the block transfer feature
3174 // Get pointer to request info
3175 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3178 result = serverRequest->ehResponseHandler(ehResponse);
3185 * Cancel a response. Applies to a block response
3187 * @param responseHandle - response handle set by stack in OCServerResponse after
3188 * OCDoResponse is called
3191 * OC_STACK_OK - No errors; Success
3192 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
3194 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
3196 OCStackResult result = OC_STACK_NOTIMPL;
3198 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
3200 // TODO: validate response handle
3205 //-----------------------------------------------------------------------------
3206 // Private internal function definitions
3207 //-----------------------------------------------------------------------------
3209 * Generate handle of OCDoResource invocation for callback management.
3211 static OCDoHandle GenerateInvocationHandle()
3213 OCDoHandle handle = NULL;
3214 // Generate token here, it will be deleted when the transaction is deleted
3215 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
3218 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
3223 #ifdef WITH_PRESENCE
3224 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3225 OCResourceProperty resourceProperties, uint8_t enable)
3227 if (resourceProperties
3228 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
3229 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3230 return OC_STACK_INVALID_PARAM;
3234 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3238 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3245 * Initialize resource data structures, variables, etc.
3247 OCStackResult initResources() {
3248 OCStackResult result = OC_STACK_OK;
3249 // Init application resource vars
3250 headResource = NULL;
3251 // Init Virtual Resources
3252 #ifdef WITH_PRESENCE
3253 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3254 //presenceResource.token = OCGenerateCoAPToken();
3255 result = OCCreateResource(&presenceResource.handle,
3256 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3261 //make resource inactive
3262 result = OCChangeResourceProperty(
3263 &(((OCResource *) presenceResource.handle)->resourceProperties),
3270 * Add a resource to the end of the linked list of resources.
3272 * @param resource - resource to be added
3274 void insertResource(OCResource *resource) {
3275 OCResource *pointer;
3277 if (!headResource) {
3278 headResource = resource;
3280 pointer = headResource;
3282 while (pointer->next) {
3283 pointer = pointer->next;
3285 pointer->next = resource;
3287 resource->next = NULL;
3291 * Find a resource in the linked list of resources.
3293 * @param resource - resource to be found
3295 * NULL - resource not found
3296 * pointer to resource - pointer to resource that was found in the linked list
3298 OCResource *findResource(OCResource *resource) {
3299 OCResource *pointer = headResource;
3302 if (pointer == resource) {
3305 pointer = pointer->next;
3310 void deleteAllResources()
3312 OCResource *pointer = headResource;
3317 temp = pointer->next;
3318 #ifdef WITH_PRESENCE
3319 if(pointer != (OCResource *) presenceResource.handle)
3321 #endif // WITH_PRESENCE
3322 deleteResource(pointer);
3323 #ifdef WITH_PRESENCE
3325 #endif // WITH_PRESENCE
3329 #ifdef WITH_PRESENCE
3330 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3331 // presence notification attributed to their deletion to be processed.
3332 deleteResource((OCResource *) presenceResource.handle);
3333 #endif // WITH_PRESENCE
3337 * Delete the resource from the linked list.
3339 * @param resource - resource to be deleted
3344 int deleteResource(OCResource *resource) {
3345 OCResource *prev = NULL;
3348 temp = headResource;
3350 if (temp == resource) {
3351 // Invalidate all Resource Properties.
3352 resource->resourceProperties = (OCResourceProperty) 0;
3353 #ifdef WITH_PRESENCE
3354 if(resource != (OCResource *) presenceResource.handle)
3356 #endif // WITH_PRESENCE
3357 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3358 #ifdef WITH_PRESENCE
3361 if(presenceResource.handle)
3363 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3364 if(resource != (OCResource *) presenceResource.handle)
3366 SendPresenceNotification(resource->rsrcType);
3370 SendPresenceNotification(NULL);
3375 if (temp == headResource) {
3376 headResource = temp->next;
3378 prev->next = temp->next;
3381 deleteResourceElements(temp);
3394 * Delete all of the dynamically allocated elements that were created for the resource.
3396 * @param resource - specified resource
3398 void deleteResourceElements(OCResource *resource) {
3404 OCFree(resource->uri);
3406 // Delete resourcetype linked list
3407 deleteResourceType(resource->rsrcType);
3409 // Delete resourceinterface linked list
3410 deleteResourceInterface(resource->rsrcInterface);
3414 * Delete all of the dynamically allocated elements that were created for the resource type.
3416 * @param resourceType - specified resource type
3418 void deleteResourceType(OCResourceType *resourceType) {
3419 OCResourceType *pointer = resourceType;
3420 OCResourceType *next;
3423 next = pointer->next;
3424 OCFree(pointer->resourcetypename);
3431 * Delete all of the dynamically allocated elements that were created for the resource interface.
3433 * @param resourceInterface - specified resource interface
3435 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
3436 OCResourceInterface *pointer = resourceInterface;
3437 OCResourceInterface *next;
3440 next = pointer->next;
3441 OCFree(pointer->name);
3448 * Insert a resource type into a resource's resource type linked list.
3450 * @param resource - resource where resource type is to be inserted
3451 * @param resourceType - resource type to be inserted
3453 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
3454 OCResourceType *pointer;
3456 if (resource && !resource->rsrcType) {
3457 resource->rsrcType = resourceType;
3461 pointer = resource->rsrcType;
3465 pointer = resourceType;
3467 while (pointer->next) {
3468 pointer = pointer->next;
3470 pointer->next = resourceType;
3472 resourceType->next = NULL;
3476 * Get a resource type at the specified index within a resource.
3478 * @param handle - handle of resource
3479 * @param index - index of resource type
3482 * resourcetype - if found
3485 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
3486 OCResource *resource;
3487 OCResourceType *pointer;
3490 // Find the specified resource
3491 resource = findResource((OCResource *) handle);
3496 // Make sure a resource has a resourcetype
3497 if (!resource->rsrcType) {
3501 // Iterate through the list
3502 pointer = resource->rsrcType;
3504 while ((i < index) && pointer) {
3506 pointer = pointer->next;
3512 * Finds a resource type in an OCResourceType link-list.
3514 * @param resourceTypeList - the link-list to be searched through
3515 * @param resourceTypeName - the key to search for
3518 * resourceType that matches the key (ie. resourceTypeName)
3519 * NULL - either an invalid parameter or this function was unable to find the key.
3521 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3523 if(resourceTypeList && resourceTypeName)
3525 OCResourceType * rtPointer = resourceTypeList;
3526 while(resourceTypeName && rtPointer)
3528 if(rtPointer->resourcetypename &&
3529 strcmp(resourceTypeName, (const char *)
3530 (rtPointer->resourcetypename)) == 0)
3534 rtPointer = rtPointer->next;
3541 * Insert a resource interface into a resource's resource interface linked list.
3543 * @param resource - resource where resource interface is to be inserted
3544 * @param resourceInterface - resource interface to be inserted
3546 void insertResourceInterface(OCResource *resource,
3547 OCResourceInterface *resourceInterface) {
3548 OCResourceInterface *pointer;
3550 if (!resource->rsrcInterface) {
3551 resource->rsrcInterface = resourceInterface;
3553 pointer = resource->rsrcInterface;
3554 while (pointer->next) {
3555 pointer = pointer->next;
3557 pointer->next = resourceInterface;
3559 resourceInterface->next = NULL;
3563 * Get a resource interface at the specified index within a resource.
3565 * @param handle - handle of resource
3566 * @param index - index of resource interface
3569 * resourceinterface - if found
3572 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3574 OCResource *resource;
3575 OCResourceInterface *pointer;
3578 // Find the specified resource
3579 resource = findResource((OCResource *) handle);
3584 // Make sure a resource has a resourceinterface
3585 if (!resource->rsrcInterface) {
3589 // Iterate through the list
3590 pointer = resource->rsrcInterface;
3592 while ((i < index) && pointer) {
3594 pointer = pointer->next;
3600 * Determine if a request/response must be sent in a block transfer because it is too large to be
3601 * sent in a single PDU. This function can be used for either a request or a response
3603 * @param request - NULL or pointer to request
3604 * @param response - NULL or pointer to response
3605 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3606 * the length of the request/response
3609 * 0 - packet transfer NOT required (i.e. normal request/response)
3610 * 1 - packet transfer required (i.e. block transfer needed)
3612 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3616 // Determine if we are checking a request or a response
3619 // If size is greater than 0, use it for the request size value, otherwise
3620 // assume request is null terminated and use strlen for size value
3621 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3628 // If size is greater than 0, use it for the response size value, otherwise
3629 // assume response is null terminated and use strlen for size value
3630 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3639 * Retrieves a resource type based upon a query ontains only just one
3640 * resource attribute (and that has to be of type "rt").
3642 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3643 * before passing in.
3645 * @param query - The quert part of the URI
3646 * @param resourceType - The resource type to be populated; pass by reference.
3649 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3650 * OC_STACK_OK - Success
3652 OCStackResult getResourceType(const char * query, unsigned char** resourceType)
3656 return OC_STACK_INVALID_PARAM;
3659 OCStackResult result = OC_STACK_ERROR;
3661 if(strncmp(query, "rt=", 3) == 0)
3663 *resourceType = (unsigned char *) OCMalloc(strlen(query)-3);
3666 result = OC_STACK_NO_MEMORY;
3669 strcpy((char *)*resourceType, ((const char *)&query[3]));
3670 result = OC_STACK_OK;
3676 OCStackResult getQueryFromUri(const char * uri, unsigned char** query, char ** newURI)
3680 return OC_STACK_INVALID_URI;
3682 if(!query || !newURI)
3684 return OC_STACK_INVALID_PARAM;
3686 char * leftToken = NULL;
3687 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3692 strcpy(tempURI, uri);
3694 leftToken = strtok_r((char *)tempURI, "?", &strTokPtr);
3696 //TODO-CA: This could be simplified. Clean up required.
3697 while(leftToken != NULL)
3699 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3701 *query = (unsigned char *) OCMalloc(strlen(leftToken));
3707 strcpy((char *)*query, ((const char *)&leftToken[0]));
3710 leftToken = strtok_r(NULL, "?", &strTokPtr);
3718 return OC_STACK_NO_MEMORY;
3721 const ServerID OCGetServerInstanceID(void)
3723 static bool generated = false;
3724 static ServerID sid;
3731 sid = OCGetRandom();
3736 const char* OCGetServerInstanceIDString(void)
3738 // max printed length of a base 10
3739 // uint32 is 10 characters, so 11 includes null.
3740 // This will change as the representation gets switched
3742 static char buffer[11];
3743 int n = sprintf(buffer, "%u", OCGetServerInstanceID());