1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //-----------------------------------------------------------------------------
24 //-----------------------------------------------------------------------------
25 #define _POSIX_C_SOURCE 200112L
30 #include "ocstackinternal.h"
31 #include "ocresourcehandler.h"
32 #include "occlientcb.h"
33 #include "ocobserve.h"
36 #include "ocserverrequest.h"
37 #include "ocsecurityinternal.h"
40 #include "cainterface.h"
47 #include "coap_time.h"
52 #include <arpa/inet.h>
55 //-----------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------
59 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
63 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
67 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
70 static OCStackState stackState = OC_STACK_UNINITIALIZED;
72 OCResource *headResource = NULL;
74 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
75 static PresenceResource presenceResource;
76 uint8_t PresenceTimeOutSize = 0;
77 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
81 OCDeviceEntityHandler defaultDeviceHandler;
82 OCStackResult getQueryFromUri(const char * uri, unsigned char** resourceType, char ** newURI);
84 //-----------------------------------------------------------------------------
86 //-----------------------------------------------------------------------------
87 #define TAG PCF("OCStack")
88 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
89 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
90 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
91 TAG, PCF(#arg " is NULL")); return (retVal); } }
92 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
95 //TODO: we should allow the server to define this
96 #define MAX_OBSERVE_AGE (0x2FFFFUL)
98 //=============================================================================
100 //=============================================================================
101 static uint32_t GetTime(float afterSeconds)
105 return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
108 static OCStackResult FormOCResponse(OCResponse * * responseLoc,
111 unsigned char * fullUri,
112 unsigned char * rcvdUri,
113 CAToken_t * rcvdToken,
114 OCClientResponse * clientResponse,
115 unsigned char * bufRes)
117 OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
120 return OC_STACK_NO_MEMORY;
122 response->cbNode = cbNode;
123 response->maxAge = maxAge;
124 response->fullUri = fullUri;
125 response->rcvdUri = rcvdUri;
126 response->rcvdToken = rcvdToken;
127 response->clientResponse = clientResponse;
128 response->bufRes = bufRes;
130 *responseLoc = response;
134 //-----------------------------------------------------------------------------
135 // Internal API function
136 //-----------------------------------------------------------------------------
138 // This internal function is called to update the stack with the status of
139 // observers and communication failures
140 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
142 OCStackResult result = OC_STACK_ERROR;
143 ResourceObserver * observer = NULL;
144 OCEntityHandlerRequest ehRequest = {0};
148 case OC_OBSERVER_NOT_INTERESTED:
149 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
150 observer = GetObserverUsingToken (token);
153 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
154 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
155 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
156 if(result != OC_STACK_OK)
160 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
162 //observer is not observing anymore
163 result = DeleteObserverUsingToken (token);
164 if(result == OC_STACK_OK)
166 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
170 result = OC_STACK_OK;
171 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
174 case OC_OBSERVER_STILL_INTERESTED:
175 //observer is still interested
176 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
177 notifications, reset the failedCount"));
178 observer = GetObserverUsingToken (token);
181 observer->forceHighQos = 0;
182 observer->failedCommCount = 0;
183 result = OC_STACK_OK;
187 result = OC_STACK_OBSERVER_NOT_FOUND;
190 case OC_OBSERVER_FAILED_COMM:
191 //observer is not reachable
192 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
193 observer = GetObserverUsingToken (token);
196 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
198 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
199 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
200 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
201 if(result != OC_STACK_OK)
203 return OC_STACK_ERROR;
205 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
206 //observer is unreachable
207 result = DeleteObserverUsingToken (token);
208 if(result == OC_STACK_OK)
210 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
214 result = OC_STACK_OK;
215 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
220 observer->failedCommCount++;
221 result = OC_STACK_CONTINUE;
223 observer->forceHighQos = 1;
224 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
228 OC_LOG(ERROR, TAG, PCF("Unknown status"));
229 result = OC_STACK_ERROR;
235 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
237 OCStackResult ret = OC_STACK_ERROR;
245 ret = OC_STACK_RESOURCE_CREATED;
248 ret = OC_STACK_RESOURCE_DELETED;
251 ret = OC_STACK_INVALID_QUERY;
254 ret = OC_STACK_INVALID_OPTION;
257 ret = OC_STACK_NO_RESOURCE;
265 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
267 OCStackResult ret = OC_STACK_OK;
272 *caConType = CA_ETHERNET;
275 *caConType = CA_WIFI;
284 // Currently OC_ALL represents WIFI and ETHERNET
285 // Add other connectivity types as they are enabled in future
286 *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
289 ret = OC_STACK_INVALID_PARAM;
295 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
297 OCStackResult ret = OC_STACK_OK;
302 *ocConType = OC_ETHERNET;
305 *ocConType = OC_WIFI;
314 ret = OC_STACK_INVALID_PARAM;
320 // update response.addr appropriately from endPoint.addressInfo
321 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
323 OCStackResult ret = OC_STACK_ERROR;
324 static OCDevAddr address = {0};
326 char * savePtr = NULL;
327 char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
330 ret = OC_STACK_NO_MEMORY;
333 memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
334 strlen(endPoint->addressInfo.IP.ipAddress) + 1);
336 // Grabs the first three numbers from the IPv4 address and replaces dots
337 for(int i=0; i<4; i++)
339 tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
343 ret = OC_STACK_ERROR;
346 address.addr[i] = atoi(tok);
349 memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
353 response->addr = &address;
354 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
358 OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
365 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
369 // The format of the payload is {"oc":[%u:%u:%s]}
370 // %u : sequence number,
372 // %s : Resource Type (Optional)
373 tok = strtok_r(payload, "[:]}", &savePtr);
374 payload[strlen(payload)] = ':';
375 tok = strtok_r(NULL, "[:]}", &savePtr);
376 payload[strlen((char *)payload)] = ':';
377 *seqNum = (uint32_t) atoi(tok);
378 tok = strtok_r(NULL, "[:]}", &savePtr);
379 *maxAge = (uint32_t) atoi(tok);
380 tok = strtok_r(NULL, "[:]}",&savePtr);
384 *resType = (char *)OCMalloc(strlen(tok));
389 payload[strlen((char *)payload)] = ':';
390 strcpy(*resType, tok);
391 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", *resType);
393 payload[strlen((char *)payload)] = ']';
396 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
397 const CAResponseInfo_t* responseInfo)
399 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
400 ClientCB * cbNode = NULL;
401 char *resourceTypeName = NULL;
402 OCClientResponse response;
403 OCStackResult result = OC_STACK_ERROR;
404 uint32_t lowerBound = 0;
405 uint32_t higherBound = 0;
408 char *fullUri = NULL;
409 char *ipAddress = NULL;
410 int presenceSubscribe = 0;
411 int multicastPresenceSubscribe = 0;
413 if (responseInfo->result != CA_SUCCESS)
415 OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
416 return OC_STACK_ERROR;
419 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
423 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
424 result = OC_STACK_NO_MEMORY;
428 ipAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
430 if(NULL == ipAddress)
432 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
433 result = OC_STACK_NO_MEMORY;
437 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress,
438 strlen(endPoint->addressInfo.IP.ipAddress));
439 ipAddress[strlen(endPoint->addressInfo.IP.ipAddress)] = '\0';
441 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
444 cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
448 presenceSubscribe = 1;
452 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
453 cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
456 multicastPresenceSubscribe = 1;
460 if(!presenceSubscribe && !multicastPresenceSubscribe)
462 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
463 ------------ ignoring"));
467 // No payload to the application in case of presence
468 response.resJSONPayload = NULL;
469 response.result = OC_STACK_OK;
471 result = UpdateResponseAddr(&response, endPoint);
472 if(result != OC_STACK_OK)
477 if(responseInfo->info.payload)
479 parsePresencePayload(responseInfo->info.payload,
480 &(response.sequenceNumber),
487 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
488 response.result = OC_STACK_PRESENCE_STOPPED;
491 OCFree(cbNode->presence->timeOut);
492 OCFree(cbNode->presence);
493 cbNode->presence = NULL;
496 else if(presenceSubscribe)
498 if(!cbNode->presence)
500 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
501 VERIFY_NON_NULL_V(cbNode->presence);
502 cbNode->presence->timeOut = NULL;
503 cbNode->presence->timeOut = (uint32_t *)
504 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
505 if(!(cbNode->presence->timeOut)){
506 OCFree(cbNode->presence);
507 result = OC_STACK_NO_MEMORY;
511 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
512 cbNode->presence->TTL = maxAge;
513 for(int index = 0; index < PresenceTimeOutSize; index++)
515 lowerBound = GetTime(((float)(PresenceTimeOut[index])
516 /(float)100)*(float)cbNode->presence->TTL);
517 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
518 /(float)100)*(float)cbNode->presence->TTL);
519 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
520 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
521 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
522 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
523 cbNode->presence->timeOut[index]);
525 cbNode->presence->TTLlevel = 0;
526 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
527 if(cbNode->sequenceNumber == response.sequenceNumber)
529 OC_LOG(INFO, TAG, PCF("===============No presence change"));
532 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
533 cbNode->sequenceNumber = response.sequenceNumber;
535 // Ensure that a filter is actually applied.
536 if(resourceTypeName && cbNode->filterResourceType)
538 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
546 // This is the multicast case
548 OCMulticastNode* mcNode = NULL;
549 mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
553 if(mcNode->nonce == response.sequenceNumber)
555 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
558 mcNode->nonce = response.sequenceNumber;
562 uint32_t uriLen = strlen((char*)fullUri);
563 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
566 memcpy(uri, fullUri, (uriLen + 1));
571 PCF("===============No Memory for URI to store in the presence node"));
572 result = OC_STACK_NO_MEMORY;
575 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, response.sequenceNumber);
576 if(result == OC_STACK_NO_MEMORY)
579 PCF("===============No Memory for Multicast Presence Node"));
580 result = OC_STACK_NO_MEMORY;
585 // Ensure that a filter is actually applied.
586 if(resourceTypeName && cbNode->filterResourceType)
588 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
595 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
597 if (cbResult == OC_STACK_DELETE_TRANSACTION)
599 FindAndDeleteClientCB(cbNode);
605 OCFree(resourceTypeName);
610 //This function will be called back by CA layer when a response is received
611 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
613 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
615 OCStackApplicationResult appResult = OC_STACK_DELETE_TRANSACTION;
619 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
623 if(NULL == responseInfo)
625 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
629 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
631 HandlePresenceResponse(endPoint, responseInfo);
635 ClientCB *cbNode = GetClientCB((CAToken_t *)&(responseInfo->info.token), NULL, NULL);
639 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
640 OCClientResponse response;
642 OCStackResult result = UpdateResponseAddr(&response, endPoint);
643 if(result != OC_STACK_OK)
645 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
649 response.result = CAToOCStackResult(responseInfo->result);
650 response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
651 response.numRcvdVendorSpecificHeaderOptions = 0;
652 if(responseInfo->info.numOptions > 0)
655 //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
656 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
658 memcpy (&(response.sequenceNumber),
659 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
660 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
665 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
668 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
670 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
674 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
676 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
677 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
680 appResult = cbNode->callBack(cbNode->context,
681 cbNode->handle, &response);
682 if (appResult == OC_STACK_DELETE_TRANSACTION)
684 FindAndDeleteClientCB(cbNode);
687 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
688 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
691 //This function will be called back by CA layer when a request is received
692 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
694 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
697 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
703 OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
707 OCStackResult requestResult = OC_STACK_ERROR;
709 if(myStackMode == OC_CLIENT)
711 //TODO: should the client be responding to requests?
715 OCServerProtocolRequest serverRequest = {};
717 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
719 char * newUri = (char *)endPoint->resourceUri;
720 unsigned char * query = NULL;
721 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
722 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
723 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
724 if(strlen(newUri) < MAX_URI_LENGTH)
727 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
731 OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
737 if(strlen((char*)query) < MAX_QUERY_LENGTH)
739 memcpy (&(serverRequest.query), query, strlen((char*)query));
743 OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
747 //copy request payload
748 if (requestInfo->info.payload)
750 serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
751 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
752 strlen(requestInfo->info.payload));
753 serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
757 serverRequest.reqTotalSize = 1;
760 switch (requestInfo->method)
764 serverRequest.method = OC_REST_GET;
769 serverRequest.method = OC_REST_PUT;
774 serverRequest.method = OC_REST_POST;
779 serverRequest.method = OC_REST_DELETE;
784 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
789 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
790 OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
792 serverRequest.requestToken = (CAToken_t)OCCalloc(1, CA_MAX_TOKEN_LEN+1);
794 if (!serverRequest.requestToken)
796 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
799 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
801 if (requestInfo->info.type == CA_MSG_CONFIRM)
803 serverRequest.qos = OC_HIGH_QOS;
805 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
807 serverRequest.qos = OC_LOW_QOS;
809 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
811 // TODO-CA: Need to handle this
813 else if (requestInfo->info.type == CA_MSG_RESET)
815 // TODO-CA: Need to handle this
817 // CA does not need the following 3 fields
818 serverRequest.coapID = 0;
819 serverRequest.delayedResNeeded = 0;
820 serverRequest.secured = endPoint->isSecured;
823 serverRequest.addressInfo = endPoint->addressInfo;
824 serverRequest.connectivityType = endPoint->connectivityType;
826 // copy vendor specific header options
827 // TODO-CA: CA is including non-vendor header options as well, like observe.
828 // Need to filter those out
829 uint8_t tempNum = (requestInfo->info.numOptions);
830 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
831 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
834 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
835 OCFree(serverRequest.requestToken);
838 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
839 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
841 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
842 sizeof(CAHeaderOption_t)*tempNum);
845 requestResult = HandleStackRequests (&serverRequest);
846 if(requestResult != OC_STACK_OK)
848 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
850 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
853 //This function will be called back by occoap layer when a request is received
854 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
856 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
857 OCStackResult result = OC_STACK_ERROR;
858 ResourceHandling resHandling;
859 OCResource *resource;
862 OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
863 return OC_STACK_INVALID_PARAM;
866 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
869 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
870 result = AddServerRequest(&request, protocolRequest->coapID,
871 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
872 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
873 protocolRequest->observationOption, protocolRequest->qos,
874 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
875 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
876 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
877 protocolRequest->reqTotalSize,
878 &protocolRequest->addressInfo, protocolRequest->connectivityType);
879 if (OC_STACK_OK != result)
881 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
884 VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
886 if(!protocolRequest->reqMorePacket)
888 request->requestComplete = 1;
893 OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
896 if(request->requestComplete)
898 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
899 result = DetermineResourceHandling (request, &resHandling, &resource);
900 if (result == OC_STACK_OK)
902 result = ProcessRequest(resHandling, resource, request);
906 result = OC_STACK_ERROR;
911 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
912 result = OC_STACK_CONTINUE;
917 //This function will be called back by occoap layer when a response is received
918 OCStackResult HandleStackResponses(OCResponse * response)
920 OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
921 OCStackResult result = OC_STACK_OK;
922 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
923 uint8_t isObserveNotification = 0;
924 ClientCB * cbNode = NULL;
927 OC_LOG(ERROR, TAG, PCF("response is NULL"));
928 return OC_STACK_INVALID_PARAM;
931 uint8_t isPresenceNotification = 0;
932 uint8_t isMulticastPresence = 0;
933 char * resourceTypeName = NULL;
934 uint32_t lowerBound = 0;
935 uint32_t higherBound = 0;
937 unsigned char * bufRes = response->bufRes;
938 #endif // WITH_PRESENCE
940 cbNode = response->cbNode;
943 cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
946 if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
948 isObserveNotification = 1;
949 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
952 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
953 response->clientResponse->sequenceNumber);
954 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
955 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
958 if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
959 isPresenceNotification = 1;
962 result = OC_STACK_INVALID_PARAM;
966 tok = strtok_r((char *)bufRes, "[:]}", &savePtr);
967 bufRes[strlen((char *)bufRes)] = ':';
968 tok = strtok_r(NULL, "[:]}", &savePtr);
969 bufRes[strlen((char *)bufRes)] = ':';
970 response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
971 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
972 tok = strtok_r(NULL, "[:]}", &savePtr);
973 response->maxAge = (uint32_t )atoi(tok);
974 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
975 tok = strtok_r(NULL, "[:]}", &savePtr);
978 resourceTypeName = (char *)OCMalloc(strlen(tok));
979 if(!resourceTypeName)
983 bufRes[strlen((char *)bufRes)] = ':';
984 strcpy(resourceTypeName, tok);
985 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
988 bufRes[strlen((char *)bufRes)] = ']';
991 // Check if the application subcribed for presence
994 cbNode = GetClientCB(NULL, NULL, response->fullUri);
997 // Check if application subscribed for multicast presence
1000 snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
1001 OC_MULTICAST_IP, response->rcvdUri);
1002 cbNode = GetClientCB(NULL, NULL, response->fullUri);
1005 isMulticastPresence = 1;
1006 isPresenceNotification = 0;
1010 if(cbNode && isPresenceNotification)
1012 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
1013 if(!cbNode->presence)
1015 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
1016 VERIFY_NON_NULL_V(cbNode->presence);
1017 cbNode->presence->timeOut = NULL;
1018 cbNode->presence->timeOut = (uint32_t *)
1019 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
1020 if(!(cbNode->presence->timeOut)){
1021 OCFree(cbNode->presence);
1022 result = OC_STACK_NO_MEMORY;
1025 if(response->maxAge == 0)
1027 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
1028 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
1029 if(cbNode->presence)
1031 OCFree(cbNode->presence->timeOut);
1032 OCFree(cbNode->presence);
1033 cbNode->presence = NULL;
1038 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
1039 cbNode->presence->TTL = response->maxAge;
1040 for(int index = 0; index < PresenceTimeOutSize; index++)
1042 lowerBound = GetTime(((float)(PresenceTimeOut[index])
1043 /(float)100)*(float)cbNode->presence->TTL);
1044 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
1045 /(float)100)*(float)cbNode->presence->TTL);
1046 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
1047 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
1048 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
1049 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
1050 cbNode->presence->timeOut[index]);
1052 cbNode->presence->TTLlevel = 0;
1053 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1054 if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
1056 OC_LOG(INFO, TAG, PCF("===============No presence change"));
1059 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
1060 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
1063 // Ensure that a filter is actually applied.
1064 if(resourceTypeName && cbNode->filterResourceType)
1066 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1072 else if(cbNode && isMulticastPresence)
1074 // Check if the same nonce for a given host
1075 OCMulticastNode* mcNode = NULL;
1076 mcNode = GetMCPresenceNode(response->fullUri);
1078 if(response->maxAge == 0)
1080 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
1081 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
1082 if(cbNode->presence)
1084 OCFree(cbNode->presence->timeOut);
1085 OCFree(cbNode->presence);
1086 cbNode->presence = NULL;
1089 else if(mcNode != NULL)
1091 if(mcNode->nonce == response->clientResponse->sequenceNumber)
1093 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
1094 result = OC_STACK_NO_MEMORY;
1097 mcNode->nonce = response->clientResponse->sequenceNumber;
1101 uint32_t uriLen = strlen((char*)response->fullUri);
1102 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
1105 memcpy(uri, response->fullUri, (uriLen + 1));
1110 PCF("===============No Memory for URI to store in the presence node"));
1111 result = OC_STACK_NO_MEMORY;
1114 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
1115 response->clientResponse->sequenceNumber);
1116 if(result == OC_STACK_NO_MEMORY)
1119 PCF("===============No Memory for Multicast Presence Node"));
1120 result = OC_STACK_NO_MEMORY;
1125 // Ensure that a filter is actually applied.
1126 if(resourceTypeName && cbNode->filterResourceType)
1128 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1135 else if(!cbNode && isPresenceNotification)
1137 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
1138 ------------ ignoring"));
1140 #endif // WITH_PRESENCE
1144 if(isObserveNotification)
1146 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
1147 //TODO: check the standard for methods to detect wrap around condition
1148 if(cbNode->method == OC_REST_OBSERVE &&
1149 (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
1150 (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
1151 response->clientResponse->sequenceNumber ==
1152 MAX_SEQUENCE_NUMBER)))
1154 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
1155 Ignoring Incoming:%d Against Current:%d.",
1156 response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
1159 if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
1160 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
1164 response->clientResponse->resJSONPayload = bufRes;
1166 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
1168 if (cbResult == OC_STACK_DELETE_TRANSACTION ||
1169 response->clientResponse->result == OC_STACK_COMM_ERROR ||
1170 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
1171 !isPresenceNotification && !isMulticastPresence))
1173 FindAndDeleteClientCB(cbNode);
1178 result = OC_STACK_ERROR;
1182 #ifdef WITH_PRESENCE
1183 OCFree(resourceTypeName);
1188 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
1191 unsigned char *itr, *coap;
1192 uint8_t dotCount = 0;
1196 /* search for scheme */
1198 if (!isdigit((unsigned char) *ipAddrStr))
1200 coap = (unsigned char *) OC_COAP_SCHEME;
1201 while (*coap && tolower(*itr) == *coap)
1209 while (*ipAddrStr) {
1210 if (isdigit((unsigned char) *ipAddrStr))
1212 ipAddr[index] *= 10;
1213 ipAddr[index] += *ipAddrStr - '0';
1215 else if ((unsigned char) *ipAddrStr == '.')
1227 if(*ipAddrStr == ':')
1231 if (isdigit((unsigned char) *ipAddrStr))
1234 *port += *ipAddrStr - '0';
1245 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
1256 //-----------------------------------------------------------------------------
1257 // Private internal function prototypes
1258 //-----------------------------------------------------------------------------
1260 static OCDoHandle GenerateInvocationHandle();
1261 static OCStackResult initResources();
1262 static void insertResource(OCResource *resource);
1263 static OCResource *findResource(OCResource *resource);
1264 static void insertResourceType(OCResource *resource,
1265 OCResourceType *resourceType);
1266 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1268 static void insertResourceInterface(OCResource *resource,
1269 OCResourceInterface *resourceInterface);
1270 static OCResourceInterface *findResourceInterfaceAtIndex(
1271 OCResourceHandle handle, uint8_t index);
1272 static void deleteResourceType(OCResourceType *resourceType);
1273 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1274 static void deleteResourceElements(OCResource *resource);
1275 static int deleteResource(OCResource *resource);
1276 static void deleteAllResources();
1277 static void incrementSequenceNumber(OCResource * resPtr);
1278 static OCStackResult verifyUriQueryLength(const char * inputUri,
1280 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1281 OCStackResult getResourceType(const char * query, unsigned char** resourceType);
1283 //-----------------------------------------------------------------------------
1285 //-----------------------------------------------------------------------------
1288 * Initialize the OC Stack. Must be called prior to starting the stack.
1291 * IP Address of host device
1293 * Port of host device
1295 * Host device is client, server, or client-server
1298 * OC_STACK_OK - no errors
1299 * OC_STACK_ERROR - stack init error
1301 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1303 OCStackResult result = OC_STACK_ERROR;
1304 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1307 if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
1309 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1310 return OC_STACK_ERROR;
1315 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
1320 //It is ok to select network to CA_WIFI for now
1322 CAResult_t caResult = CASelectNetwork(CA_ETHERNET);
1324 CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
1326 if(caResult == CA_STATUS_OK)
1328 OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
1329 CARegisterHandler(HandleCARequests, HandleCAResponses);
1331 OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
1332 stackState = OC_STACK_INITIALIZED;
1333 result = OC_STACK_OK;
1337 caResult = CAStartDiscoveryServer();
1338 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1341 caResult = CAStartListeningServer();
1342 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1344 case OC_CLIENT_SERVER:
1345 caResult = CAStartListeningServer();
1346 if(caResult == CA_STATUS_OK)
1348 caResult = CAStartDiscoveryServer();
1350 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1353 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1354 return OC_STACK_ERROR;
1359 if (caResult == CA_STATUS_OK)
1361 result = OC_STACK_OK;
1365 result = OC_STACK_ERROR;
1370 defaultDeviceHandler = NULL;
1372 #if defined(__WITH_DTLS__)
1373 caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
1374 result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
1375 #endif // (__WITH_DTLS__)
1377 #ifdef WITH_PRESENCE
1378 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1379 #endif // WITH_PRESENCE
1381 if (result == OC_STACK_OK)
1383 stackState = OC_STACK_INITIALIZED;
1385 // Initialize resource
1386 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
1388 result = initResources();
1390 if(result != OC_STACK_OK)
1392 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1398 * Stop the OC stack. Use for a controlled shutdown.
1400 * OC_STACK_OK - no errors
1401 * OC_STACK_ERROR - stack not initialized
1403 OCStackResult OCStop()
1405 OCStackResult result = OC_STACK_ERROR;
1407 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1409 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1411 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1414 else if (stackState != OC_STACK_INITIALIZED)
1416 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1417 return OC_STACK_ERROR;
1420 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1422 #ifdef WITH_PRESENCE
1423 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1424 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1425 presenceResource.presenceTTL = 0;
1426 #endif // WITH_PRESENCE
1428 // Free memory dynamically allocated for resources
1429 deleteAllResources();
1432 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1433 result = OC_STACK_OK;
1435 if (result == OC_STACK_OK)
1437 // Remove all observers
1438 DeleteObserverList();
1439 // Remove all the client callbacks
1440 DeleteClientCBList();
1441 stackState = OC_STACK_UNINITIALIZED;
1442 result = OC_STACK_OK;
1444 stackState = OC_STACK_INITIALIZED;
1445 result = OC_STACK_ERROR;
1448 // Deinit security blob
1449 DeinitOCSecurityInfo();
1451 if (result != OC_STACK_OK) {
1452 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1459 * Map OCQualityOfService to CAMessageType
1461 * @param OCQualityOfService - Input qos.
1463 * Returns CA message type for a given qos.
1465 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1470 return CA_MSG_CONFIRM;
1475 return CA_MSG_NONCONFIRM;
1480 * Verify the lengths of the URI and the query separately
1482 * @param inputUri - Input URI and query.
1483 * @param uriLen - The length of the initial URI with query.
1485 * Note: The '?' that appears after the URI is not considered as
1486 * a part of the query.
1488 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1492 query = strchr (inputUri, '?');
1496 if((query - inputUri) > MAX_URI_LENGTH)
1498 return OC_STACK_INVALID_URI;
1501 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1503 return OC_STACK_INVALID_QUERY;
1506 else if(uriLen > MAX_URI_LENGTH)
1508 return OC_STACK_INVALID_URI;
1514 * Discover or Perform requests on a specified resource
1515 * (specified by that Resource's respective URI).
1517 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
1519 * @param method - @ref OCMethod to perform on the resource
1520 * @param requiredUri - URI of the resource to interact with
1521 * @param referenceUri - URI of the reference resource
1522 * @param request - JSON encoded request
1523 * @param qos - quality of service
1524 * @param cbData - struct that contains asynchronous callback function that is invoked
1525 * by the stack when discovery or resource interaction is complete
1526 * @param options - The address of an array containing the vendor specific header
1527 * header options to be sent with the request
1528 * @param numOptions - Number of vendor specific header options to be included
1531 * OC_STACK_OK - no errors
1532 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1533 * OC_STACK_INVALID_METHOD - invalid resource method
1534 * OC_STACK_INVALID_URI - invalid required or reference URI
1536 * Note: IN case of CA, when using multicast, the required URI should not contain IP address.
1537 * Instead, it just contains the URI to the resource such as "/oc/core".
1539 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1540 const char *referenceUri, const char *request, OCConnectivityType conType,
1541 OCQualityOfService qos, OCCallbackData *cbData,
1542 OCHeaderOption * options, uint8_t numOptions)
1544 OCStackResult result = OC_STACK_ERROR;
1545 ClientCB *clientCB = NULL;
1546 unsigned char * requestUri = NULL;
1547 unsigned char * resourceType = NULL;
1548 unsigned char * query = NULL;
1549 char * newUri = (char *)requiredUri;
1550 (void) referenceUri;
1551 CARemoteEndpoint_t* endpoint = NULL;
1552 CAResult_t caResult;
1553 CAToken_t token = NULL;
1554 CAInfo_t requestData;
1555 CARequestInfo_t requestInfo;
1556 CAGroupEndpoint_t grpEnd = {0};
1558 // To track if memory is allocated for additional header options
1559 uint8_t hdrOptionMemAlloc = 0;
1561 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1563 // Validate input parameters
1564 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1565 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1567 //TODO ("Need to form the final query by concatenating require and reference URI's");
1568 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1570 uint16_t uriLen = strlen(requiredUri);
1572 // ToDo: We should also check if the requiredUri has a mutlicast address,
1573 // then qos has to be OC_Low_QOS
1579 case OC_REST_DELETE:
1580 case OC_REST_OBSERVE:
1581 case OC_REST_OBSERVE_ALL:
1582 case OC_REST_CANCEL_OBSERVE:
1584 #ifdef WITH_PRESENCE
1585 case OC_REST_PRESENCE:
1589 result = OC_STACK_INVALID_METHOD;
1593 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1598 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1600 result = OC_STACK_INVALID_PARAM;
1604 #ifdef WITH_PRESENCE
1605 if(method == OC_REST_PRESENCE)
1607 result = getQueryFromUri(requiredUri, &query, &newUri);
1610 result = getResourceType((char *) query, &resourceType);
1613 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1617 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1622 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1624 if(result != OC_STACK_OK)
1629 #endif // WITH_PRESENCE
1631 requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1634 memcpy(requestUri, newUri, (uriLen + 1));
1638 result = OC_STACK_NO_MEMORY;
1642 *handle = GenerateInvocationHandle();
1645 result = OC_STACK_NO_MEMORY;
1649 memset(&requestData, 0, sizeof(CAInfo_t));
1650 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1654 case OC_REST_OBSERVE:
1655 case OC_REST_OBSERVE_ALL:
1656 case OC_REST_CANCEL_OBSERVE:
1658 requestInfo.method = CA_GET;
1663 requestInfo.method = CA_PUT;
1668 requestInfo.method = CA_POST;
1671 case OC_REST_DELETE:
1673 requestInfo.method = CA_DELETE;
1676 #ifdef WITH_PRESENCE
1677 case OC_REST_PRESENCE:
1679 // Replacing method type with GET because "presence"
1680 // is a stack layer only implementation.
1681 requestInfo.method = CA_GET;
1686 result = OC_STACK_INVALID_METHOD;
1690 //High QoS is not supported
1691 if(qos == OC_HIGH_QOS)
1693 result = OC_STACK_INVALID_PARAM;
1698 caResult = CAGenerateToken(&token);
1699 if (caResult != CA_STATUS_OK)
1701 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1702 CADestroyToken(token);
1706 requestData.type = qualityOfServiceToMessageType(qos);
1707 requestData.token = token;
1708 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1710 result = CreateObserveHeaderOption (&(requestData.options), options,
1711 numOptions, OC_OBSERVE_REGISTER);
1712 if (result != OC_STACK_OK)
1716 hdrOptionMemAlloc = 1;
1717 requestData.numOptions = numOptions + 1;
1721 requestData.options = (CAHeaderOption_t*)options;
1722 requestData.numOptions = numOptions;
1724 requestData.payload = (char *)request;
1726 requestInfo.info = requestData;
1728 CAConnectivityType_t caConType;
1730 result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
1731 if (result != OC_STACK_OK)
1733 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1738 if(conType == OC_ALL)
1740 grpEnd.connectivityType = caConType;
1742 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1743 if(!grpEnd.resourceUri)
1745 result = OC_STACK_NO_MEMORY;
1748 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1750 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1754 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1756 if (caResult != CA_STATUS_OK)
1758 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1762 caResult = CASendRequest(endpoint, &requestInfo);
1765 if (caResult != CA_STATUS_OK)
1767 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1771 if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
1772 requestUri, resourceType)) != OC_STACK_OK)
1774 result = OC_STACK_NO_MEMORY;
1779 if(newUri != requiredUri)
1783 if (result != OC_STACK_OK)
1785 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1786 FindAndDeleteClientCB(clientCB);
1788 CADestroyRemoteEndpoint(endpoint);
1789 OCFree(grpEnd.resourceUri);
1790 if (hdrOptionMemAlloc)
1792 OCFree(requestData.options);
1798 * Cancel a request associated with a specific @ref OCDoResource invocation.
1800 * @param handle - Used to identify a specific OCDoResource invocation.
1801 * @param qos - used to specify Quality of Service (read below for more info)
1802 * @param options- used to specify vendor specific header options when sending
1803 * explicit observe cancellation
1804 * @param numOptions- Number of header options to be included
1807 * OC_STACK_OK - No errors; Success
1808 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1810 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1814 * This ftn is implemented one of two ways in the case of observation:
1816 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1817 * Remove the callback associated on client side.
1818 * When the next notification comes in from server,
1819 * reply with RESET message to server.
1820 * Keep in mind that the server will react to RESET only
1821 * if the last notification was sent ans CON
1823 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1824 * and it is associated with an observe request
1825 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1826 * Send CON Observe request to server with
1827 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1828 * Remove the callback associated on client side.
1830 OCStackResult ret = OC_STACK_OK;
1831 CARemoteEndpoint_t* endpoint = NULL;
1832 CAResult_t caResult;
1833 CAInfo_t requestData;
1834 CARequestInfo_t requestInfo;
1835 // Track if memory is allocated for additional header options
1836 uint8_t hdrOptionMemAlloc = 0;
1839 return OC_STACK_INVALID_PARAM;
1842 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1844 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1847 switch (clientCB->method)
1849 case OC_REST_OBSERVE:
1850 case OC_REST_OBSERVE_ALL:
1851 //TODO-CA : Why CA_WIFI alone?
1852 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1854 if (caResult != CA_STATUS_OK)
1856 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1857 return OC_STACK_ERROR;
1860 memset(&requestData, 0, sizeof(CAInfo_t));
1861 requestData.type = qualityOfServiceToMessageType(qos);
1862 requestData.token = clientCB->token;
1863 if (CreateObserveHeaderOption (&(requestData.options),
1864 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1866 return OC_STACK_ERROR;
1868 hdrOptionMemAlloc = 1;
1869 requestData.numOptions = numOptions + 1;
1870 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1871 requestInfo.method = CA_GET;
1872 requestInfo.info = requestData;
1874 caResult = CASendRequest(endpoint, &requestInfo);
1875 if (caResult != CA_STATUS_OK)
1877 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1879 if(caResult == CA_STATUS_OK)
1883 #ifdef WITH_PRESENCE
1884 case OC_REST_PRESENCE:
1885 FindAndDeleteClientCB(clientCB);
1889 return OC_STACK_INVALID_METHOD;
1892 CADestroyRemoteEndpoint(endpoint);
1893 if (hdrOptionMemAlloc)
1895 OCFree(requestData.options);
1901 #ifdef WITH_PRESENCE
1902 OCStackResult OCProcessPresence()
1904 OCStackResult result = OC_STACK_OK;
1905 uint8_t ipAddr[4] = { 0 };
1908 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1909 ClientCB* cbNode = NULL;
1911 OCClientResponse clientResponse;
1912 OCResponse * response = NULL;
1913 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1915 LL_FOREACH(cbList, cbNode) {
1916 if(OC_REST_PRESENCE == cbNode->method)
1918 if(cbNode->presence)
1920 uint32_t now = GetTime(0);
1921 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d",
1922 cbNode->presence->TTLlevel);
1923 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1926 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1931 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1932 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1933 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1936 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1938 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1939 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1941 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1944 clientResponse.sequenceNumber = 0;
1945 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
1946 clientResponse.addr = (OCDevAddr *) &dst;
1947 clientResponse.resJSONPayload = NULL;
1949 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1950 &cbNode->token, &clientResponse, NULL);
1951 if(result != OC_STACK_OK)
1956 // Increment the TTLLevel (going to a next state), so we don't keep
1957 // sending presence notification to client.
1958 cbNode->presence->TTLlevel++;
1959 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1960 cbNode->presence->TTLlevel);
1964 result = OC_STACK_INVALID_IP;
1968 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1969 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1971 FindAndDeleteClientCB(cbNode);
1975 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1977 CAResult_t caResult;
1978 CARemoteEndpoint_t* endpoint = NULL;
1979 CAInfo_t requestData;
1980 CARequestInfo_t requestInfo;
1982 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1984 //TODO-CA : Why CA_WIFI alone?
1985 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1988 if (caResult != CA_STATUS_OK)
1990 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1994 memset(&requestData, 0, sizeof(CAInfo_t));
1995 requestData.type = CA_MSG_NONCONFIRM;
1996 requestData.token = cbNode->token;
1998 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1999 requestInfo.method = CA_GET;
2000 requestInfo.info = requestData;
2002 caResult = CASendRequest(endpoint, &requestInfo);
2004 if (caResult != CA_STATUS_OK)
2006 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
2010 cbNode->presence->TTLlevel++;
2011 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
2012 cbNode->presence->TTLlevel);
2018 if (result != OC_STACK_OK)
2020 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
2024 #endif // WITH_PRESENCE
2027 * Called in main loop of OC client or server. Allows low-level processing of
2031 * OC_STACK_OK - no errors
2032 * OC_STACK_ERROR - stack process error
2034 OCStackResult OCProcess()
2036 #ifdef WITH_PRESENCE
2037 OCProcessPresence();
2039 CAHandleRequestResponse();
2044 #ifdef WITH_PRESENCE
2046 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
2047 * presence notifications to clients via multicast. Once this API has been called with a success,
2048 * clients may query for this server's presence and this server's stack will respond via multicast.
2050 * Server can call this function when it comes online for the first time, or when it comes back
2051 * online from offline mode, or when it re enters network.
2053 * @param ttl - Time To Live in seconds
2054 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
2057 * OC_STACK_OK - No errors; Success
2059 OCStackResult OCStartPresence(const uint32_t ttl)
2061 OCChangeResourceProperty(
2062 &(((OCResource *)presenceResource.handle)->resourceProperties),
2067 presenceResource.presenceTTL = ttl;
2070 if(OC_PRESENCE_UNINITIALIZED == presenceState)
2072 OCDevAddr multiCastAddr;
2073 presenceState = OC_PRESENCE_INITIALIZED;
2075 OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
2077 CAAddress_t addressInfo;
2078 strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
2079 addressInfo.IP.port = 5683;
2081 //TODO make sure there is no memory leak here since another copy
2082 //of token is being created inside AddObserver
2083 CAToken_t caToken = NULL;
2084 CAResult_t caResult = CAGenerateToken(&caToken);
2085 if (caResult != CA_STATUS_OK)
2087 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2088 CADestroyToken(caToken);
2089 return OC_STACK_ERROR;
2092 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
2093 &multiCastAddr, (OCResource *)presenceResource.handle, OC_LOW_QOS,
2094 &addressInfo, CA_WIFI);
2097 // Each time OCStartPresence is called
2098 // a different random 32-bit integer number is used
2099 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2101 return SendPresenceNotification(NULL);
2105 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
2106 * presence notifications to clients via multicast. Once this API has been called with a success,
2107 * this server's stack will not respond to clients querying for this server's presence.
2109 * Server can call this function when it is terminating, going offline, or when going
2110 * away from network.
2113 * OC_STACK_OK - No errors; Success
2115 OCStackResult OCStopPresence()
2117 OCStackResult result = OC_STACK_ERROR;
2118 //make resource inactive
2119 result = OCChangeResourceProperty(
2120 &(((OCResource *) presenceResource.handle)->resourceProperties),
2122 result = SendPresenceNotification(NULL);
2129 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
2131 defaultDeviceHandler = entityHandler;
2136 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2138 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
2140 if(myStackMode == OC_CLIENT)
2142 return OC_STACK_ERROR;
2145 return SaveDeviceInfo(deviceInfo);
2151 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2152 * Used to refer to resource
2153 * @param resourceTypeName - name of resource type. Example: "core.led"
2154 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2155 * @param uri - URI of the resource. Example: "/a/led"
2156 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2157 * NULL for default entity handler
2158 * @param resourceProperties - properties supported by resource.
2159 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2162 * OC_STACK_OK - no errors
2163 * OC_STACK_ERROR - stack process error
2165 OCStackResult OCCreateResource(OCResourceHandle *handle,
2166 const char *resourceTypeName,
2167 const char *resourceInterfaceName,
2168 const char *uri, OCEntityHandler entityHandler,
2169 uint8_t resourceProperties) {
2171 OCResource *pointer = NULL;
2174 OCStackResult result = OC_STACK_ERROR;
2176 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
2178 if(myStackMode == OC_CLIENT)
2182 // Validate parameters
2183 if(!uri || (strlen(uri) == 0))
2185 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
2186 return OC_STACK_INVALID_URI;
2188 // Is it presented during resource discovery?
2189 if (!handle || !resourceTypeName) {
2190 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
2191 return OC_STACK_INVALID_PARAM;
2194 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
2195 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2198 // Make sure resourceProperties bitmask has allowed properties specified
2199 if (resourceProperties
2200 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
2201 OC_LOG(ERROR, TAG, PCF("Invalid property"));
2202 return OC_STACK_INVALID_PARAM;
2205 // If the headResource is NULL, then no resources have been created...
2206 pointer = headResource;
2208 // At least one resources is in the resource list, so we need to search for
2209 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2211 if (strcmp(uri, pointer->uri) == 0) {
2212 OC_LOG(ERROR, TAG, PCF("URI already in use"));
2213 return OC_STACK_INVALID_PARAM;
2215 pointer = pointer->next;
2218 // Create the pointer and insert it into the resource list
2219 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
2223 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2225 insertResource(pointer);
2228 size = strlen(uri) + 1;
2229 str = (char *) OCMalloc(size);
2233 strncpy(str, uri, size);
2236 // Set properties. Set OC_ACTIVE
2237 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2240 // Add the resourcetype to the resource
2241 result = BindResourceTypeToResource(pointer, resourceTypeName);
2242 if (result != OC_STACK_OK) {
2243 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2247 // Add the resourceinterface to the resource
2248 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2249 if (result != OC_STACK_OK) {
2250 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2254 // If an entity handler has been passed, attach it to the newly created
2255 // resource. Otherwise, set the default entity handler.
2258 pointer->entityHandler = entityHandler;
2262 pointer->entityHandler = defaultResourceEHandler;
2266 result = OC_STACK_OK;
2268 #ifdef WITH_PRESENCE
2269 if(presenceResource.handle)
2271 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2272 SendPresenceNotification(pointer->rsrcType);
2276 if (result != OC_STACK_OK)
2278 // Deep delete of resource and other dynamic elements that it contains
2279 deleteResource(pointer);
2288 * Create a resource. with host ip address for remote resource
2290 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2291 * Used to refer to resource
2292 * @param resourceTypeName - name of resource type. Example: "core.led"
2293 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2294 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2295 * @param uri - URI of the resource. Example: "/a/led"
2296 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2297 * NULL for default entity handler
2298 * @param resourceProperties - properties supported by resource.
2299 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2302 * OC_STACK_OK - no errors
2303 * OC_STACK_ERROR - stack process error
2306 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2307 const char *resourceTypeName,
2308 const char *resourceInterfaceName,
2311 OCEntityHandler entityHandler,
2312 uint8_t resourceProperties)
2316 OCStackResult result = OC_STACK_ERROR;
2318 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2319 uri, entityHandler, resourceProperties);
2321 if (result != OC_STACK_ERROR)
2324 size = strlen(host) + 1;
2325 str = (char *) OCMalloc(size);
2328 return OC_STACK_ERROR;
2330 strncpy(str, host, size);
2331 ((OCResource *) *handle)->host = str;
2338 * Add a resource to a collection resource.
2340 * @param collectionHandle - handle to the collection resource
2341 * @param resourceHandle - handle to resource to be added to the collection resource
2344 * OC_STACK_OK - no errors
2345 * OC_STACK_ERROR - stack process error
2346 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2348 OCStackResult OCBindResource(
2349 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2350 OCResource *resource;
2353 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2355 // Validate parameters
2356 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2357 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2358 // Container cannot contain itself
2359 if (collectionHandle == resourceHandle) {
2360 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2361 return OC_STACK_INVALID_PARAM;
2364 // Use the handle to find the resource in the resource linked list
2365 resource = findResource((OCResource *) collectionHandle);
2367 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2368 return OC_STACK_INVALID_PARAM;
2371 // Look for an open slot to add add the child resource.
2372 // If found, add it and return success
2373 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2374 if (!resource->rsrcResources[i]) {
2375 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2376 OC_LOG(INFO, TAG, PCF("resource bound"));
2381 #ifdef WITH_PRESENCE
2382 if(presenceResource.handle)
2384 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2385 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2389 // Unable to add resourceHandle, so return error
2390 return OC_STACK_ERROR;
2394 * Remove a resource from a collection resource.
2396 * @param collectionHandle - handle to the collection resource
2397 * @param resourceHandle - handle to resource to be added to the collection resource
2400 * OC_STACK_OK - no errors
2401 * OC_STACK_ERROR - stack process error
2402 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2404 OCStackResult OCUnBindResource(
2405 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2406 OCResource *resource;
2409 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2411 // Validate parameters
2412 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2413 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2414 // Container cannot contain itself
2415 if (collectionHandle == resourceHandle) {
2416 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2417 return OC_STACK_INVALID_PARAM;
2420 // Use the handle to find the resource in the resource linked list
2421 resource = findResource((OCResource *) collectionHandle);
2423 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2424 return OC_STACK_INVALID_PARAM;
2427 // Look for an open slot to add add the child resource.
2428 // If found, add it and return success
2429 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2430 if (resourceHandle == resource->rsrcResources[i]) {
2431 resource->rsrcResources[i] = (OCResource *) NULL;
2432 OC_LOG(INFO, TAG, PCF("resource unbound"));
2437 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2439 #ifdef WITH_PRESENCE
2440 if(presenceResource.handle)
2442 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2443 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2447 // Unable to add resourceHandle, so return error
2448 return OC_STACK_ERROR;
2451 OCStackResult BindResourceTypeToResource(OCResource* resource,
2452 const char *resourceTypeName)
2454 OCResourceType *pointer = NULL;
2457 OCStackResult result = OC_STACK_ERROR;
2459 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2461 // Validate parameters
2462 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2463 // TODO: Does resource attribute resentation really have to be maintained in stack?
2464 // Is it presented during resource discovery?
2466 //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2468 // Create the resourcetype and insert it into the resource list
2469 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2474 // Set the resourceTypeName
2475 size = strlen(resourceTypeName) + 1;
2476 str = (char *) OCMalloc(size);
2480 strncpy(str, resourceTypeName, size);
2481 pointer->resourcetypename = str;
2483 insertResourceType(resource, pointer);
2484 result = OC_STACK_OK;
2486 exit: if (result != OC_STACK_OK) {
2494 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2495 const char *resourceInterfaceName)
2497 OCResourceInterface *pointer = NULL;
2500 OCStackResult result = OC_STACK_ERROR;
2502 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2504 // Validate parameters
2505 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2507 //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2509 // Create the resourceinterface and insert it into the resource list
2510 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2515 // Set the resourceinterface name
2516 size = strlen(resourceInterfaceName) + 1;
2517 str = (char *) OCMalloc(size);
2521 strncpy(str, resourceInterfaceName, size);
2522 pointer->name = str;
2524 // Bind the resourceinterface to the resource
2525 insertResourceInterface(resource, pointer);
2527 result = OC_STACK_OK;
2529 exit: if (result != OC_STACK_OK) {
2538 * Bind a resourcetype to a resource.
2540 * @param handle - handle to the resource
2541 * @param resourceTypeName - name of resource type. Example: "core.led"
2544 * OC_STACK_OK - no errors
2545 * OC_STACK_ERROR - stack process error
2547 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2548 const char *resourceTypeName) {
2550 OCStackResult result = OC_STACK_ERROR;
2551 OCResource *resource;
2553 // Make sure resource exists
2554 resource = findResource((OCResource *) handle);
2556 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2557 return OC_STACK_ERROR;
2560 // call internal function
2561 result = BindResourceTypeToResource(resource, resourceTypeName);
2563 #ifdef WITH_PRESENCE
2564 if(presenceResource.handle)
2566 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2567 SendPresenceNotification(resource->rsrcType);
2575 * Bind a resourceinterface to a resource.
2577 * @param handle - handle to the resource
2578 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2581 * OC_STACK_OK - no errors
2582 * OC_STACK_ERROR - stack process error
2585 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2586 const char *resourceInterfaceName) {
2588 OCStackResult result = OC_STACK_ERROR;
2589 OCResource *resource;
2591 // Make sure resource exists
2592 resource = findResource((OCResource *) handle);
2594 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2595 return OC_STACK_ERROR;
2598 // call internal function
2599 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2601 #ifdef WITH_PRESENCE
2602 if(presenceResource.handle)
2604 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2605 SendPresenceNotification(resource->rsrcType);
2613 * Get the number of resources that have been created in the stack.
2615 * @param numResources - pointer to count variable
2618 * OC_STACK_OK - no errors
2619 * OC_STACK_ERROR - stack process error
2622 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2623 OCResource *pointer = headResource;
2625 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2626 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2629 *numResources = *numResources + 1;
2630 pointer = pointer->next;
2636 * Get a resource handle by index.
2638 * @param index - index of resource, 0 to Count - 1
2641 * Resource handle - if found
2642 * NULL - if not found
2644 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2645 OCResource *pointer = headResource;
2648 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2650 // Iterate through the list
2651 while ((i < index) && pointer) {
2653 pointer = pointer->next;
2655 return (OCResourceHandle) pointer;
2659 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2662 * @param handle - handle of resource to be deleted
2665 * OC_STACK_OK - no errors
2666 * OC_STACK_ERROR - stack process error
2667 * OC_STACK_NO_RESOURCE - resource not found
2668 * OC_STACK_INVALID_PARAM - invalid param
2670 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2671 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2674 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2675 return OC_STACK_INVALID_PARAM;
2678 OCResource *resource = findResource((OCResource *) handle);
2679 if (resource == NULL) {
2680 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2681 return OC_STACK_NO_RESOURCE;
2684 if (deleteResource((OCResource *) handle) == 0) {
2685 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2686 return OC_STACK_ERROR;
2693 * Get the URI of the resource specified by handle.
2695 * @param handle - handle of resource
2697 * URI string - if resource found
2698 * NULL - resource not found
2700 const char *OCGetResourceUri(OCResourceHandle handle) {
2701 OCResource *resource;
2702 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2704 resource = findResource((OCResource *) handle);
2706 return resource->uri;
2708 return (const char *) NULL;
2712 * Get the properties of the resource specified by handle.
2713 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2714 * for the resource by the stack.
2716 * @param handle - handle of resource
2718 * property bitmap - if resource found
2719 * NULL - resource not found
2721 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2722 OCResource *resource;
2723 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2725 resource = findResource((OCResource *) handle);
2727 return resource->resourceProperties;
2733 * Get the number of resource types of the resource.
2735 * @param handle - handle of resource
2736 * @param numResourceTypes - pointer to count variable
2739 * OC_STACK_OK - no errors
2740 * OC_STACK_ERROR - stack process error
2742 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2743 uint8_t *numResourceTypes) {
2744 OCResource *resource;
2745 OCResourceType *pointer;
2747 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2748 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2749 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2751 *numResourceTypes = 0;
2753 resource = findResource((OCResource *) handle);
2755 pointer = resource->rsrcType;
2757 *numResourceTypes = *numResourceTypes + 1;
2758 pointer = pointer->next;
2765 * Get name of resource type of the resource.
2767 * @param handle - handle of resource
2768 * @param index - index of resource, 0 to Count - 1
2771 * resource type name - if resource found
2772 * NULL - resource not found
2774 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2775 OCResourceType *resourceType;
2777 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2779 resourceType = findResourceTypeAtIndex(handle, index);
2781 return resourceType->resourcetypename;
2783 return (const char *) NULL;
2789 * Get the number of resource interfaces of the resource.
2791 * @param handle - handle of resource
2792 * @param numResources - pointer to count variable
2795 * OC_STACK_OK - no errors
2796 * OC_STACK_ERROR - stack process error
2798 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2799 uint8_t *numResourceInterfaces) {
2800 OCResourceInterface *pointer;
2801 OCResource *resource;
2803 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2805 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2806 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2808 *numResourceInterfaces = 0;
2809 resource = findResource((OCResource *) handle);
2811 pointer = resource->rsrcInterface;
2813 *numResourceInterfaces = *numResourceInterfaces + 1;
2814 pointer = pointer->next;
2821 * Get name of resource interface of the resource.
2823 * @param handle - handle of resource
2824 * @param index - index of resource, 0 to Count - 1
2827 * resource interface name - if resource found
2828 * NULL - resource not found
2830 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2831 OCResourceInterface *resourceInterface;
2833 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2835 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2836 if (resourceInterface) {
2837 return resourceInterface->name;
2839 return (const char *) NULL;
2843 * Get resource handle from the collection resource by index.
2845 * @param collectionHandle - handle of collection resource
2846 * @param index - index of contained resource, 0 to Count - 1
2849 * handle to resource - if resource found
2850 * NULL - resource not found
2852 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2854 OCResource *resource;
2856 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2858 if (index >= MAX_CONTAINED_RESOURCES) {
2862 resource = findResource((OCResource *) collectionHandle);
2867 return resource->rsrcResources[index];
2871 * Bind an entity handler to the resource.
2873 * @param handle - handle to the resource that the contained resource is to be bound
2874 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2876 * OC_STACK_OK - no errors
2877 * OC_STACK_ERROR - stack process error
2879 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2880 OCEntityHandler entityHandler) {
2881 OCResource *resource;
2883 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2885 // Validate parameters
2886 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2887 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2889 // Use the handle to find the resource in the resource linked list
2890 resource = findResource((OCResource *)handle);
2892 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2893 return OC_STACK_ERROR;
2897 resource->entityHandler = entityHandler;
2899 #ifdef WITH_PRESENCE
2900 if(presenceResource.handle)
2902 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2903 SendPresenceNotification(resource->rsrcType);
2911 * Get the entity handler for a resource.
2913 * @param handle - handle of resource
2916 * entity handler - if resource found
2917 * NULL - resource not found
2919 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2920 OCResource *resource;
2922 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2924 // Use the handle to find the resource in the resource linked list
2925 resource = findResource((OCResource *)handle);
2927 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2932 return resource->entityHandler;
2935 void incrementSequenceNumber(OCResource * resPtr)
2937 // Increment the sequence number
2938 resPtr->sequenceNum += 1;
2939 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2941 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2947 * Notify Presence subscribers that a resource has been modified
2949 * @param resourceType - Handle to the resourceType linked list of resource
2950 * that was modified.
2951 * @param qos - Quality Of Service
2954 #ifdef WITH_PRESENCE
2955 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2957 OCResource *resPtr = NULL;
2958 OCStackResult result;
2959 OCMethod method = OC_REST_PRESENCE;
2960 uint32_t maxAge = 0;
2961 resPtr = findResource((OCResource *) presenceResource.handle);
2964 return OC_STACK_NO_RESOURCE;
2966 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2968 maxAge = presenceResource.presenceTTL;
2975 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2979 #endif // WITH_PRESENCE
2981 * Notify observers that an observed value has changed.
2983 * @param handle - handle of resource
2986 * OC_STACK_OK - no errors
2987 * OC_STACK_NO_RESOURCE - invalid resource handle
2988 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2990 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
2992 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2994 OCResource *resPtr = NULL;
2995 OCStackResult result;
2996 OCMethod method = OC_REST_NOMETHOD;
2997 uint32_t maxAge = 0;
2999 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
3000 #ifdef WITH_PRESENCE
3001 if(handle == presenceResource.handle)
3005 #endif // WITH_PRESENCE
3006 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3008 // Verify that the resource exists
3009 resPtr = findResource ((OCResource *) handle);
3012 return OC_STACK_NO_RESOURCE;
3016 //only increment in the case of regular observing (not presence)
3017 incrementSequenceNumber(resPtr);
3018 method = OC_REST_OBSERVE;
3019 maxAge = MAX_OBSERVE_AGE;
3020 #ifdef WITH_PRESENCE
3021 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
3023 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3030 OCNotifyListOfObservers (OCResourceHandle handle,
3031 OCObservationId *obsIdList,
3032 uint8_t numberOfIds,
3033 unsigned char *notificationJSONPayload,
3034 OCQualityOfService qos)
3036 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
3038 OCResource *resPtr = NULL;
3039 //TODO: we should allow the server to define this
3040 uint32_t maxAge = MAX_OBSERVE_AGE;
3042 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3043 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3044 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
3046 // Verify that the resource exists
3047 resPtr = findResource ((OCResource *) handle);
3048 if (NULL == resPtr || myStackMode == OC_CLIENT)
3050 return OC_STACK_NO_RESOURCE;
3054 incrementSequenceNumber(resPtr);
3056 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3057 notificationJSONPayload, maxAge, qos));
3061 * Send a response to a request.
3062 * The response can be a regular, slow, or block (i.e. a response that
3063 * is too large to be sent in a single PDU and must span multiple transmissions)
3065 * @param response - pointer to structure that contains response parameters
3068 * OC_STACK_OK - No errors; Success
3069 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
3070 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
3071 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
3072 * persistent response buffer is necessary
3074 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3076 OCStackResult result = OC_STACK_ERROR;
3077 OCServerRequest *serverRequest = NULL;
3079 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
3081 // Validate input parameters
3082 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3083 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3085 // TODO: Placeholder for creating a response entry when implementing
3086 // block transfer feature
3088 // If a response payload is present, check if block transfer is required
3089 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
3090 (const char *)ehResponse->payload, ehResponse->payloadSize))
3092 OC_LOG(INFO, TAG, PCF("Block transfer required"));
3094 // Persistent response buffer is needed for block transfer
3095 if (!ehResponse->persistentBufferFlag)
3097 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
3098 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
3100 // TODO: Placeholder for block transfer handling
3101 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
3102 // when implementing the block transfer feature
3107 // Get pointer to request info
3108 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3111 result = serverRequest->ehResponseHandler(ehResponse);
3118 * Cancel a response. Applies to a block response
3120 * @param responseHandle - response handle set by stack in OCServerResponse after
3121 * OCDoResponse is called
3124 * OC_STACK_OK - No errors; Success
3125 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
3127 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
3129 OCStackResult result = OC_STACK_NOTIMPL;
3131 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
3133 // TODO: validate response handle
3138 //-----------------------------------------------------------------------------
3139 // Private internal function definitions
3140 //-----------------------------------------------------------------------------
3142 * Generate handle of OCDoResource invocation for callback management.
3144 static OCDoHandle GenerateInvocationHandle()
3146 OCDoHandle handle = NULL;
3147 // Generate token here, it will be deleted when the transaction is deleted
3148 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3151 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3156 #ifdef WITH_PRESENCE
3157 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3158 OCResourceProperty resourceProperties, uint8_t enable)
3160 if (resourceProperties
3161 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
3162 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3163 return OC_STACK_INVALID_PARAM;
3167 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3171 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3178 * Initialize resource data structures, variables, etc.
3180 OCStackResult initResources() {
3181 OCStackResult result = OC_STACK_OK;
3182 // Init application resource vars
3183 headResource = NULL;
3184 // Init Virtual Resources
3185 #ifdef WITH_PRESENCE
3186 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3187 //presenceResource.token = OCGenerateCoAPToken();
3188 result = OCCreateResource(&presenceResource.handle,
3189 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3194 //make resource inactive
3195 result = OCChangeResourceProperty(
3196 &(((OCResource *) presenceResource.handle)->resourceProperties),
3203 * Add a resource to the end of the linked list of resources.
3205 * @param resource - resource to be added
3207 void insertResource(OCResource *resource) {
3208 OCResource *pointer;
3210 if (!headResource) {
3211 headResource = resource;
3213 pointer = headResource;
3215 while (pointer->next) {
3216 pointer = pointer->next;
3218 pointer->next = resource;
3220 resource->next = NULL;
3224 * Find a resource in the linked list of resources.
3226 * @param resource - resource to be found
3228 * NULL - resource not found
3229 * pointer to resource - pointer to resource that was found in the linked list
3231 OCResource *findResource(OCResource *resource) {
3232 OCResource *pointer = headResource;
3235 if (pointer == resource) {
3238 pointer = pointer->next;
3243 void deleteAllResources()
3245 OCResource *pointer = headResource;
3250 temp = pointer->next;
3251 #ifdef WITH_PRESENCE
3252 if(pointer != (OCResource *) presenceResource.handle)
3254 #endif // WITH_PRESENCE
3255 deleteResource(pointer);
3256 #ifdef WITH_PRESENCE
3258 #endif // WITH_PRESENCE
3262 #ifdef WITH_PRESENCE
3263 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3264 // presence notification attributed to their deletion to be processed.
3265 deleteResource((OCResource *) presenceResource.handle);
3266 #endif // WITH_PRESENCE
3270 * Delete the resource from the linked list.
3272 * @param resource - resource to be deleted
3277 int deleteResource(OCResource *resource) {
3278 OCResource *prev = NULL;
3281 temp = headResource;
3283 if (temp == resource) {
3284 // Invalidate all Resource Properties.
3285 resource->resourceProperties = (OCResourceProperty) 0;
3286 #ifdef WITH_PRESENCE
3287 if(resource != (OCResource *) presenceResource.handle)
3289 #endif // WITH_PRESENCE
3290 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3291 #ifdef WITH_PRESENCE
3294 if(presenceResource.handle)
3296 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3297 if(resource != (OCResource *) presenceResource.handle)
3299 SendPresenceNotification(resource->rsrcType);
3303 SendPresenceNotification(NULL);
3308 if (temp == headResource) {
3309 headResource = temp->next;
3311 prev->next = temp->next;
3314 deleteResourceElements(temp);
3327 * Delete all of the dynamically allocated elements that were created for the resource.
3329 * @param resource - specified resource
3331 void deleteResourceElements(OCResource *resource) {
3337 OCFree(resource->uri);
3339 // Delete resourcetype linked list
3340 deleteResourceType(resource->rsrcType);
3342 // Delete resourceinterface linked list
3343 deleteResourceInterface(resource->rsrcInterface);
3347 * Delete all of the dynamically allocated elements that were created for the resource type.
3349 * @param resourceType - specified resource type
3351 void deleteResourceType(OCResourceType *resourceType) {
3352 OCResourceType *pointer = resourceType;
3353 OCResourceType *next;
3356 next = pointer->next;
3357 OCFree(pointer->resourcetypename);
3364 * Delete all of the dynamically allocated elements that were created for the resource interface.
3366 * @param resourceInterface - specified resource interface
3368 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
3369 OCResourceInterface *pointer = resourceInterface;
3370 OCResourceInterface *next;
3373 next = pointer->next;
3374 OCFree(pointer->name);
3381 * Insert a resource type into a resource's resource type linked list.
3383 * @param resource - resource where resource type is to be inserted
3384 * @param resourceType - resource type to be inserted
3386 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
3387 OCResourceType *pointer;
3389 if (resource && !resource->rsrcType) {
3390 resource->rsrcType = resourceType;
3394 pointer = resource->rsrcType;
3398 pointer = resourceType;
3400 while (pointer->next) {
3401 pointer = pointer->next;
3403 pointer->next = resourceType;
3405 resourceType->next = NULL;
3409 * Get a resource type at the specified index within a resource.
3411 * @param handle - handle of resource
3412 * @param index - index of resource type
3415 * resourcetype - if found
3418 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
3419 OCResource *resource;
3420 OCResourceType *pointer;
3423 // Find the specified resource
3424 resource = findResource((OCResource *) handle);
3429 // Make sure a resource has a resourcetype
3430 if (!resource->rsrcType) {
3434 // Iterate through the list
3435 pointer = resource->rsrcType;
3437 while ((i < index) && pointer) {
3439 pointer = pointer->next;
3445 * Finds a resource type in an OCResourceType link-list.
3447 * @param resourceTypeList - the link-list to be searched through
3448 * @param resourceTypeName - the key to search for
3451 * resourceType that matches the key (ie. resourceTypeName)
3452 * NULL - either an invalid parameter or this function was unable to find the key.
3454 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3456 if(resourceTypeList && resourceTypeName)
3458 OCResourceType * rtPointer = resourceTypeList;
3459 while(resourceTypeName && rtPointer)
3461 if(rtPointer->resourcetypename &&
3462 strcmp(resourceTypeName, (const char *)
3463 (rtPointer->resourcetypename)) == 0)
3467 rtPointer = rtPointer->next;
3474 * Insert a resource interface into a resource's resource interface linked list.
3476 * @param resource - resource where resource interface is to be inserted
3477 * @param resourceInterface - resource interface to be inserted
3479 void insertResourceInterface(OCResource *resource,
3480 OCResourceInterface *resourceInterface) {
3481 OCResourceInterface *pointer;
3483 if (!resource->rsrcInterface) {
3484 resource->rsrcInterface = resourceInterface;
3486 pointer = resource->rsrcInterface;
3487 while (pointer->next) {
3488 pointer = pointer->next;
3490 pointer->next = resourceInterface;
3492 resourceInterface->next = NULL;
3496 * Get a resource interface at the specified index within a resource.
3498 * @param handle - handle of resource
3499 * @param index - index of resource interface
3502 * resourceinterface - if found
3505 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3507 OCResource *resource;
3508 OCResourceInterface *pointer;
3511 // Find the specified resource
3512 resource = findResource((OCResource *) handle);
3517 // Make sure a resource has a resourceinterface
3518 if (!resource->rsrcInterface) {
3522 // Iterate through the list
3523 pointer = resource->rsrcInterface;
3525 while ((i < index) && pointer) {
3527 pointer = pointer->next;
3533 * Determine if a request/response must be sent in a block transfer because it is too large to be
3534 * sent in a single PDU. This function can be used for either a request or a response
3536 * @param request - NULL or pointer to request
3537 * @param response - NULL or pointer to response
3538 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3539 * the length of the request/response
3542 * 0 - packet transfer NOT required (i.e. normal request/response)
3543 * 1 - packet transfer required (i.e. block transfer needed)
3545 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3549 // Determine if we are checking a request or a response
3552 // If size is greater than 0, use it for the request size value, otherwise
3553 // assume request is null terminated and use strlen for size value
3554 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3561 // If size is greater than 0, use it for the response size value, otherwise
3562 // assume response is null terminated and use strlen for size value
3563 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3572 * Retrieves a resource type based upon a query ontains only just one
3573 * resource attribute (and that has to be of type "rt").
3575 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3576 * before passing in.
3578 * @param query - The quert part of the URI
3579 * @param resourceType - The resource type to be populated; pass by reference.
3582 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3583 * OC_STACK_OK - Success
3585 OCStackResult getResourceType(const char * query, unsigned char** resourceType)
3589 return OC_STACK_INVALID_PARAM;
3592 OCStackResult result = OC_STACK_ERROR;
3594 if(strncmp(query, "rt=", 3) == 0)
3596 *resourceType = (unsigned char *) OCMalloc(strlen(query)-3);
3599 result = OC_STACK_NO_MEMORY;
3602 strcpy((char *)*resourceType, ((const char *)&query[3]));
3603 result = OC_STACK_OK;
3609 OCStackResult getQueryFromUri(const char * uri, unsigned char** query, char ** newURI)
3613 return OC_STACK_INVALID_URI;
3615 if(!query || !newURI)
3617 return OC_STACK_INVALID_PARAM;
3619 char * leftToken = NULL;
3620 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3625 strcpy(tempURI, uri);
3627 leftToken = strtok_r((char *)tempURI, "?", &strTokPtr);
3629 //TODO-CA: This could be simplified. Clean up required.
3630 while(leftToken != NULL)
3632 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3634 *query = (unsigned char *) OCMalloc(strlen(leftToken) + 1);
3640 strcpy((char *)*query, ((const char *)&leftToken[0]));
3643 leftToken = strtok_r(NULL, "?", &strTokPtr);
3651 return OC_STACK_NO_MEMORY;
3654 const ServerID OCGetServerInstanceID(void)
3656 static bool generated = false;
3657 static ServerID sid;
3664 sid = OCGetRandom();
3669 const char* OCGetServerInstanceIDString(void)
3671 // max printed length of a base 10
3672 // uint32 is 10 characters, so 11 includes null.
3673 // This will change as the representation gets switched
3675 static char buffer[11];
3676 int n = sprintf(buffer, "%u", OCGetServerInstanceID());