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"
41 #include "cainterface.h"
45 //-----------------------------------------------------------------------------
47 //-----------------------------------------------------------------------------
49 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
54 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
58 //-----------------------------------------------------------------------------
60 //-----------------------------------------------------------------------------
61 static OCStackState stackState = OC_STACK_UNINITIALIZED;
63 OCResource *headResource = NULL;
65 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
66 static PresenceResource presenceResource;
67 uint8_t PresenceTimeOutSize = 0;
68 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
72 OCDeviceEntityHandler defaultDeviceHandler;
73 OCStackResult getQueryFromUri(const char * uri, unsigned char** resourceType, char ** newURI);
75 //-----------------------------------------------------------------------------
77 //-----------------------------------------------------------------------------
78 #define TAG PCF("OCStack")
79 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
80 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
81 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
82 TAG, PCF(#arg " is NULL")); return (retVal); } }
83 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
86 //TODO: we should allow the server to define this
87 #define MAX_OBSERVE_AGE (0x2FFFFUL)
89 //-----------------------------------------------------------------------------
91 //-----------------------------------------------------------------------------
92 extern void DeinitOCSecurityInfo();
94 //-----------------------------------------------------------------------------
95 // Internal API function
96 //-----------------------------------------------------------------------------
98 // This internal function is called to update the stack with the status of
99 // observers and communication failures
101 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
103 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
106 OCStackResult result = OC_STACK_ERROR;
107 ResourceObserver * observer = NULL;
108 OCEntityHandlerRequest ehRequest = {0};
112 case OC_OBSERVER_NOT_INTERESTED:
113 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
114 observer = GetObserverUsingToken (token);
117 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
118 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
119 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
120 if(result != OC_STACK_OK)
124 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
126 //observer is not observing anymore
127 result = DeleteObserverUsingToken (token);
128 if(result == OC_STACK_OK)
130 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
134 result = OC_STACK_OK;
135 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
138 case OC_OBSERVER_STILL_INTERESTED:
139 //observer is still interested
140 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
141 notifications, reset the failedCount"));
142 observer = GetObserverUsingToken (token);
145 observer->forceHighQos = 0;
146 observer->failedCommCount = 0;
147 result = OC_STACK_OK;
151 result = OC_STACK_OBSERVER_NOT_FOUND;
154 case OC_OBSERVER_FAILED_COMM:
155 //observer is not reachable
156 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
157 observer = GetObserverUsingToken (token);
160 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
162 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
163 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
164 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
165 if(result != OC_STACK_OK)
167 return OC_STACK_ERROR;
169 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
170 //observer is unreachable
171 result = DeleteObserverUsingToken (token);
172 if(result == OC_STACK_OK)
174 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
178 result = OC_STACK_OK;
179 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
184 observer->failedCommCount++;
185 result = OC_STACK_CONTINUE;
187 observer->forceHighQos = 1;
188 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
192 OC_LOG(ERROR, TAG, PCF("Unknown status"));
193 result = OC_STACK_ERROR;
200 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
202 OCStackResult ret = OC_STACK_ERROR;
210 ret = OC_STACK_RESOURCE_CREATED;
213 ret = OC_STACK_RESOURCE_DELETED;
216 ret = OC_STACK_INVALID_QUERY;
219 ret = OC_STACK_INVALID_OPTION;
222 ret = OC_STACK_NO_RESOURCE;
230 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
232 OCStackResult ret = OC_STACK_OK;
237 *caConType = CA_ETHERNET;
240 *caConType = CA_WIFI;
249 //TODO-CA Add other connectivity types as they are enabled
250 *caConType = (CA_WIFI|CA_ETHERNET);
253 ret = OC_STACK_INVALID_PARAM;
259 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
261 OCStackResult ret = OC_STACK_OK;
266 *ocConType = OC_ETHERNET;
269 *ocConType = OC_WIFI;
278 ret = OC_STACK_INVALID_PARAM;
284 // update response.addr appropriately from endPoint.addressInfo
285 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
287 struct sockaddr_in sa;
288 OCStackResult ret = OC_STACK_INVALID_PARAM;
289 //TODO-CA Check validity of the endPoint pointer
290 inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
291 sa.sin_port = htons(endPoint->addressInfo.IP.port);
292 static OCDevAddr address;
293 memcpy((void*)&address.addr, &(sa), sizeof(sa));
296 response->addr = &address;
297 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
302 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
306 // The format of the payload is {"oc":[%u:%u:%s]}
307 // %u : sequence number,
309 // %s : Resource Type (Optional)
310 tok = strtok(payload, "[:]}");
311 payload[strlen(payload)] = ':';
312 tok = strtok(NULL, "[:]}");
313 payload[strlen((char *)payload)] = ':';
314 *seqNum = (uint32_t) atoi(tok);
315 tok = strtok(NULL, "[:]}");
316 *maxAge = (uint32_t) atoi(tok);
317 tok = strtok(NULL, "[:]}");
321 *resType = (char *)OCMalloc(strlen(tok));
326 payload[strlen((char *)payload)] = ':';
327 strcpy(*resType, tok);
328 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", *resType);
330 payload[strlen((char *)payload)] = ']';
333 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
334 const CAResponseInfo_t* responseInfo)
336 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
337 ClientCB * cbNode = NULL;
338 char *resourceTypeName = NULL;
339 OCClientResponse response;
340 OCStackResult result = OC_STACK_ERROR;
341 uint32_t lowerBound = 0;
342 uint32_t higherBound = 0;
345 char *fullUri = NULL;
346 char *ipAddress = NULL;
347 int presenceSubscribe = 0;
348 int multicastPresenceSubscribe = 0;
350 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
354 OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for fullUri"));
355 result = OC_STACK_NO_MEMORY;
359 ipAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
361 if(NULL == ipAddress)
363 OC_LOG(INFO, TAG, PCF("Memory could not be abllocated for ipAddress"));
364 result = OC_STACK_NO_MEMORY;
368 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress,
369 strlen(endPoint->addressInfo.IP.ipAddress));
370 ipAddress[strlen(endPoint->addressInfo.IP.ipAddress)] = '\0';
372 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
375 cbNode = GetClientCB(NULL, NULL, fullUri);
379 presenceSubscribe = 1;
383 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
384 cbNode = GetClientCB(NULL, NULL, fullUri);
387 multicastPresenceSubscribe = 1;
391 if(!presenceSubscribe && !multicastPresenceSubscribe)
393 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
394 ------------ ignoring"));
398 // No payload to the application in case of presence
399 response.resJSONPayload = NULL;
400 response.result = OC_STACK_OK;
402 UpdateResponseAddr(&response, endPoint);
404 if(responseInfo->info.payload)
406 parsePresencePayload(responseInfo->info.payload,
407 &(response.sequenceNumber),
414 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
415 response.result = OC_STACK_PRESENCE_STOPPED;
418 OCFree(cbNode->presence->timeOut);
419 OCFree(cbNode->presence);
420 cbNode->presence = NULL;
423 else if(presenceSubscribe)
425 if(!cbNode->presence)
427 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
428 VERIFY_NON_NULL_V(cbNode->presence);
429 cbNode->presence->timeOut = NULL;
430 cbNode->presence->timeOut = (uint32_t *)
431 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
432 if(!(cbNode->presence->timeOut)){
433 OCFree(cbNode->presence);
434 result = OC_STACK_NO_MEMORY;
438 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
439 cbNode->presence->TTL = maxAge;
440 for(int index = 0; index < PresenceTimeOutSize; index++)
442 lowerBound = GetTime(((float)(PresenceTimeOut[index])
443 /(float)100)*(float)cbNode->presence->TTL);
444 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
445 /(float)100)*(float)cbNode->presence->TTL);
446 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
447 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
448 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
449 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
450 cbNode->presence->timeOut[index]);
452 cbNode->presence->TTLlevel = 0;
453 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
454 if(cbNode->sequenceNumber == response.sequenceNumber)
456 OC_LOG(INFO, TAG, PCF("===============No presence change"));
459 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
460 cbNode->sequenceNumber = response.sequenceNumber;
462 // Ensure that a filter is actually applied.
463 if(resourceTypeName && cbNode->filterResourceType)
465 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
473 // This is the multicast case
475 OCMulticastNode* mcNode = NULL;
476 mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
480 if(mcNode->nonce == response.sequenceNumber)
482 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
485 mcNode->nonce = response.sequenceNumber;
489 uint32_t uriLen = strlen((char*)fullUri);
490 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
493 memcpy(uri, fullUri, (uriLen + 1));
498 PCF("===============No Memory for URI to store in the presence node"));
499 result = OC_STACK_NO_MEMORY;
502 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, response.sequenceNumber);
503 if(result == OC_STACK_NO_MEMORY)
506 PCF("===============No Memory for Multicast Presence Node"));
507 result = OC_STACK_NO_MEMORY;
512 // Ensure that a filter is actually applied.
513 if(resourceTypeName && cbNode->filterResourceType)
515 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
522 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
524 if (cbResult == OC_STACK_DELETE_TRANSACTION)
526 FindAndDeleteClientCB(cbNode);
532 OCFree(resourceTypeName);
537 //This function will be called back by CA layer when a response is received
538 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
540 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
544 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
548 if(NULL == responseInfo)
550 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
554 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
556 HandlePresenceResponse(endPoint, responseInfo);
560 ClientCB *cbNode = GetClientCB(&(responseInfo->info.token), NULL, NULL);
564 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
565 OCClientResponse response;
567 OCStackResult result = UpdateResponseAddr(&response, endPoint);
568 if(result != OC_STACK_OK)
570 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
574 response.result = CAToOCStackResult(responseInfo->result);
575 response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
576 response.numRcvdVendorSpecificHeaderOptions = 0;
577 if(responseInfo->info.numOptions > 0)
580 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
581 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
583 memcpy (&(response.sequenceNumber),
584 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
585 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
590 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
593 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
595 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
599 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
601 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
602 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
605 result = cbNode->callBack(cbNode->context,
606 cbNode->handle, &response);
607 if (result == OC_STACK_DELETE_TRANSACTION)
609 FindAndDeleteClientCB(cbNode);
612 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
613 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
616 //This function will be called back by CA layer when a request is received
617 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
619 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
621 if(myStackMode == OC_CLIENT)
623 //TODO: should the client be responding to requests?
627 OCServerProtocolRequest serverRequest;
629 memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
630 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
632 char * newUri = (char *)endPoint->resourceUri;
633 unsigned char * query = NULL;
634 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
635 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
636 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
638 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
642 memcpy (&(serverRequest.query), query, strlen((char*)query));
644 //copy request payload
645 if (requestInfo->info.payload)
647 serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
648 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
649 strlen(requestInfo->info.payload));
650 serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
654 serverRequest.reqTotalSize = 1;
657 switch (requestInfo->method)
661 serverRequest.method = OC_REST_GET;
666 serverRequest.method = OC_REST_PUT;
671 serverRequest.method = OC_REST_POST;
676 serverRequest.method = OC_REST_DELETE;
681 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
686 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
687 OC_LOG_BUFFER(INFO, TAG, requestInfo->info.token, CA_MAX_TOKEN_LEN);
689 serverRequest.requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
691 if (!serverRequest.requestToken)
693 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
696 memset(serverRequest.requestToken, 0, CA_MAX_TOKEN_LEN + 1);
697 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
699 if (requestInfo->info.type == CA_MSG_CONFIRM)
701 serverRequest.qos = OC_HIGH_QOS;
703 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
705 serverRequest.qos = OC_LOW_QOS;
707 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
709 // TODO-CA: Need to handle this
711 else if (requestInfo->info.type == CA_MSG_RESET)
713 // TODO-CA: Need to handle this
715 // CA does not need the following 3 fields
716 serverRequest.coapID = 0;
717 serverRequest.delayedResNeeded = 0;
718 serverRequest.secured = endPoint->isSecured;
721 serverRequest.addressInfo = endPoint->addressInfo;
722 serverRequest.connectivityType = endPoint->connectivityType;
724 // copy vendor specific header options
725 // TODO-CA: CA is including non-vendor header options as well, like observe.
726 // Need to filter those out
727 GetObserveHeaderOption(&serverRequest.observationOption,
728 requestInfo->info.options, &(requestInfo->info.numOptions));
729 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
732 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
735 serverRequest.numRcvdVendorSpecificHeaderOptions = requestInfo->info.numOptions;
736 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
738 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
739 sizeof(CAHeaderOption_t)*requestInfo->info.numOptions);
742 if(HandleStackRequests (&serverRequest) != OC_STACK_OK)
744 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
747 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
752 //This function will be called back by occoap layer when a request is received
753 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
755 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
756 OCStackResult result = OC_STACK_ERROR;
757 ResourceHandling resHandling;
758 OCResource *resource;
760 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
763 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
765 result = AddServerRequest(&request, protocolRequest->coapID,
766 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
767 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
768 protocolRequest->observationOption, protocolRequest->qos,
769 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
770 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
771 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
772 protocolRequest->reqTotalSize,
773 &protocolRequest->addressInfo, protocolRequest->connectivityType);
775 result = AddServerRequest(&request, protocolRequest->coapID,
776 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
777 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
778 protocolRequest->observationOption, protocolRequest->qos,
779 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
780 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
781 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
782 protocolRequest->reqTotalSize);
784 if (OC_STACK_OK != result)
786 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
789 VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
791 if(!protocolRequest->reqMorePacket)
793 request->requestComplete = 1;
798 OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
801 if(request->requestComplete)
803 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
804 result = DetermineResourceHandling (request, &resHandling, &resource);
805 if (result == OC_STACK_OK)
807 result = ProcessRequest(resHandling, resource, request);
811 result = OC_STACK_ERROR;
816 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
817 result = OC_STACK_CONTINUE;
822 //This function will be called back by occoap layer when a response is received
823 OCStackResult HandleStackResponses(OCResponse * response)
825 OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
826 OCStackResult result = OC_STACK_OK;
827 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
828 uint8_t isObserveNotification = 0;
829 ClientCB * cbNode = NULL;
831 uint8_t isPresenceNotification = 0;
832 uint8_t isMulticastPresence = 0;
833 char * resourceTypeName = NULL;
834 uint32_t lowerBound = 0;
835 uint32_t higherBound = 0;
837 unsigned char * bufRes = response->bufRes;
838 #endif // WITH_PRESENCE
840 cbNode = response->cbNode;
843 cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
846 if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
848 isObserveNotification = 1;
849 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
852 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
853 response->clientResponse->sequenceNumber);
854 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
855 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
858 if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
859 isPresenceNotification = 1;
862 result = OC_STACK_INVALID_PARAM;
865 tok = strtok((char *)bufRes, "[:]}");
866 bufRes[strlen((char *)bufRes)] = ':';
867 tok = strtok(NULL, "[:]}");
868 bufRes[strlen((char *)bufRes)] = ':';
869 response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
870 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
871 tok = strtok(NULL, "[:]}");
872 response->maxAge = (uint32_t )atoi(tok);
873 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
874 tok = strtok(NULL, "[:]}");
877 resourceTypeName = (char *)OCMalloc(strlen(tok));
878 if(!resourceTypeName)
882 bufRes[strlen((char *)bufRes)] = ':';
883 strcpy(resourceTypeName, tok);
884 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
887 bufRes[strlen((char *)bufRes)] = ']';
890 // Check if the application subcribed for presence
893 cbNode = GetClientCB(NULL, NULL, response->fullUri);
896 // Check if application subscribed for multicast presence
899 snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
900 OC_MULTICAST_IP, response->rcvdUri);
901 cbNode = GetClientCB(NULL, NULL, response->fullUri);
904 isMulticastPresence = 1;
905 isPresenceNotification = 0;
909 if(cbNode && isPresenceNotification)
911 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
912 if(!cbNode->presence)
914 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
915 VERIFY_NON_NULL_V(cbNode->presence);
916 cbNode->presence->timeOut = NULL;
917 cbNode->presence->timeOut = (uint32_t *)
918 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
919 if(!(cbNode->presence->timeOut)){
920 OCFree(cbNode->presence);
921 result = OC_STACK_NO_MEMORY;
924 if(response->maxAge == 0)
926 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
927 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
930 OCFree(cbNode->presence->timeOut);
931 OCFree(cbNode->presence);
932 cbNode->presence = NULL;
937 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
938 cbNode->presence->TTL = response->maxAge;
939 for(int index = 0; index < PresenceTimeOutSize; index++)
941 lowerBound = GetTime(((float)(PresenceTimeOut[index])
942 /(float)100)*(float)cbNode->presence->TTL);
943 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
944 /(float)100)*(float)cbNode->presence->TTL);
945 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
946 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
947 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
948 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
949 cbNode->presence->timeOut[index]);
951 cbNode->presence->TTLlevel = 0;
952 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
953 if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
955 OC_LOG(INFO, TAG, PCF("===============No presence change"));
958 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
959 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
962 // Ensure that a filter is actually applied.
963 if(resourceTypeName && cbNode->filterResourceType)
965 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
971 else if(cbNode && isMulticastPresence)
973 // Check if the same nonce for a given host
974 OCMulticastNode* mcNode = NULL;
975 mcNode = GetMCPresenceNode(response->fullUri);
977 if(response->maxAge == 0)
979 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
980 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
983 OCFree(cbNode->presence->timeOut);
984 OCFree(cbNode->presence);
985 cbNode->presence = NULL;
988 else if(mcNode != NULL)
990 if(mcNode->nonce == response->clientResponse->sequenceNumber)
992 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
993 result = OC_STACK_NO_MEMORY;
996 mcNode->nonce = response->clientResponse->sequenceNumber;
1000 uint32_t uriLen = strlen((char*)response->fullUri);
1001 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
1004 memcpy(uri, response->fullUri, (uriLen + 1));
1009 PCF("===============No Memory for URI to store in the presence node"));
1010 result = OC_STACK_NO_MEMORY;
1013 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
1014 response->clientResponse->sequenceNumber);
1015 if(result == OC_STACK_NO_MEMORY)
1018 PCF("===============No Memory for Multicast Presence Node"));
1019 result = OC_STACK_NO_MEMORY;
1024 // Ensure that a filter is actually applied.
1025 if(resourceTypeName && cbNode->filterResourceType)
1027 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1034 else if(!cbNode && isPresenceNotification)
1036 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
1037 ------------ ignoring"));
1039 #endif // WITH_PRESENCE
1043 if(isObserveNotification)
1045 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
1046 //TODO: check the standard for methods to detect wrap around condition
1047 if(cbNode->method == OC_REST_OBSERVE &&
1048 (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
1049 (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
1050 response->clientResponse->sequenceNumber ==
1051 MAX_SEQUENCE_NUMBER)))
1053 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
1054 Ignoring Incoming:%d Against Current:%d.",
1055 response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
1058 if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
1059 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
1063 response->clientResponse->resJSONPayload = bufRes;
1065 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
1067 if (cbResult == OC_STACK_DELETE_TRANSACTION ||
1068 response->clientResponse->result == OC_STACK_COMM_ERROR ||
1069 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
1070 !isPresenceNotification && !isMulticastPresence))
1072 FindAndDeleteClientCB(cbNode);
1077 result = OC_STACK_ERROR;
1081 #ifdef WITH_PRESENCE
1082 OCFree(resourceTypeName);
1087 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
1090 unsigned char *itr, *coap;
1091 uint8_t dotCount = 0;
1095 /* search for scheme */
1097 if (!isdigit((unsigned char) *ipAddrStr))
1099 coap = (unsigned char *) OC_COAP_SCHEME;
1100 while (*coap && tolower(*itr) == *coap)
1108 while (*ipAddrStr) {
1109 if (isdigit((unsigned char) *ipAddrStr))
1111 ipAddr[index] *= 10;
1112 ipAddr[index] += *ipAddrStr - '0';
1114 else if ((unsigned char) *ipAddrStr == '.')
1126 if(*ipAddrStr == ':')
1130 if (isdigit((unsigned char) *ipAddrStr))
1133 *port += *ipAddrStr - '0';
1144 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
1155 //-----------------------------------------------------------------------------
1156 // Private internal function prototypes
1157 //-----------------------------------------------------------------------------
1159 static OCDoHandle GenerateInvocationHandle();
1160 static OCStackResult initResources();
1161 static void insertResource(OCResource *resource);
1162 static OCResource *findResource(OCResource *resource);
1163 static void insertResourceType(OCResource *resource,
1164 OCResourceType *resourceType);
1165 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1167 static void insertResourceInterface(OCResource *resource,
1168 OCResourceInterface *resourceInterface);
1169 static OCResourceInterface *findResourceInterfaceAtIndex(
1170 OCResourceHandle handle, uint8_t index);
1171 static void deleteResourceType(OCResourceType *resourceType);
1172 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1173 static void deleteResourceElements(OCResource *resource);
1174 static int deleteResource(OCResource *resource);
1175 static void deleteAllResources();
1176 static void incrementSequenceNumber(OCResource * resPtr);
1177 static OCStackResult verifyUriQueryLength(const char * inputUri,
1179 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1180 OCStackResult getResourceType(const char * query, unsigned char** resourceType);
1182 //-----------------------------------------------------------------------------
1184 //-----------------------------------------------------------------------------
1187 * Initialize the OC Stack. Must be called prior to starting the stack.
1190 * IP Address of host device
1192 * Port of host device
1194 * Host device is client, server, or client-server
1197 * OC_STACK_OK - no errors
1198 * OC_STACK_ERROR - stack init error
1200 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1202 OCStackResult result = OC_STACK_ERROR;
1203 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1207 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
1213 //It is ok to select network to CA_WIFI for now
1214 CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
1215 if(caResult == CA_STATUS_OK)
1217 OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
1218 CARegisterHandler(HandleCARequests, HandleCAResponses);
1220 OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
1221 stackState = OC_STACK_INITIALIZED;
1222 result = OC_STACK_OK;
1226 caResult = CAStartDiscoveryServer();
1227 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1230 caResult = CAStartListeningServer();
1231 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1233 case OC_CLIENT_SERVER:
1234 caResult = CAStartListeningServer();
1235 if(caResult == CA_STATUS_OK)
1237 caResult = CAStartDiscoveryServer();
1239 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1242 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1243 return OC_STACK_ERROR;
1248 if (caResult == CA_STATUS_OK)
1250 result = OC_STACK_OK;
1254 result = OC_STACK_ERROR;
1261 OC_LOG(INFO, TAG, PCF("Client mode"));
1264 OC_LOG(INFO, TAG, PCF("Server mode"));
1266 case OC_CLIENT_SERVER:
1267 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1270 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1271 return OC_STACK_ERROR;
1275 // Make call to OCCoAP layer
1276 result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
1280 defaultDeviceHandler = NULL;
1282 #ifdef WITH_PRESENCE
1283 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1284 #endif // WITH_PRESENCE
1286 if (result == OC_STACK_OK)
1288 stackState = OC_STACK_INITIALIZED;
1290 // Initialize resource
1291 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
1293 result = initResources();
1295 if(result != OC_STACK_OK)
1297 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1303 * Stop the OC stack. Use for a controlled shutdown.
1305 * OC_STACK_OK - no errors
1306 * OC_STACK_ERROR - stack not initialized
1308 OCStackResult OCStop()
1310 OCStackResult result = OC_STACK_ERROR;
1312 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1314 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1316 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1319 else if (stackState != OC_STACK_INITIALIZED)
1321 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1322 return OC_STACK_ERROR;
1325 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1327 #ifdef WITH_PRESENCE
1328 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1329 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1330 presenceResource.presenceTTL = 0;
1331 #endif // WITH_PRESENCE
1333 // Free memory dynamically allocated for resources
1334 deleteAllResources();
1338 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1339 result = OC_STACK_OK;
1341 result = OCStopCoAP();
1344 if (result == OC_STACK_OK)
1346 // Remove all observers
1347 DeleteObserverList();
1348 // Remove all the client callbacks
1349 DeleteClientCBList();
1350 stackState = OC_STACK_UNINITIALIZED;
1351 result = OC_STACK_OK;
1353 stackState = OC_STACK_INITIALIZED;
1354 result = OC_STACK_ERROR;
1357 // Deinit security blob
1358 DeinitOCSecurityInfo();
1360 if (result != OC_STACK_OK) {
1361 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1368 * Map OCQualityOfService to CAMessageType
1370 * @param OCQualityOfService - Input qos.
1372 * Returns CA message type for a given qos.
1374 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1379 return CA_MSG_CONFIRM;
1384 return CA_MSG_NONCONFIRM;
1389 * Verify the lengths of the URI and the query separately
1391 * @param inputUri - Input URI and query.
1392 * @param uriLen - The length of the initial URI with query.
1394 * Note: The '?' that appears after the URI is not considered as
1395 * a part of the query.
1397 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1401 query = strchr (inputUri, '?');
1405 if((query - inputUri) > MAX_URI_LENGTH)
1407 return OC_STACK_INVALID_URI;
1410 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1412 return OC_STACK_INVALID_QUERY;
1415 else if(uriLen > MAX_URI_LENGTH)
1417 return OC_STACK_INVALID_URI;
1423 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
1425 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
1426 * @param method - @ref OCMethod to perform on the resource
1427 * @param requiredUri - URI of the resource to interact with
1428 * @param referenceUri - URI of the reference resource
1429 * @param request - JSON encoded request
1430 * @param qos - quality of service
1431 * @param cbData - struct that contains asynchronous callback function that is invoked
1432 * by the stack when discovery or resource interaction is complete
1433 * @param options - The address of an array containing the vendor specific header
1434 * header options to be sent with the request
1435 * @param numOptions - Number of vendor specific header options to be included
1438 * OC_STACK_OK - no errors
1439 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1440 * OC_STACK_INVALID_METHOD - invalid resource method
1441 * OC_STACK_INVALID_URI - invalid required or reference URI
1443 * Note: IN case of CA, when using multicast, the required URI should not contain IP address.
1444 * Instead, it just contains the URI to the resource such as "/oc/core".
1447 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1448 const char *referenceUri, const char *request, uint8_t conType,
1449 OCQualityOfService qos, OCCallbackData *cbData,
1450 OCHeaderOption * options, uint8_t numOptions)
1452 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1453 const char *referenceUri, const char *request,
1454 OCQualityOfService qos, OCCallbackData *cbData,
1455 OCHeaderOption * options, uint8_t numOptions)
1458 OCStackResult result = OC_STACK_ERROR;
1459 ClientCB *clientCB = NULL;
1460 unsigned char * requestUri = NULL;
1461 unsigned char * resourceType = NULL;
1462 unsigned char * query = NULL;
1463 char * newUri = (char *)requiredUri;
1464 (void) referenceUri;
1466 CARemoteEndpoint_t* endpoint = NULL;
1467 CAResult_t caResult;
1468 CAToken_t token = NULL;
1469 CAInfo_t requestData;
1470 CARequestInfo_t requestInfo;
1471 CAGroupEndpoint_t grpEnd;
1473 // To track if memory is allocated for additional header options
1474 uint8_t hdrOptionMemAlloc = 0;
1479 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1481 // Validate input parameters
1482 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1483 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1485 TODO ("Need to form the final query by concatenating require and reference URI's");
1486 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1488 uint16_t uriLen = strlen(requiredUri);
1490 // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
1496 case OC_REST_DELETE:
1497 case OC_REST_OBSERVE:
1498 case OC_REST_OBSERVE_ALL:
1499 case OC_REST_CANCEL_OBSERVE:
1501 #ifdef WITH_PRESENCE
1502 case OC_REST_PRESENCE:
1506 result = OC_STACK_INVALID_METHOD;
1510 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1515 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1517 result = OC_STACK_INVALID_PARAM;
1521 #ifdef WITH_PRESENCE
1522 if(method == OC_REST_PRESENCE)
1524 result = getQueryFromUri(requiredUri, &query, &newUri);
1527 result = getResourceType((char *) query, &resourceType);
1530 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1534 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1539 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1541 if(result != OC_STACK_OK)
1546 #endif // WITH_PRESENCE
1548 requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1551 memcpy(requestUri, newUri, (uriLen + 1));
1555 result = OC_STACK_NO_MEMORY;
1559 *handle = GenerateInvocationHandle();
1562 result = OC_STACK_NO_MEMORY;
1567 memset(&requestData, 0, sizeof(CAInfo_t));
1568 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1569 memset(&grpEnd, 0, sizeof(CAGroupEndpoint_t));
1573 case OC_REST_OBSERVE:
1574 case OC_REST_OBSERVE_ALL:
1575 case OC_REST_CANCEL_OBSERVE:
1577 requestInfo.method = CA_GET;
1582 requestInfo.method = CA_PUT;
1587 requestInfo.method = CA_POST;
1590 case OC_REST_DELETE:
1592 requestInfo.method = CA_DELETE;
1595 #ifdef WITH_PRESENCE
1596 case OC_REST_PRESENCE:
1598 // Replacing method type with GET because "presence"
1599 // is a stack layer only implementation.
1600 requestInfo.method = CA_GET;
1605 result = OC_STACK_INVALID_METHOD;
1609 //High QoS is not supported
1610 if(qos == OC_HIGH_QOS)
1612 result = OC_STACK_INVALID_PARAM;
1618 caResult = CAGenerateToken(&token);
1619 if (caResult != CA_STATUS_OK)
1621 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1622 CADestroyToken(token);
1626 requestData.type = qualityOfServiceToMessageType(qos);
1627 requestData.token = token;
1628 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1630 result = CreateObserveHeaderOption (&(requestData.options), options,
1631 numOptions, OC_OBSERVE_REGISTER);
1632 if (result != OC_STACK_OK)
1636 hdrOptionMemAlloc = 1;
1637 requestData.numOptions = numOptions + 1;
1641 requestData.options = (CAHeaderOption_t*)options;
1642 requestData.numOptions = numOptions;
1644 requestData.payload = (char *)request;
1646 requestInfo.info = requestData;
1648 CAConnectivityType_t caConType;
1650 result = OCToCAConnectivityType(conType, &caConType);
1651 if (result != OC_STACK_OK)
1653 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1658 if(conType == OC_ALL)
1660 grpEnd.connectivityType = caConType;
1662 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1663 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1665 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1669 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1671 if (caResult != CA_STATUS_OK)
1673 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1677 caResult = CASendRequest(endpoint, &requestInfo);
1680 if (caResult != CA_STATUS_OK)
1682 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1686 if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
1687 requestUri, resourceType)) != OC_STACK_OK)
1689 result = OC_STACK_NO_MEMORY;
1695 // Generate token which will be used by OCStack to match responses received
1697 OCGenerateCoAPToken(&token);
1699 if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
1702 result = OC_STACK_NO_MEMORY;
1706 // Make call to OCCoAP layer
1707 result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
1711 if(newUri != requiredUri)
1715 if (result != OC_STACK_OK)
1717 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1718 FindAndDeleteClientCB(clientCB);
1721 CADestroyRemoteEndpoint(endpoint);
1722 OCFree(grpEnd.resourceUri);
1723 if (hdrOptionMemAlloc)
1725 OCFree(requestData.options);
1732 * Cancel a request associated with a specific @ref OCDoResource invocation.
1734 * @param handle - Used to identify a specific OCDoResource invocation.
1735 * @param qos - used to specify Quality of Service (read below for more info)
1736 * @param options- used to specify vendor specific header options when sending
1737 * explicit observe cancellation
1738 * @param numOptions- Number of header options to be included
1741 * OC_STACK_OK - No errors; Success
1742 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1744 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1748 * This ftn is implemented one of two ways in the case of observation:
1750 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1751 * Remove the callback associated on client side.
1752 * When the next notification comes in from server,
1753 * reply with RESET message to server.
1754 * Keep in mind that the server will react to RESET only
1755 * if the last notification was sent ans CON
1757 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1758 * and it is associated with an observe request
1759 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1760 * Send CON Observe request to server with
1761 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1762 * Remove the callback associated on client side.
1764 OCStackResult ret = OC_STACK_OK;
1766 CARemoteEndpoint_t* endpoint = NULL;
1767 CAResult_t caResult;
1768 CAInfo_t requestData;
1769 CARequestInfo_t requestInfo;
1770 // Track if memory is allocated for additional header options
1771 uint8_t hdrOptionMemAlloc = 0;
1775 return OC_STACK_INVALID_PARAM;
1778 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1780 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1783 switch (clientCB->method)
1785 case OC_REST_OBSERVE:
1786 case OC_REST_OBSERVE_ALL:
1788 //TODO-CA : Why CA_WIFI alone?
1789 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1791 if (caResult != CA_STATUS_OK)
1793 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1794 return OC_STACK_ERROR;
1797 memset(&requestData, 0, sizeof(CAInfo_t));
1798 requestData.type = qualityOfServiceToMessageType(qos);
1799 requestData.token = clientCB->token;
1800 if (CreateObserveHeaderOption (&(requestData.options),
1801 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1803 return OC_STACK_ERROR;
1805 hdrOptionMemAlloc = 1;
1806 requestData.numOptions = numOptions + 1;
1807 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1808 requestInfo.method = CA_GET;
1809 requestInfo.info = requestData;
1811 caResult = CASendRequest(endpoint, &requestInfo);
1812 if (caResult != CA_STATUS_OK)
1814 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1816 if(caResult == CA_STATUS_OK)
1821 if(qos == OC_HIGH_QOS)
1823 ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
1824 &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
1829 FindAndDeleteClientCB(clientCB);
1833 #ifdef WITH_PRESENCE
1834 case OC_REST_PRESENCE:
1835 FindAndDeleteClientCB(clientCB);
1839 return OC_STACK_INVALID_METHOD;
1843 CADestroyRemoteEndpoint(endpoint);
1844 if (hdrOptionMemAlloc)
1846 OCFree(requestData.options);
1853 #ifdef WITH_PRESENCE
1855 OCStackResult OCProcessPresence()
1857 OCStackResult result = OC_STACK_OK;
1858 uint8_t ipAddr[4] = { 0 };
1861 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1862 ClientCB* cbNode = NULL;
1864 OCClientResponse clientResponse;
1865 OCResponse * response = NULL;
1866 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1868 LL_FOREACH(cbList, cbNode) {
1869 if(OC_REST_PRESENCE == cbNode->method)
1871 if(cbNode->presence)
1873 uint32_t now = GetTime(0);
1874 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d",
1875 cbNode->presence->TTLlevel);
1876 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1879 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1884 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1885 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1886 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1889 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1891 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1892 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1894 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1896 result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
1897 (OCDevAddr *) &dst, 0, NULL);
1898 if(result != OC_STACK_OK)
1902 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1903 &cbNode->token, &clientResponse, NULL);
1904 if(result != OC_STACK_OK)
1909 // Increment the TTLLevel (going to a next state), so we don't keep
1910 // sending presence notification to client.
1911 cbNode->presence->TTLlevel++;
1912 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1913 cbNode->presence->TTLlevel);
1917 result = OC_STACK_INVALID_IP;
1921 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1922 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1924 FindAndDeleteClientCB(cbNode);
1928 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1930 CAResult_t caResult;
1931 CARemoteEndpoint_t* endpoint = NULL;
1932 CAInfo_t requestData;
1933 CARequestInfo_t requestInfo;
1935 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1937 //TODO-CA : Why CA_WIFI alone?
1938 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1941 if (caResult != CA_STATUS_OK)
1943 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1947 memset(&requestData, 0, sizeof(CAInfo_t));
1948 requestData.type = CA_MSG_NONCONFIRM;
1949 requestData.token = cbNode->token;
1951 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1952 requestInfo.method = CA_GET;
1953 requestInfo.info = requestData;
1955 caResult = CASendRequest(endpoint, &requestInfo);
1957 if (caResult != CA_STATUS_OK)
1959 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1963 cbNode->presence->TTLlevel++;
1964 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1965 cbNode->presence->TTLlevel);
1971 if (result != OC_STACK_OK)
1973 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1978 OCStackResult OCProcessPresence()
1980 OCStackResult result = OC_STACK_OK;
1981 uint8_t ipAddr[4] = { 0 };
1984 ClientCB* cbNode = NULL;
1986 OCClientResponse clientResponse;
1987 OCResponse * response = NULL;
1989 LL_FOREACH(cbList, cbNode) {
1990 if(OC_REST_PRESENCE == cbNode->method)
1992 if(cbNode->presence)
1994 uint32_t now = GetTime(0);
1995 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1996 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1999 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
2004 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
2005 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
2006 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2009 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2011 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
2012 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
2014 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
2016 result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
2017 (OCDevAddr *) &dst, 0, NULL);
2018 if(result != OC_STACK_OK)
2022 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
2023 &cbNode->token, &clientResponse, NULL);
2024 if(result != OC_STACK_OK)
2029 // Increment the TTLLevel (going to a next state), so we don't keep
2030 // sending presence notification to client.
2031 cbNode->presence->TTLlevel++;
2032 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
2033 cbNode->presence->TTLlevel);
2037 result = OC_STACK_INVALID_IP;
2040 HandleStackResponses(response);
2042 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2044 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
2047 CAToken_t token = NULL;
2048 CAResult_t caResult = CAGenerateToken(&token);
2049 if (caResult != CA_STATUS_OK)
2051 CADestroyToken(token);
2056 OCGenerateCoAPToken(&token);
2058 result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
2059 &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
2061 if(result != OC_STACK_OK)
2066 cbNode->presence->TTLlevel++;
2067 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
2073 if (result != OC_STACK_OK)
2075 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
2080 #endif // WITH_PRESENCE
2083 * Called in main loop of OC client or server. Allows low-level processing of
2087 * OC_STACK_OK - no errors
2088 * OC_STACK_ERROR - stack process error
2090 OCStackResult OCProcess()
2092 #ifdef WITH_PRESENCE
2093 OCProcessPresence();
2096 CAHandleRequestResponse();
2104 #ifdef WITH_PRESENCE
2106 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
2107 * presence notifications to clients via multicast. Once this API has been called with a success,
2108 * clients may query for this server's presence and this server's stack will respond via multicast.
2110 * Server can call this function when it comes online for the first time, or when it comes back
2111 * online from offline mode, or when it re enters network.
2113 * @param ttl - Time To Live in seconds
2114 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
2117 * OC_STACK_OK - No errors; Success
2119 OCStackResult OCStartPresence(const uint32_t ttl)
2121 OCChangeResourceProperty(
2122 &(((OCResource *)presenceResource.handle)->resourceProperties),
2127 presenceResource.presenceTTL = ttl;
2130 if(OC_PRESENCE_UNINITIALIZED == presenceState)
2132 OCDevAddr multiCastAddr;
2133 presenceState = OC_PRESENCE_INITIALIZED;
2135 OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
2138 CAAddress_t addressInfo;
2139 strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
2140 addressInfo.IP.port = 5683;
2142 //TODO make sure there is no memory leak here since another copy
2143 //of token is being created inside AddObserver
2144 CAToken_t caToken = NULL;
2145 CAResult_t caResult = CAGenerateToken(&caToken);
2146 if (caResult != CA_STATUS_OK)
2148 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2149 CADestroyToken(caToken);
2150 return OC_STACK_ERROR;
2153 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
2154 &multiCastAddr, (OCResource *)presenceResource.handle, OC_LOW_QOS,
2155 &addressInfo, CA_WIFI);
2158 OCGenerateCoAPToken(&token);
2159 //add the presence observer
2160 AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
2161 (OCResource *)presenceResource.handle, OC_LOW_QOS);
2165 // Each time OCStartPresence is called
2166 // a different random 32-bit integer number is used
2167 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2169 return SendPresenceNotification(NULL);
2173 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
2174 * presence notifications to clients via multicast. Once this API has been called with a success,
2175 * this server's stack will not respond to clients querying for this server's presence.
2177 * Server can call this function when it is terminating, going offline, or when going
2178 * away from network.
2181 * OC_STACK_OK - No errors; Success
2183 OCStackResult OCStopPresence()
2185 OCStackResult result = OC_STACK_ERROR;
2186 //make resource inactive
2187 result = OCChangeResourceProperty(
2188 &(((OCResource *) presenceResource.handle)->resourceProperties),
2190 result = SendPresenceNotification(NULL);
2197 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
2199 defaultDeviceHandler = entityHandler;
2204 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2206 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
2208 if(myStackMode == OC_CLIENT)
2210 return OC_STACK_ERROR;
2213 return SaveDeviceInfo(deviceInfo);
2219 * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
2220 * @param resourceTypeName - name of resource type. Example: "core.led"
2221 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2222 * @param uri - URI of the resource. Example: "/a/led"
2223 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2224 * NULL for default entity handler
2225 * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
2228 * OC_STACK_OK - no errors
2229 * OC_STACK_ERROR - stack process error
2231 OCStackResult OCCreateResource(OCResourceHandle *handle,
2232 const char *resourceTypeName,
2233 const char *resourceInterfaceName,
2234 const char *uri, OCEntityHandler entityHandler,
2235 uint8_t resourceProperties) {
2237 OCResource *pointer = NULL;
2240 OCStackResult result = OC_STACK_ERROR;
2242 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
2244 if(myStackMode == OC_CLIENT)
2248 // Validate parameters
2249 if(!uri || (strlen(uri) == 0))
2251 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
2252 return OC_STACK_INVALID_URI;
2254 // Is it presented during resource discovery?
2255 if (!handle || !resourceTypeName) {
2256 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
2257 return OC_STACK_INVALID_PARAM;
2260 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
2261 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2264 // Make sure resourceProperties bitmask has allowed properties specified
2265 if (resourceProperties
2266 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
2267 OC_LOG(ERROR, TAG, PCF("Invalid property"));
2268 return OC_STACK_INVALID_PARAM;
2271 // If the headResource is NULL, then no resources have been created...
2272 pointer = headResource;
2274 // At least one resources is in the resource list, so we need to search for
2275 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2277 if (strcmp(uri, pointer->uri) == 0) {
2278 OC_LOG(ERROR, TAG, PCF("URI already in use"));
2279 return OC_STACK_INVALID_PARAM;
2281 pointer = pointer->next;
2284 // Create the pointer and insert it into the resource list
2285 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
2289 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2291 insertResource(pointer);
2294 size = strlen(uri) + 1;
2295 str = (char *) OCMalloc(size);
2299 strncpy(str, uri, size);
2302 // Set properties. Set OC_ACTIVE
2303 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2306 // Add the resourcetype to the resource
2307 result = BindResourceTypeToResource(pointer, resourceTypeName);
2308 if (result != OC_STACK_OK) {
2309 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2313 // Add the resourceinterface to the resource
2314 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2315 if (result != OC_STACK_OK) {
2316 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2320 // If an entity handler has been passed, attach it to the newly created
2321 // resource. Otherwise, set the default entity handler.
2324 pointer->entityHandler = entityHandler;
2328 pointer->entityHandler = defaultResourceEHandler;
2332 result = OC_STACK_OK;
2334 #ifdef WITH_PRESENCE
2335 if(presenceResource.handle)
2337 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2338 SendPresenceNotification(pointer->rsrcType);
2342 if (result != OC_STACK_OK)
2344 // Deep delete of resource and other dynamic elements that it contains
2345 deleteResource(pointer);
2354 * Create a resource. with host ip address for remote resource
2356 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2357 * Used to refer to resource
2358 * @param resourceTypeName - name of resource type. Example: "core.led"
2359 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2360 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2361 * @param uri - URI of the resource. Example: "/a/led"
2362 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2363 * NULL for default entity handler
2364 * @param resourceProperties - properties supported by resource.
2365 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2368 * OC_STACK_OK - no errors
2369 * OC_STACK_ERROR - stack process error
2372 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2373 const char *resourceTypeName,
2374 const char *resourceInterfaceName,
2377 OCEntityHandler entityHandler,
2378 uint8_t resourceProperties)
2382 OCStackResult result = OC_STACK_ERROR;
2384 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2385 uri, entityHandler, resourceProperties);
2387 if (result != OC_STACK_ERROR)
2390 size = strlen(host) + 1;
2391 str = (char *) OCMalloc(size);
2394 return OC_STACK_ERROR;
2396 strncpy(str, host, size);
2397 ((OCResource *) *handle)->host = str;
2404 * Add a resource to a collection resource.
2406 * @param collectionHandle - handle to the collection resource
2407 * @param resourceHandle - handle to resource to be added to the collection resource
2410 * OC_STACK_OK - no errors
2411 * OC_STACK_ERROR - stack process error
2412 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2414 OCStackResult OCBindResource(
2415 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2416 OCResource *resource;
2419 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2421 // Validate parameters
2422 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2423 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2424 // Container cannot contain itself
2425 if (collectionHandle == resourceHandle) {
2426 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2427 return OC_STACK_INVALID_PARAM;
2430 // Use the handle to find the resource in the resource linked list
2431 resource = findResource((OCResource *) collectionHandle);
2433 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2434 return OC_STACK_INVALID_PARAM;
2437 // Look for an open slot to add add the child resource.
2438 // If found, add it and return success
2439 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2440 if (!resource->rsrcResources[i]) {
2441 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2442 OC_LOG(INFO, TAG, PCF("resource bound"));
2447 #ifdef WITH_PRESENCE
2448 if(presenceResource.handle)
2450 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2451 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2455 // Unable to add resourceHandle, so return error
2456 return OC_STACK_ERROR;
2460 * Remove a resource from a collection resource.
2462 * @param collectionHandle - handle to the collection resource
2463 * @param resourceHandle - handle to resource to be added to the collection resource
2466 * OC_STACK_OK - no errors
2467 * OC_STACK_ERROR - stack process error
2468 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2470 OCStackResult OCUnBindResource(
2471 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2472 OCResource *resource;
2475 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2477 // Validate parameters
2478 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2479 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2480 // Container cannot contain itself
2481 if (collectionHandle == resourceHandle) {
2482 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2483 return OC_STACK_INVALID_PARAM;
2486 // Use the handle to find the resource in the resource linked list
2487 resource = findResource((OCResource *) collectionHandle);
2489 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2490 return OC_STACK_INVALID_PARAM;
2493 // Look for an open slot to add add the child resource.
2494 // If found, add it and return success
2495 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2496 if (resourceHandle == resource->rsrcResources[i]) {
2497 resource->rsrcResources[i] = (OCResource *) NULL;
2498 OC_LOG(INFO, TAG, PCF("resource unbound"));
2503 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2505 #ifdef WITH_PRESENCE
2506 if(presenceResource.handle)
2508 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2509 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2513 // Unable to add resourceHandle, so return error
2514 return OC_STACK_ERROR;
2517 OCStackResult BindResourceTypeToResource(OCResource* resource,
2518 const char *resourceTypeName)
2520 OCResourceType *pointer = NULL;
2523 OCStackResult result = OC_STACK_ERROR;
2525 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2527 // Validate parameters
2528 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2529 // TODO: Does resource attribute resentation really have to be maintained in stack?
2530 // Is it presented during resource discovery?
2532 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2534 // Create the resourcetype and insert it into the resource list
2535 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2540 // Set the resourceTypeName
2541 size = strlen(resourceTypeName) + 1;
2542 str = (char *) OCMalloc(size);
2546 strncpy(str, resourceTypeName, size);
2547 pointer->resourcetypename = str;
2549 insertResourceType(resource, pointer);
2550 result = OC_STACK_OK;
2552 exit: if (result != OC_STACK_OK) {
2560 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2561 const char *resourceInterfaceName)
2563 OCResourceInterface *pointer = NULL;
2566 OCStackResult result = OC_STACK_ERROR;
2568 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2570 // Validate parameters
2571 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2573 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2575 // Create the resourceinterface and insert it into the resource list
2576 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2581 // Set the resourceinterface name
2582 size = strlen(resourceInterfaceName) + 1;
2583 str = (char *) OCMalloc(size);
2587 strncpy(str, resourceInterfaceName, size);
2588 pointer->name = str;
2590 // Bind the resourceinterface to the resource
2591 insertResourceInterface(resource, pointer);
2593 result = OC_STACK_OK;
2595 exit: if (result != OC_STACK_OK) {
2604 * Bind a resourcetype to a resource.
2606 * @param handle - handle to the resource
2607 * @param resourceTypeName - name of resource type. Example: "core.led"
2610 * OC_STACK_OK - no errors
2611 * OC_STACK_ERROR - stack process error
2613 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2614 const char *resourceTypeName) {
2616 OCStackResult result = OC_STACK_ERROR;
2617 OCResource *resource;
2619 // Make sure resource exists
2620 resource = findResource((OCResource *) handle);
2622 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2623 return OC_STACK_ERROR;
2626 // call internal function
2627 result = BindResourceTypeToResource(resource, resourceTypeName);
2629 #ifdef WITH_PRESENCE
2630 if(presenceResource.handle)
2632 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2633 SendPresenceNotification(resource->rsrcType);
2641 * Bind a resourceinterface to a resource.
2643 * @param handle - handle to the resource
2644 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2647 * OC_STACK_OK - no errors
2648 * OC_STACK_ERROR - stack process error
2651 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2652 const char *resourceInterfaceName) {
2654 OCStackResult result = OC_STACK_ERROR;
2655 OCResource *resource;
2657 // Make sure resource exists
2658 resource = findResource((OCResource *) handle);
2660 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2661 return OC_STACK_ERROR;
2664 // call internal function
2665 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2667 #ifdef WITH_PRESENCE
2668 if(presenceResource.handle)
2670 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2671 SendPresenceNotification(resource->rsrcType);
2679 * Get the number of resources that have been created in the stack.
2681 * @param numResources - pointer to count variable
2684 * OC_STACK_OK - no errors
2685 * OC_STACK_ERROR - stack process error
2688 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2689 OCResource *pointer = headResource;
2691 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2692 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2695 *numResources = *numResources + 1;
2696 pointer = pointer->next;
2702 * Get a resource handle by index.
2704 * @param index - index of resource, 0 to Count - 1
2707 * Resource handle - if found
2708 * NULL - if not found
2710 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2711 OCResource *pointer = headResource;
2714 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2716 // Iterate through the list
2717 while ((i < index) && pointer) {
2719 pointer = pointer->next;
2721 return (OCResourceHandle) pointer;
2725 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2728 * @param handle - handle of resource to be deleted
2731 * OC_STACK_OK - no errors
2732 * OC_STACK_ERROR - stack process error
2733 * OC_STACK_NO_RESOURCE - resource not found
2734 * OC_STACK_INVALID_PARAM - invalid param
2736 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2737 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2740 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2741 return OC_STACK_INVALID_PARAM;
2744 OCResource *resource = findResource((OCResource *) handle);
2745 if (resource == NULL) {
2746 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2747 return OC_STACK_NO_RESOURCE;
2750 if (deleteResource((OCResource *) handle) == 0) {
2751 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2752 return OC_STACK_ERROR;
2759 * Get the URI of the resource specified by handle.
2761 * @param handle - handle of resource
2763 * URI string - if resource found
2764 * NULL - resource not found
2766 const char *OCGetResourceUri(OCResourceHandle handle) {
2767 OCResource *resource;
2768 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2770 resource = findResource((OCResource *) handle);
2772 return resource->uri;
2774 return (const char *) NULL;
2778 * Get the properties of the resource specified by handle.
2779 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2780 * for the resource by the stack.
2782 * @param handle - handle of resource
2784 * property bitmap - if resource found
2785 * NULL - resource not found
2787 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2788 OCResource *resource;
2789 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2791 resource = findResource((OCResource *) handle);
2793 return resource->resourceProperties;
2799 * Get the number of resource types of the resource.
2801 * @param handle - handle of resource
2802 * @param numResourceTypes - pointer to count variable
2805 * OC_STACK_OK - no errors
2806 * OC_STACK_ERROR - stack process error
2808 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2809 uint8_t *numResourceTypes) {
2810 OCResource *resource;
2811 OCResourceType *pointer;
2813 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2814 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2815 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2817 *numResourceTypes = 0;
2819 resource = findResource((OCResource *) handle);
2821 pointer = resource->rsrcType;
2823 *numResourceTypes = *numResourceTypes + 1;
2824 pointer = pointer->next;
2831 * Get name of resource type of the resource.
2833 * @param handle - handle of resource
2834 * @param index - index of resource, 0 to Count - 1
2837 * resource type name - if resource found
2838 * NULL - resource not found
2840 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2841 OCResourceType *resourceType;
2843 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2845 resourceType = findResourceTypeAtIndex(handle, index);
2847 return resourceType->resourcetypename;
2849 return (const char *) NULL;
2855 * Get the number of resource interfaces of the resource.
2857 * @param handle - handle of resource
2858 * @param numResources - pointer to count variable
2861 * OC_STACK_OK - no errors
2862 * OC_STACK_ERROR - stack process error
2864 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2865 uint8_t *numResourceInterfaces) {
2866 OCResourceInterface *pointer;
2867 OCResource *resource;
2869 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2871 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2872 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2874 *numResourceInterfaces = 0;
2875 resource = findResource((OCResource *) handle);
2877 pointer = resource->rsrcInterface;
2879 *numResourceInterfaces = *numResourceInterfaces + 1;
2880 pointer = pointer->next;
2887 * Get name of resource interface of the resource.
2889 * @param handle - handle of resource
2890 * @param index - index of resource, 0 to Count - 1
2893 * resource interface name - if resource found
2894 * NULL - resource not found
2896 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2897 OCResourceInterface *resourceInterface;
2899 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2901 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2902 if (resourceInterface) {
2903 return resourceInterface->name;
2905 return (const char *) NULL;
2909 * Get resource handle from the collection resource by index.
2911 * @param collectionHandle - handle of collection resource
2912 * @param index - index of contained resource, 0 to Count - 1
2915 * handle to resource - if resource found
2916 * NULL - resource not found
2918 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2920 OCResource *resource;
2922 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2924 if (index >= MAX_CONTAINED_RESOURCES) {
2928 resource = findResource((OCResource *) collectionHandle);
2933 return resource->rsrcResources[index];
2937 * Bind an entity handler to the resource.
2939 * @param handle - handle to the resource that the contained resource is to be bound
2940 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2942 * OC_STACK_OK - no errors
2943 * OC_STACK_ERROR - stack process error
2945 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2946 OCEntityHandler entityHandler) {
2947 OCResource *resource;
2949 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2951 // Validate parameters
2952 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2953 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2955 // Use the handle to find the resource in the resource linked list
2956 resource = findResource((OCResource *)handle);
2958 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2959 return OC_STACK_ERROR;
2963 resource->entityHandler = entityHandler;
2965 #ifdef WITH_PRESENCE
2966 if(presenceResource.handle)
2968 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2969 SendPresenceNotification(resource->rsrcType);
2977 * Get the entity handler for a resource.
2979 * @param handle - handle of resource
2982 * entity handler - if resource found
2983 * NULL - resource not found
2985 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2986 OCResource *resource;
2988 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2990 // Use the handle to find the resource in the resource linked list
2991 resource = findResource((OCResource *)handle);
2993 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2998 return resource->entityHandler;
3001 void incrementSequenceNumber(OCResource * resPtr)
3003 // Increment the sequence number
3004 resPtr->sequenceNum += 1;
3005 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3007 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3013 * Notify Presence subscribers that a resource has been modified
3015 * @param resourceType - Handle to the resourceType linked list of resource
3016 * that was modified.
3017 * @param qos - Quality Of Service
3020 #ifdef WITH_PRESENCE
3021 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
3023 OCResource *resPtr = NULL;
3024 OCStackResult result;
3025 OCMethod method = OC_REST_PRESENCE;
3026 uint32_t maxAge = 0;
3027 resPtr = findResource((OCResource *) presenceResource.handle);
3030 return OC_STACK_NO_RESOURCE;
3032 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3034 maxAge = presenceResource.presenceTTL;
3041 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
3045 #endif // WITH_PRESENCE
3047 * Notify observers that an observed value has changed.
3049 * @param handle - handle of resource
3052 * OC_STACK_OK - no errors
3053 * OC_STACK_NO_RESOURCE - invalid resource handle
3054 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
3056 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
3058 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
3060 OCResource *resPtr = NULL;
3061 OCStackResult result;
3062 OCMethod method = OC_REST_NOMETHOD;
3063 uint32_t maxAge = 0;
3065 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
3066 #ifdef WITH_PRESENCE
3067 if(handle == presenceResource.handle)
3071 #endif // WITH_PRESENCE
3072 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3074 // Verify that the resource exists
3075 resPtr = findResource ((OCResource *) handle);
3078 return OC_STACK_NO_RESOURCE;
3082 //only increment in the case of regular observing (not presence)
3083 incrementSequenceNumber(resPtr);
3084 method = OC_REST_OBSERVE;
3085 maxAge = MAX_OBSERVE_AGE;
3086 #ifdef WITH_PRESENCE
3087 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
3089 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3096 OCNotifyListOfObservers (OCResourceHandle handle,
3097 OCObservationId *obsIdList,
3098 uint8_t numberOfIds,
3099 unsigned char *notificationJSONPayload,
3100 OCQualityOfService qos)
3102 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
3104 OCResource *resPtr = NULL;
3105 //TODO: we should allow the server to define this
3106 uint32_t maxAge = MAX_OBSERVE_AGE;
3108 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3109 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3110 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
3112 // Verify that the resource exists
3113 resPtr = findResource ((OCResource *) handle);
3114 if (NULL == resPtr || myStackMode == OC_CLIENT)
3116 return OC_STACK_NO_RESOURCE;
3120 incrementSequenceNumber(resPtr);
3122 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3123 notificationJSONPayload, maxAge, qos));
3127 * Send a response to a request.
3128 * The response can be a regular, slow, or block (i.e. a response that
3129 * is too large to be sent in a single PDU and must span multiple transmissions)
3131 * @param response - pointer to structure that contains response parameters
3134 * OC_STACK_OK - No errors; Success
3135 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
3136 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
3137 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
3138 * persistent response buffer is necessary
3140 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3142 OCStackResult result = OC_STACK_ERROR;
3143 OCServerRequest *serverRequest = NULL;
3145 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
3147 // Validate input parameters
3148 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3149 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3151 // TODO: Placeholder for creating a response entry when implementing
3152 // block transfer feature
3154 // If a response payload is present, check if block transfer is required
3155 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
3156 (const char *)ehResponse->payload, ehResponse->payloadSize))
3158 OC_LOG(INFO, TAG, PCF("Block transfer required"));
3160 // Persistent response buffer is needed for block transfer
3161 if (!ehResponse->persistentBufferFlag)
3163 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
3164 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
3166 // TODO: Placeholder for block transfer handling
3167 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
3168 // when implementing the block transfer feature
3173 // Get pointer to request info
3174 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3177 result = serverRequest->ehResponseHandler(ehResponse);
3184 * Cancel a response. Applies to a block response
3186 * @param responseHandle - response handle set by stack in OCServerResponse after
3187 * OCDoResponse is called
3190 * OC_STACK_OK - No errors; Success
3191 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
3193 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
3195 OCStackResult result = OC_STACK_NOTIMPL;
3197 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
3199 // TODO: validate response handle
3204 //-----------------------------------------------------------------------------
3205 // Private internal function definitions
3206 //-----------------------------------------------------------------------------
3208 * Generate handle of OCDoResource invocation for callback management.
3210 static OCDoHandle GenerateInvocationHandle()
3212 OCDoHandle handle = NULL;
3213 // Generate token here, it will be deleted when the transaction is deleted
3214 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
3217 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
3222 #ifdef WITH_PRESENCE
3223 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3224 OCResourceProperty resourceProperties, uint8_t enable)
3226 if (resourceProperties
3227 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
3228 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3229 return OC_STACK_INVALID_PARAM;
3233 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3237 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3244 * Initialize resource data structures, variables, etc.
3246 OCStackResult initResources() {
3247 OCStackResult result = OC_STACK_OK;
3248 // Init application resource vars
3249 headResource = NULL;
3250 // Init Virtual Resources
3251 #ifdef WITH_PRESENCE
3252 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3253 //presenceResource.token = OCGenerateCoAPToken();
3254 result = OCCreateResource(&presenceResource.handle,
3255 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3260 //make resource inactive
3261 result = OCChangeResourceProperty(
3262 &(((OCResource *) presenceResource.handle)->resourceProperties),
3269 * Add a resource to the end of the linked list of resources.
3271 * @param resource - resource to be added
3273 void insertResource(OCResource *resource) {
3274 OCResource *pointer;
3276 if (!headResource) {
3277 headResource = resource;
3279 pointer = headResource;
3281 while (pointer->next) {
3282 pointer = pointer->next;
3284 pointer->next = resource;
3286 resource->next = NULL;
3290 * Find a resource in the linked list of resources.
3292 * @param resource - resource to be found
3294 * NULL - resource not found
3295 * pointer to resource - pointer to resource that was found in the linked list
3297 OCResource *findResource(OCResource *resource) {
3298 OCResource *pointer = headResource;
3301 if (pointer == resource) {
3304 pointer = pointer->next;
3309 void deleteAllResources()
3311 OCResource *pointer = headResource;
3316 temp = pointer->next;
3317 #ifdef WITH_PRESENCE
3318 if(pointer != (OCResource *) presenceResource.handle)
3320 #endif // WITH_PRESENCE
3321 deleteResource(pointer);
3322 #ifdef WITH_PRESENCE
3324 #endif // WITH_PRESENCE
3328 #ifdef WITH_PRESENCE
3329 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3330 // presence notification attributed to their deletion to be processed.
3331 deleteResource((OCResource *) presenceResource.handle);
3332 #endif // WITH_PRESENCE
3336 * Delete the resource from the linked list.
3338 * @param resource - resource to be deleted
3343 int deleteResource(OCResource *resource) {
3344 OCResource *prev = NULL;
3347 temp = headResource;
3349 if (temp == resource) {
3350 // Invalidate all Resource Properties.
3351 resource->resourceProperties = (OCResourceProperty) 0;
3352 #ifdef WITH_PRESENCE
3353 if(resource != (OCResource *) presenceResource.handle)
3355 #endif // WITH_PRESENCE
3356 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3357 #ifdef WITH_PRESENCE
3360 if(presenceResource.handle)
3362 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3363 if(resource != (OCResource *) presenceResource.handle)
3365 SendPresenceNotification(resource->rsrcType);
3369 SendPresenceNotification(NULL);
3374 if (temp == headResource) {
3375 headResource = temp->next;
3377 prev->next = temp->next;
3380 deleteResourceElements(temp);
3393 * Delete all of the dynamically allocated elements that were created for the resource.
3395 * @param resource - specified resource
3397 void deleteResourceElements(OCResource *resource) {
3403 OCFree(resource->uri);
3405 // Delete resourcetype linked list
3406 deleteResourceType(resource->rsrcType);
3408 // Delete resourceinterface linked list
3409 deleteResourceInterface(resource->rsrcInterface);
3413 * Delete all of the dynamically allocated elements that were created for the resource type.
3415 * @param resourceType - specified resource type
3417 void deleteResourceType(OCResourceType *resourceType) {
3418 OCResourceType *pointer = resourceType;
3419 OCResourceType *next;
3422 next = pointer->next;
3423 OCFree(pointer->resourcetypename);
3430 * Delete all of the dynamically allocated elements that were created for the resource interface.
3432 * @param resourceInterface - specified resource interface
3434 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
3435 OCResourceInterface *pointer = resourceInterface;
3436 OCResourceInterface *next;
3439 next = pointer->next;
3440 OCFree(pointer->name);
3447 * Insert a resource type into a resource's resource type linked list.
3449 * @param resource - resource where resource type is to be inserted
3450 * @param resourceType - resource type to be inserted
3452 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
3453 OCResourceType *pointer;
3455 if (resource && !resource->rsrcType) {
3456 resource->rsrcType = resourceType;
3460 pointer = resource->rsrcType;
3464 pointer = resourceType;
3466 while (pointer->next) {
3467 pointer = pointer->next;
3469 pointer->next = resourceType;
3471 resourceType->next = NULL;
3475 * Get a resource type at the specified index within a resource.
3477 * @param handle - handle of resource
3478 * @param index - index of resource type
3481 * resourcetype - if found
3484 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
3485 OCResource *resource;
3486 OCResourceType *pointer;
3489 // Find the specified resource
3490 resource = findResource((OCResource *) handle);
3495 // Make sure a resource has a resourcetype
3496 if (!resource->rsrcType) {
3500 // Iterate through the list
3501 pointer = resource->rsrcType;
3503 while ((i < index) && pointer) {
3505 pointer = pointer->next;
3511 * Finds a resource type in an OCResourceType link-list.
3513 * @param resourceTypeList - the link-list to be searched through
3514 * @param resourceTypeName - the key to search for
3517 * resourceType that matches the key (ie. resourceTypeName)
3518 * NULL - either an invalid parameter or this function was unable to find the key.
3520 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3522 if(resourceTypeList && resourceTypeName)
3524 OCResourceType * rtPointer = resourceTypeList;
3525 while(resourceTypeName && rtPointer)
3527 if(rtPointer->resourcetypename &&
3528 strcmp(resourceTypeName, (const char *)
3529 (rtPointer->resourcetypename)) == 0)
3533 rtPointer = rtPointer->next;
3540 * Insert a resource interface into a resource's resource interface linked list.
3542 * @param resource - resource where resource interface is to be inserted
3543 * @param resourceInterface - resource interface to be inserted
3545 void insertResourceInterface(OCResource *resource,
3546 OCResourceInterface *resourceInterface) {
3547 OCResourceInterface *pointer;
3549 if (!resource->rsrcInterface) {
3550 resource->rsrcInterface = resourceInterface;
3552 pointer = resource->rsrcInterface;
3553 while (pointer->next) {
3554 pointer = pointer->next;
3556 pointer->next = resourceInterface;
3558 resourceInterface->next = NULL;
3562 * Get a resource interface at the specified index within a resource.
3564 * @param handle - handle of resource
3565 * @param index - index of resource interface
3568 * resourceinterface - if found
3571 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3573 OCResource *resource;
3574 OCResourceInterface *pointer;
3577 // Find the specified resource
3578 resource = findResource((OCResource *) handle);
3583 // Make sure a resource has a resourceinterface
3584 if (!resource->rsrcInterface) {
3588 // Iterate through the list
3589 pointer = resource->rsrcInterface;
3591 while ((i < index) && pointer) {
3593 pointer = pointer->next;
3599 * Determine if a request/response must be sent in a block transfer because it is too large to be
3600 * sent in a single PDU. This function can be used for either a request or a response
3602 * @param request - NULL or pointer to request
3603 * @param response - NULL or pointer to response
3604 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3605 * the length of the request/response
3608 * 0 - packet transfer NOT required (i.e. normal request/response)
3609 * 1 - packet transfer required (i.e. block transfer needed)
3611 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3615 // Determine if we are checking a request or a response
3618 // If size is greater than 0, use it for the request size value, otherwise
3619 // assume request is null terminated and use strlen for size value
3620 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3627 // If size is greater than 0, use it for the response size value, otherwise
3628 // assume response is null terminated and use strlen for size value
3629 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3638 * Retrieves a resource type based upon a query ontains only just one
3639 * resource attribute (and that has to be of type "rt").
3641 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3642 * before passing in.
3644 * @param query - The quert part of the URI
3645 * @param resourceType - The resource type to be populated; pass by reference.
3648 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3649 * OC_STACK_OK - Success
3651 OCStackResult getResourceType(const char * query, unsigned char** resourceType)
3655 return OC_STACK_INVALID_PARAM;
3658 OCStackResult result = OC_STACK_ERROR;
3660 if(strncmp(query, "rt=", 3) == 0)
3662 *resourceType = (unsigned char *) OCMalloc(strlen(query)-3);
3665 result = OC_STACK_NO_MEMORY;
3668 strcpy((char *)*resourceType, ((const char *)&query[3]));
3669 result = OC_STACK_OK;
3675 OCStackResult getQueryFromUri(const char * uri, unsigned char** query, char ** newURI)
3679 return OC_STACK_INVALID_URI;
3681 if(!query || !newURI)
3683 return OC_STACK_INVALID_PARAM;
3685 char * leftToken = NULL;
3686 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3691 strcpy(tempURI, uri);
3693 leftToken = strtok_r((char *)tempURI, "?", &strTokPtr);
3695 //TODO-CA: This could be simplified. Clean up required.
3696 while(leftToken != NULL)
3698 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3700 *query = (unsigned char *) OCMalloc(strlen(leftToken));
3706 strcpy((char *)*query, ((const char *)&leftToken[0]));
3709 leftToken = strtok_r(NULL, "?", &strTokPtr);
3717 return OC_STACK_NO_MEMORY;
3720 const ServerID OCGetServerInstanceID(void)
3722 static bool generated = false;
3723 static ServerID sid;
3730 sid = OCGetRandom();
3735 const char* OCGetServerInstanceIDString(void)
3737 // max printed length of a base 10
3738 // uint32 is 10 characters, so 11 includes null.
3739 // This will change as the representation gets switched
3741 static char buffer[11];
3742 int n = sprintf(buffer, "%u", OCGetServerInstanceID());