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, ClientCB * cbNode, uint32_t maxAge,
109 unsigned char * fullUri, unsigned char * rcvdUri, CAToken_t * rcvdToken,
110 OCClientResponse * clientResponse, unsigned char * bufRes)
112 OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
115 return OC_STACK_NO_MEMORY;
117 response->cbNode = cbNode;
118 response->maxAge = maxAge;
119 response->fullUri = fullUri;
120 response->rcvdUri = rcvdUri;
121 response->rcvdToken = rcvdToken;
122 response->clientResponse = clientResponse;
123 response->bufRes = bufRes;
125 *responseLoc = response;
129 //-----------------------------------------------------------------------------
130 // Internal API function
131 //-----------------------------------------------------------------------------
133 // This internal function is called to update the stack with the status of
134 // observers and communication failures
135 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
137 OCStackResult result = OC_STACK_ERROR;
138 ResourceObserver * observer = NULL;
139 OCEntityHandlerRequest ehRequest = {0};
143 case OC_OBSERVER_NOT_INTERESTED:
144 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
145 observer = GetObserverUsingToken (token);
148 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
149 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
150 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
151 if(result != OC_STACK_OK)
155 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
157 //observer is not observing anymore
158 result = DeleteObserverUsingToken (token);
159 if(result == OC_STACK_OK)
161 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
165 result = OC_STACK_OK;
166 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
169 case OC_OBSERVER_STILL_INTERESTED:
170 //observer is still interested
171 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
172 notifications, reset the failedCount"));
173 observer = GetObserverUsingToken (token);
176 observer->forceHighQos = 0;
177 observer->failedCommCount = 0;
178 result = OC_STACK_OK;
182 result = OC_STACK_OBSERVER_NOT_FOUND;
185 case OC_OBSERVER_FAILED_COMM:
186 //observer is not reachable
187 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
188 observer = GetObserverUsingToken (token);
191 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
193 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
194 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
195 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
196 if(result != OC_STACK_OK)
198 return OC_STACK_ERROR;
200 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
201 //observer is unreachable
202 result = DeleteObserverUsingToken (token);
203 if(result == OC_STACK_OK)
205 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
209 result = OC_STACK_OK;
210 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
215 observer->failedCommCount++;
216 result = OC_STACK_CONTINUE;
218 observer->forceHighQos = 1;
219 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
223 OC_LOG(ERROR, TAG, PCF("Unknown status"));
224 result = OC_STACK_ERROR;
230 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
232 OCStackResult ret = OC_STACK_ERROR;
240 ret = OC_STACK_RESOURCE_CREATED;
243 ret = OC_STACK_RESOURCE_DELETED;
246 ret = OC_STACK_INVALID_QUERY;
249 ret = OC_STACK_INVALID_OPTION;
252 ret = OC_STACK_NO_RESOURCE;
260 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
262 OCStackResult ret = OC_STACK_OK;
267 *caConType = CA_ETHERNET;
270 *caConType = CA_WIFI;
279 // Currently OC_ALL represents WIFI and ETHERNET
280 // Add other connectivity types as they are enabled in future
281 *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
284 ret = OC_STACK_INVALID_PARAM;
290 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
292 OCStackResult ret = OC_STACK_OK;
297 *ocConType = OC_ETHERNET;
300 *ocConType = OC_WIFI;
309 ret = OC_STACK_INVALID_PARAM;
315 // update response.addr appropriately from endPoint.addressInfo
316 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
318 OCStackResult ret = OC_STACK_ERROR;
319 static OCDevAddr address = {0};
321 char * savePtr = NULL;
322 char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
325 ret = OC_STACK_NO_MEMORY;
328 memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
329 strlen(endPoint->addressInfo.IP.ipAddress) + 1);
331 // Grabs the first three numbers from the IPv4 address and replaces dots
332 for(int i=0; i<4; i++)
334 tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
338 ret = OC_STACK_ERROR;
341 address.addr[i] = atoi(tok);
344 memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
348 response->addr = &address;
349 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
353 OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
360 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
364 // The format of the payload is {"oc":[%u:%u:%s]}
365 // %u : sequence number,
367 // %s : Resource Type (Optional)
368 tok = strtok_r(payload, "[:]}", &savePtr);
369 payload[strlen(payload)] = ':';
370 tok = strtok_r(NULL, "[:]}", &savePtr);
371 payload[strlen((char *)payload)] = ':';
372 *seqNum = (uint32_t) atoi(tok);
373 tok = strtok_r(NULL, "[:]}", &savePtr);
374 *maxAge = (uint32_t) atoi(tok);
375 tok = strtok_r(NULL, "[:]}",&savePtr);
379 *resType = (char *)OCMalloc(strlen(tok));
384 payload[strlen((char *)payload)] = ':';
385 strcpy(*resType, tok);
386 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", *resType);
388 payload[strlen((char *)payload)] = ']';
391 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
392 const CAResponseInfo_t* responseInfo)
394 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
395 ClientCB * cbNode = NULL;
396 char *resourceTypeName = NULL;
397 OCClientResponse response;
398 OCStackResult result = OC_STACK_ERROR;
399 uint32_t lowerBound = 0;
400 uint32_t higherBound = 0;
403 char *fullUri = NULL;
404 char *ipAddress = NULL;
405 int presenceSubscribe = 0;
406 int multicastPresenceSubscribe = 0;
408 if (responseInfo->result != CA_SUCCESS)
410 OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
411 return OC_STACK_ERROR;
414 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
418 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
419 result = OC_STACK_NO_MEMORY;
423 ipAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
425 if(NULL == ipAddress)
427 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
428 result = OC_STACK_NO_MEMORY;
432 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress,
433 strlen(endPoint->addressInfo.IP.ipAddress));
434 ipAddress[strlen(endPoint->addressInfo.IP.ipAddress)] = '\0';
436 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
439 cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
443 presenceSubscribe = 1;
447 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
448 cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
451 multicastPresenceSubscribe = 1;
455 if(!presenceSubscribe && !multicastPresenceSubscribe)
457 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
458 ------------ ignoring"));
462 // No payload to the application in case of presence
463 response.resJSONPayload = NULL;
464 response.result = OC_STACK_OK;
466 result = UpdateResponseAddr(&response, endPoint);
467 if(result != OC_STACK_OK)
472 if(responseInfo->info.payload)
474 parsePresencePayload(responseInfo->info.payload,
475 &(response.sequenceNumber),
482 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
483 response.result = OC_STACK_PRESENCE_STOPPED;
486 OCFree(cbNode->presence->timeOut);
487 OCFree(cbNode->presence);
488 cbNode->presence = NULL;
491 else if(presenceSubscribe)
493 if(!cbNode->presence)
495 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
496 VERIFY_NON_NULL_V(cbNode->presence);
497 cbNode->presence->timeOut = NULL;
498 cbNode->presence->timeOut = (uint32_t *)
499 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
500 if(!(cbNode->presence->timeOut)){
501 OCFree(cbNode->presence);
502 result = OC_STACK_NO_MEMORY;
506 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
507 cbNode->presence->TTL = maxAge;
508 for(int index = 0; index < PresenceTimeOutSize; index++)
510 lowerBound = GetTime(((float)(PresenceTimeOut[index])
511 /(float)100)*(float)cbNode->presence->TTL);
512 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
513 /(float)100)*(float)cbNode->presence->TTL);
514 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
515 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
516 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
517 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
518 cbNode->presence->timeOut[index]);
520 cbNode->presence->TTLlevel = 0;
521 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
522 if(cbNode->sequenceNumber == response.sequenceNumber)
524 OC_LOG(INFO, TAG, PCF("===============No presence change"));
527 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
528 cbNode->sequenceNumber = response.sequenceNumber;
530 // Ensure that a filter is actually applied.
531 if(resourceTypeName && cbNode->filterResourceType)
533 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
541 // This is the multicast case
543 OCMulticastNode* mcNode = NULL;
544 mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
548 if(mcNode->nonce == response.sequenceNumber)
550 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
553 mcNode->nonce = response.sequenceNumber;
557 uint32_t uriLen = strlen((char*)fullUri);
558 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
561 memcpy(uri, fullUri, (uriLen + 1));
566 PCF("===============No Memory for URI to store in the presence node"));
567 result = OC_STACK_NO_MEMORY;
570 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, response.sequenceNumber);
571 if(result == OC_STACK_NO_MEMORY)
574 PCF("===============No Memory for Multicast Presence Node"));
575 result = OC_STACK_NO_MEMORY;
580 // Ensure that a filter is actually applied.
581 if(resourceTypeName && cbNode->filterResourceType)
583 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
590 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
592 if (cbResult == OC_STACK_DELETE_TRANSACTION)
594 FindAndDeleteClientCB(cbNode);
600 OCFree(resourceTypeName);
605 //This function will be called back by CA layer when a response is received
606 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
608 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
610 OCStackApplicationResult appResult = OC_STACK_DELETE_TRANSACTION;
614 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
618 if(NULL == responseInfo)
620 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
624 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
626 HandlePresenceResponse(endPoint, responseInfo);
630 ClientCB *cbNode = GetClientCB((CAToken_t *)&(responseInfo->info.token), NULL, NULL);
634 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
635 OCClientResponse response;
637 OCStackResult result = UpdateResponseAddr(&response, endPoint);
638 if(result != OC_STACK_OK)
640 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
644 response.result = CAToOCStackResult(responseInfo->result);
645 response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
646 response.numRcvdVendorSpecificHeaderOptions = 0;
647 if(responseInfo->info.numOptions > 0)
650 //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
651 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
653 memcpy (&(response.sequenceNumber),
654 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
655 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
660 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
663 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
665 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
669 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
671 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
672 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
675 appResult = cbNode->callBack(cbNode->context,
676 cbNode->handle, &response);
677 if (appResult == OC_STACK_DELETE_TRANSACTION)
679 FindAndDeleteClientCB(cbNode);
682 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
683 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
686 //This function will be called back by CA layer when a request is received
687 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
689 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
692 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
698 OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
702 OCStackResult requestResult = OC_STACK_ERROR;
704 if(myStackMode == OC_CLIENT)
706 //TODO: should the client be responding to requests?
710 OCServerProtocolRequest serverRequest;
712 memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
713 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
715 char * newUri = (char *)endPoint->resourceUri;
716 unsigned char * query = NULL;
717 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
718 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
719 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
721 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
725 memcpy (&(serverRequest.query), query, strlen((char*)query));
727 //copy request payload
728 if (requestInfo->info.payload)
730 serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
731 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
732 strlen(requestInfo->info.payload));
733 serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
737 serverRequest.reqTotalSize = 1;
740 switch (requestInfo->method)
744 serverRequest.method = OC_REST_GET;
749 serverRequest.method = OC_REST_PUT;
754 serverRequest.method = OC_REST_POST;
759 serverRequest.method = OC_REST_DELETE;
764 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
769 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
770 OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
772 serverRequest.requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
774 if (!serverRequest.requestToken)
776 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
779 memset(serverRequest.requestToken, 0, CA_MAX_TOKEN_LEN + 1);
780 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
782 if (requestInfo->info.type == CA_MSG_CONFIRM)
784 serverRequest.qos = OC_HIGH_QOS;
786 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
788 serverRequest.qos = OC_LOW_QOS;
790 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
792 // TODO-CA: Need to handle this
794 else if (requestInfo->info.type == CA_MSG_RESET)
796 // TODO-CA: Need to handle this
798 // CA does not need the following 3 fields
799 serverRequest.coapID = 0;
800 serverRequest.delayedResNeeded = 0;
801 serverRequest.secured = endPoint->isSecured;
804 serverRequest.addressInfo = endPoint->addressInfo;
805 serverRequest.connectivityType = endPoint->connectivityType;
807 // copy vendor specific header options
808 // TODO-CA: CA is including non-vendor header options as well, like observe.
809 // Need to filter those out
810 uint8_t tempNum = (requestInfo->info.numOptions);
811 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
812 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
815 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
818 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
819 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
821 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
822 sizeof(CAHeaderOption_t)*tempNum);
825 requestResult = HandleStackRequests (&serverRequest);
826 if(requestResult != OC_STACK_OK)
828 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
830 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
833 //This function will be called back by occoap layer when a request is received
834 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
836 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
837 OCStackResult result = OC_STACK_ERROR;
838 ResourceHandling resHandling;
839 OCResource *resource;
842 OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
843 return OC_STACK_INVALID_PARAM;
846 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
849 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
850 result = AddServerRequest(&request, protocolRequest->coapID,
851 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
852 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
853 protocolRequest->observationOption, protocolRequest->qos,
854 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
855 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
856 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
857 protocolRequest->reqTotalSize,
858 &protocolRequest->addressInfo, protocolRequest->connectivityType);
859 if (OC_STACK_OK != result)
861 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
864 VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
866 if(!protocolRequest->reqMorePacket)
868 request->requestComplete = 1;
873 OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
876 if(request->requestComplete)
878 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
879 result = DetermineResourceHandling (request, &resHandling, &resource);
880 if (result == OC_STACK_OK)
882 result = ProcessRequest(resHandling, resource, request);
886 result = OC_STACK_ERROR;
891 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
892 result = OC_STACK_CONTINUE;
897 //This function will be called back by occoap layer when a response is received
898 OCStackResult HandleStackResponses(OCResponse * response)
900 OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
901 OCStackResult result = OC_STACK_OK;
902 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
903 uint8_t isObserveNotification = 0;
904 ClientCB * cbNode = NULL;
907 OC_LOG(ERROR, TAG, PCF("response is NULL"));
908 return OC_STACK_INVALID_PARAM;
911 uint8_t isPresenceNotification = 0;
912 uint8_t isMulticastPresence = 0;
913 char * resourceTypeName = NULL;
914 uint32_t lowerBound = 0;
915 uint32_t higherBound = 0;
917 unsigned char * bufRes = response->bufRes;
918 #endif // WITH_PRESENCE
920 cbNode = response->cbNode;
923 cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
926 if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
928 isObserveNotification = 1;
929 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
932 OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
933 response->clientResponse->sequenceNumber);
934 OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
935 OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
938 if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
939 isPresenceNotification = 1;
942 result = OC_STACK_INVALID_PARAM;
946 tok = strtok_r((char *)bufRes, "[:]}", &savePtr);
947 bufRes[strlen((char *)bufRes)] = ':';
948 tok = strtok_r(NULL, "[:]}", &savePtr);
949 bufRes[strlen((char *)bufRes)] = ':';
950 response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
951 OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
952 tok = strtok_r(NULL, "[:]}", &savePtr);
953 response->maxAge = (uint32_t )atoi(tok);
954 OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
955 tok = strtok_r(NULL, "[:]}", &savePtr);
958 resourceTypeName = (char *)OCMalloc(strlen(tok));
959 if(!resourceTypeName)
963 bufRes[strlen((char *)bufRes)] = ':';
964 strcpy(resourceTypeName, tok);
965 OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
968 bufRes[strlen((char *)bufRes)] = ']';
971 // Check if the application subcribed for presence
974 cbNode = GetClientCB(NULL, NULL, response->fullUri);
977 // Check if application subscribed for multicast presence
980 snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
981 OC_MULTICAST_IP, response->rcvdUri);
982 cbNode = GetClientCB(NULL, NULL, response->fullUri);
985 isMulticastPresence = 1;
986 isPresenceNotification = 0;
990 if(cbNode && isPresenceNotification)
992 OC_LOG(INFO, TAG, PCF("Received a presence notification"));
993 if(!cbNode->presence)
995 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
996 VERIFY_NON_NULL_V(cbNode->presence);
997 cbNode->presence->timeOut = NULL;
998 cbNode->presence->timeOut = (uint32_t *)
999 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
1000 if(!(cbNode->presence->timeOut)){
1001 OCFree(cbNode->presence);
1002 result = OC_STACK_NO_MEMORY;
1005 if(response->maxAge == 0)
1007 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
1008 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
1009 if(cbNode->presence)
1011 OCFree(cbNode->presence->timeOut);
1012 OCFree(cbNode->presence);
1013 cbNode->presence = NULL;
1018 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
1019 cbNode->presence->TTL = response->maxAge;
1020 for(int index = 0; index < PresenceTimeOutSize; index++)
1022 lowerBound = GetTime(((float)(PresenceTimeOut[index])
1023 /(float)100)*(float)cbNode->presence->TTL);
1024 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
1025 /(float)100)*(float)cbNode->presence->TTL);
1026 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
1027 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
1028 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
1029 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
1030 cbNode->presence->timeOut[index]);
1032 cbNode->presence->TTLlevel = 0;
1033 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1034 if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
1036 OC_LOG(INFO, TAG, PCF("===============No presence change"));
1039 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
1040 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
1043 // Ensure that a filter is actually applied.
1044 if(resourceTypeName && cbNode->filterResourceType)
1046 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1052 else if(cbNode && isMulticastPresence)
1054 // Check if the same nonce for a given host
1055 OCMulticastNode* mcNode = NULL;
1056 mcNode = GetMCPresenceNode(response->fullUri);
1058 if(response->maxAge == 0)
1060 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
1061 response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
1062 if(cbNode->presence)
1064 OCFree(cbNode->presence->timeOut);
1065 OCFree(cbNode->presence);
1066 cbNode->presence = NULL;
1069 else if(mcNode != NULL)
1071 if(mcNode->nonce == response->clientResponse->sequenceNumber)
1073 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
1074 result = OC_STACK_NO_MEMORY;
1077 mcNode->nonce = response->clientResponse->sequenceNumber;
1081 uint32_t uriLen = strlen((char*)response->fullUri);
1082 unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
1085 memcpy(uri, response->fullUri, (uriLen + 1));
1090 PCF("===============No Memory for URI to store in the presence node"));
1091 result = OC_STACK_NO_MEMORY;
1094 result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
1095 response->clientResponse->sequenceNumber);
1096 if(result == OC_STACK_NO_MEMORY)
1099 PCF("===============No Memory for Multicast Presence Node"));
1100 result = OC_STACK_NO_MEMORY;
1105 // Ensure that a filter is actually applied.
1106 if(resourceTypeName && cbNode->filterResourceType)
1108 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1115 else if(!cbNode && isPresenceNotification)
1117 OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
1118 ------------ ignoring"));
1120 #endif // WITH_PRESENCE
1124 if(isObserveNotification)
1126 OC_LOG(INFO, TAG, PCF("Received an observe notification"));
1127 //TODO: check the standard for methods to detect wrap around condition
1128 if(cbNode->method == OC_REST_OBSERVE &&
1129 (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
1130 (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
1131 response->clientResponse->sequenceNumber ==
1132 MAX_SEQUENCE_NUMBER)))
1134 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
1135 Ignoring Incoming:%d Against Current:%d.",
1136 response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
1139 if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
1140 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
1144 response->clientResponse->resJSONPayload = bufRes;
1146 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
1148 if (cbResult == OC_STACK_DELETE_TRANSACTION ||
1149 response->clientResponse->result == OC_STACK_COMM_ERROR ||
1150 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
1151 !isPresenceNotification && !isMulticastPresence))
1153 FindAndDeleteClientCB(cbNode);
1158 result = OC_STACK_ERROR;
1162 #ifdef WITH_PRESENCE
1163 OCFree(resourceTypeName);
1168 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
1171 unsigned char *itr, *coap;
1172 uint8_t dotCount = 0;
1176 /* search for scheme */
1178 if (!isdigit((unsigned char) *ipAddrStr))
1180 coap = (unsigned char *) OC_COAP_SCHEME;
1181 while (*coap && tolower(*itr) == *coap)
1189 while (*ipAddrStr) {
1190 if (isdigit((unsigned char) *ipAddrStr))
1192 ipAddr[index] *= 10;
1193 ipAddr[index] += *ipAddrStr - '0';
1195 else if ((unsigned char) *ipAddrStr == '.')
1207 if(*ipAddrStr == ':')
1211 if (isdigit((unsigned char) *ipAddrStr))
1214 *port += *ipAddrStr - '0';
1225 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
1236 //-----------------------------------------------------------------------------
1237 // Private internal function prototypes
1238 //-----------------------------------------------------------------------------
1240 static OCDoHandle GenerateInvocationHandle();
1241 static OCStackResult initResources();
1242 static void insertResource(OCResource *resource);
1243 static OCResource *findResource(OCResource *resource);
1244 static void insertResourceType(OCResource *resource,
1245 OCResourceType *resourceType);
1246 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1248 static void insertResourceInterface(OCResource *resource,
1249 OCResourceInterface *resourceInterface);
1250 static OCResourceInterface *findResourceInterfaceAtIndex(
1251 OCResourceHandle handle, uint8_t index);
1252 static void deleteResourceType(OCResourceType *resourceType);
1253 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1254 static void deleteResourceElements(OCResource *resource);
1255 static int deleteResource(OCResource *resource);
1256 static void deleteAllResources();
1257 static void incrementSequenceNumber(OCResource * resPtr);
1258 static OCStackResult verifyUriQueryLength(const char * inputUri,
1260 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1261 OCStackResult getResourceType(const char * query, unsigned char** resourceType);
1263 //-----------------------------------------------------------------------------
1265 //-----------------------------------------------------------------------------
1268 * Initialize the OC Stack. Must be called prior to starting the stack.
1271 * IP Address of host device
1273 * Port of host device
1275 * Host device is client, server, or client-server
1278 * OC_STACK_OK - no errors
1279 * OC_STACK_ERROR - stack init error
1281 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1283 OCStackResult result = OC_STACK_ERROR;
1284 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1288 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
1293 //It is ok to select network to CA_WIFI for now
1295 CAResult_t caResult = CASelectNetwork(CA_ETHERNET);
1297 CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
1299 if(caResult == CA_STATUS_OK)
1301 OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
1302 CARegisterHandler(HandleCARequests, HandleCAResponses);
1304 OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
1305 stackState = OC_STACK_INITIALIZED;
1306 result = OC_STACK_OK;
1310 caResult = CAStartDiscoveryServer();
1311 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1314 caResult = CAStartListeningServer();
1315 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1317 case OC_CLIENT_SERVER:
1318 caResult = CAStartListeningServer();
1319 if(caResult == CA_STATUS_OK)
1321 caResult = CAStartDiscoveryServer();
1323 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1326 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1327 return OC_STACK_ERROR;
1332 if (caResult == CA_STATUS_OK)
1334 result = OC_STACK_OK;
1338 result = OC_STACK_ERROR;
1343 defaultDeviceHandler = NULL;
1345 #if defined(__WITH_DTLS__)
1346 caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
1347 result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
1348 #endif // (__WITH_DTLS__)
1350 #ifdef WITH_PRESENCE
1351 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1352 #endif // WITH_PRESENCE
1354 if (result == OC_STACK_OK)
1356 stackState = OC_STACK_INITIALIZED;
1358 // Initialize resource
1359 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
1361 result = initResources();
1363 if(result != OC_STACK_OK)
1365 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1371 * Stop the OC stack. Use for a controlled shutdown.
1373 * OC_STACK_OK - no errors
1374 * OC_STACK_ERROR - stack not initialized
1376 OCStackResult OCStop()
1378 OCStackResult result = OC_STACK_ERROR;
1380 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1382 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1384 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1387 else if (stackState != OC_STACK_INITIALIZED)
1389 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1390 return OC_STACK_ERROR;
1393 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1395 #ifdef WITH_PRESENCE
1396 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1397 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1398 presenceResource.presenceTTL = 0;
1399 #endif // WITH_PRESENCE
1401 // Free memory dynamically allocated for resources
1402 deleteAllResources();
1405 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1406 result = OC_STACK_OK;
1408 if (result == OC_STACK_OK)
1410 // Remove all observers
1411 DeleteObserverList();
1412 // Remove all the client callbacks
1413 DeleteClientCBList();
1414 stackState = OC_STACK_UNINITIALIZED;
1415 result = OC_STACK_OK;
1417 stackState = OC_STACK_INITIALIZED;
1418 result = OC_STACK_ERROR;
1421 // Deinit security blob
1422 DeinitOCSecurityInfo();
1424 if (result != OC_STACK_OK) {
1425 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1432 * Map OCQualityOfService to CAMessageType
1434 * @param OCQualityOfService - Input qos.
1436 * Returns CA message type for a given qos.
1438 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1443 return CA_MSG_CONFIRM;
1448 return CA_MSG_NONCONFIRM;
1453 * Verify the lengths of the URI and the query separately
1455 * @param inputUri - Input URI and query.
1456 * @param uriLen - The length of the initial URI with query.
1458 * Note: The '?' that appears after the URI is not considered as
1459 * a part of the query.
1461 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1465 query = strchr (inputUri, '?');
1469 if((query - inputUri) > MAX_URI_LENGTH)
1471 return OC_STACK_INVALID_URI;
1474 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1476 return OC_STACK_INVALID_QUERY;
1479 else if(uriLen > MAX_URI_LENGTH)
1481 return OC_STACK_INVALID_URI;
1487 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
1489 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
1490 * @param method - @ref OCMethod to perform on the resource
1491 * @param requiredUri - URI of the resource to interact with
1492 * @param referenceUri - URI of the reference resource
1493 * @param request - JSON encoded request
1494 * @param qos - quality of service
1495 * @param cbData - struct that contains asynchronous callback function that is invoked
1496 * by the stack when discovery or resource interaction is complete
1497 * @param options - The address of an array containing the vendor specific header
1498 * header options to be sent with the request
1499 * @param numOptions - Number of vendor specific header options to be included
1502 * OC_STACK_OK - no errors
1503 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1504 * OC_STACK_INVALID_METHOD - invalid resource method
1505 * OC_STACK_INVALID_URI - invalid required or reference URI
1507 * Note: IN case of CA, when using multicast, the required URI should not contain IP address.
1508 * Instead, it just contains the URI to the resource such as "/oc/core".
1510 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1511 const char *referenceUri, const char *request, OCConnectivityType conType,
1512 OCQualityOfService qos, OCCallbackData *cbData,
1513 OCHeaderOption * options, uint8_t numOptions)
1515 OCStackResult result = OC_STACK_ERROR;
1516 ClientCB *clientCB = NULL;
1517 unsigned char * requestUri = NULL;
1518 unsigned char * resourceType = NULL;
1519 unsigned char * query = NULL;
1520 char * newUri = (char *)requiredUri;
1521 (void) referenceUri;
1522 CARemoteEndpoint_t* endpoint = NULL;
1523 CAResult_t caResult;
1524 CAToken_t token = NULL;
1525 CAInfo_t requestData;
1526 CARequestInfo_t requestInfo;
1527 CAGroupEndpoint_t grpEnd;
1529 // To track if memory is allocated for additional header options
1530 uint8_t hdrOptionMemAlloc = 0;
1532 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1534 // Validate input parameters
1535 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1536 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1538 //TODO ("Need to form the final query by concatenating require and reference URI's");
1539 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1541 uint16_t uriLen = strlen(requiredUri);
1543 // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
1549 case OC_REST_DELETE:
1550 case OC_REST_OBSERVE:
1551 case OC_REST_OBSERVE_ALL:
1552 case OC_REST_CANCEL_OBSERVE:
1554 #ifdef WITH_PRESENCE
1555 case OC_REST_PRESENCE:
1559 result = OC_STACK_INVALID_METHOD;
1563 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1568 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1570 result = OC_STACK_INVALID_PARAM;
1574 #ifdef WITH_PRESENCE
1575 if(method == OC_REST_PRESENCE)
1577 result = getQueryFromUri(requiredUri, &query, &newUri);
1580 result = getResourceType((char *) query, &resourceType);
1583 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1587 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1592 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1594 if(result != OC_STACK_OK)
1599 #endif // WITH_PRESENCE
1601 requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1604 memcpy(requestUri, newUri, (uriLen + 1));
1608 result = OC_STACK_NO_MEMORY;
1612 *handle = GenerateInvocationHandle();
1615 result = OC_STACK_NO_MEMORY;
1619 memset(&requestData, 0, sizeof(CAInfo_t));
1620 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1621 memset(&grpEnd, 0, sizeof(CAGroupEndpoint_t));
1625 case OC_REST_OBSERVE:
1626 case OC_REST_OBSERVE_ALL:
1627 case OC_REST_CANCEL_OBSERVE:
1629 requestInfo.method = CA_GET;
1634 requestInfo.method = CA_PUT;
1639 requestInfo.method = CA_POST;
1642 case OC_REST_DELETE:
1644 requestInfo.method = CA_DELETE;
1647 #ifdef WITH_PRESENCE
1648 case OC_REST_PRESENCE:
1650 // Replacing method type with GET because "presence"
1651 // is a stack layer only implementation.
1652 requestInfo.method = CA_GET;
1657 result = OC_STACK_INVALID_METHOD;
1661 //High QoS is not supported
1662 if(qos == OC_HIGH_QOS)
1664 result = OC_STACK_INVALID_PARAM;
1669 caResult = CAGenerateToken(&token);
1670 if (caResult != CA_STATUS_OK)
1672 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1673 CADestroyToken(token);
1677 requestData.type = qualityOfServiceToMessageType(qos);
1678 requestData.token = token;
1679 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1681 result = CreateObserveHeaderOption (&(requestData.options), options,
1682 numOptions, OC_OBSERVE_REGISTER);
1683 if (result != OC_STACK_OK)
1687 hdrOptionMemAlloc = 1;
1688 requestData.numOptions = numOptions + 1;
1692 requestData.options = (CAHeaderOption_t*)options;
1693 requestData.numOptions = numOptions;
1695 requestData.payload = (char *)request;
1697 requestInfo.info = requestData;
1699 CAConnectivityType_t caConType;
1701 result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
1702 if (result != OC_STACK_OK)
1704 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1709 if(conType == OC_ALL)
1711 grpEnd.connectivityType = caConType;
1713 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1714 if(!grpEnd.resourceUri)
1716 result = OC_STACK_NO_MEMORY;
1719 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1721 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1725 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1727 if (caResult != CA_STATUS_OK)
1729 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1733 caResult = CASendRequest(endpoint, &requestInfo);
1736 if (caResult != CA_STATUS_OK)
1738 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1742 if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
1743 requestUri, resourceType)) != OC_STACK_OK)
1745 result = OC_STACK_NO_MEMORY;
1750 if(newUri != requiredUri)
1754 if (result != OC_STACK_OK)
1756 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1757 FindAndDeleteClientCB(clientCB);
1759 CADestroyRemoteEndpoint(endpoint);
1760 OCFree(grpEnd.resourceUri);
1761 if (hdrOptionMemAlloc)
1763 OCFree(requestData.options);
1769 * Cancel a request associated with a specific @ref OCDoResource invocation.
1771 * @param handle - Used to identify a specific OCDoResource invocation.
1772 * @param qos - used to specify Quality of Service (read below for more info)
1773 * @param options- used to specify vendor specific header options when sending
1774 * explicit observe cancellation
1775 * @param numOptions- Number of header options to be included
1778 * OC_STACK_OK - No errors; Success
1779 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1781 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1785 * This ftn is implemented one of two ways in the case of observation:
1787 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1788 * Remove the callback associated on client side.
1789 * When the next notification comes in from server,
1790 * reply with RESET message to server.
1791 * Keep in mind that the server will react to RESET only
1792 * if the last notification was sent ans CON
1794 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1795 * and it is associated with an observe request
1796 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1797 * Send CON Observe request to server with
1798 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1799 * Remove the callback associated on client side.
1801 OCStackResult ret = OC_STACK_OK;
1802 CARemoteEndpoint_t* endpoint = NULL;
1803 CAResult_t caResult;
1804 CAInfo_t requestData;
1805 CARequestInfo_t requestInfo;
1806 // Track if memory is allocated for additional header options
1807 uint8_t hdrOptionMemAlloc = 0;
1810 return OC_STACK_INVALID_PARAM;
1813 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1815 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1818 switch (clientCB->method)
1820 case OC_REST_OBSERVE:
1821 case OC_REST_OBSERVE_ALL:
1822 //TODO-CA : Why CA_WIFI alone?
1823 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1825 if (caResult != CA_STATUS_OK)
1827 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1828 return OC_STACK_ERROR;
1831 memset(&requestData, 0, sizeof(CAInfo_t));
1832 requestData.type = qualityOfServiceToMessageType(qos);
1833 requestData.token = clientCB->token;
1834 if (CreateObserveHeaderOption (&(requestData.options),
1835 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1837 return OC_STACK_ERROR;
1839 hdrOptionMemAlloc = 1;
1840 requestData.numOptions = numOptions + 1;
1841 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1842 requestInfo.method = CA_GET;
1843 requestInfo.info = requestData;
1845 caResult = CASendRequest(endpoint, &requestInfo);
1846 if (caResult != CA_STATUS_OK)
1848 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1850 if(caResult == CA_STATUS_OK)
1854 #ifdef WITH_PRESENCE
1855 case OC_REST_PRESENCE:
1856 FindAndDeleteClientCB(clientCB);
1860 return OC_STACK_INVALID_METHOD;
1863 CADestroyRemoteEndpoint(endpoint);
1864 if (hdrOptionMemAlloc)
1866 OCFree(requestData.options);
1872 #ifdef WITH_PRESENCE
1873 OCStackResult OCProcessPresence()
1875 OCStackResult result = OC_STACK_OK;
1876 uint8_t ipAddr[4] = { 0 };
1879 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1880 ClientCB* cbNode = NULL;
1882 OCClientResponse clientResponse;
1883 OCResponse * response = NULL;
1884 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1886 LL_FOREACH(cbList, cbNode) {
1887 if(OC_REST_PRESENCE == cbNode->method)
1889 if(cbNode->presence)
1891 uint32_t now = GetTime(0);
1892 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d",
1893 cbNode->presence->TTLlevel);
1894 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1897 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1902 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1903 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1904 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1907 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1909 OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1910 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1912 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1915 clientResponse.sequenceNumber = 0;
1916 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
1917 clientResponse.addr = (OCDevAddr *) &dst;
1918 clientResponse.resJSONPayload = NULL;
1920 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1921 &cbNode->token, &clientResponse, NULL);
1922 if(result != OC_STACK_OK)
1927 // Increment the TTLLevel (going to a next state), so we don't keep
1928 // sending presence notification to client.
1929 cbNode->presence->TTLlevel++;
1930 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1931 cbNode->presence->TTLlevel);
1935 result = OC_STACK_INVALID_IP;
1939 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1940 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1942 FindAndDeleteClientCB(cbNode);
1946 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1948 CAResult_t caResult;
1949 CARemoteEndpoint_t* endpoint = NULL;
1950 CAInfo_t requestData;
1951 CARequestInfo_t requestInfo;
1953 OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1955 //TODO-CA : Why CA_WIFI alone?
1956 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1959 if (caResult != CA_STATUS_OK)
1961 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1965 memset(&requestData, 0, sizeof(CAInfo_t));
1966 requestData.type = CA_MSG_NONCONFIRM;
1967 requestData.token = cbNode->token;
1969 memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1970 requestInfo.method = CA_GET;
1971 requestInfo.info = requestData;
1973 caResult = CASendRequest(endpoint, &requestInfo);
1975 if (caResult != CA_STATUS_OK)
1977 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1981 cbNode->presence->TTLlevel++;
1982 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1983 cbNode->presence->TTLlevel);
1989 if (result != OC_STACK_OK)
1991 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1995 #endif // WITH_PRESENCE
1998 * Called in main loop of OC client or server. Allows low-level processing of
2002 * OC_STACK_OK - no errors
2003 * OC_STACK_ERROR - stack process error
2005 OCStackResult OCProcess()
2007 #ifdef WITH_PRESENCE
2008 OCProcessPresence();
2010 CAHandleRequestResponse();
2015 #ifdef WITH_PRESENCE
2017 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
2018 * presence notifications to clients via multicast. Once this API has been called with a success,
2019 * clients may query for this server's presence and this server's stack will respond via multicast.
2021 * Server can call this function when it comes online for the first time, or when it comes back
2022 * online from offline mode, or when it re enters network.
2024 * @param ttl - Time To Live in seconds
2025 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
2028 * OC_STACK_OK - No errors; Success
2030 OCStackResult OCStartPresence(const uint32_t ttl)
2032 OCChangeResourceProperty(
2033 &(((OCResource *)presenceResource.handle)->resourceProperties),
2038 presenceResource.presenceTTL = ttl;
2041 if(OC_PRESENCE_UNINITIALIZED == presenceState)
2043 OCDevAddr multiCastAddr;
2044 presenceState = OC_PRESENCE_INITIALIZED;
2046 OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
2048 CAAddress_t addressInfo;
2049 strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
2050 addressInfo.IP.port = 5683;
2052 //TODO make sure there is no memory leak here since another copy
2053 //of token is being created inside AddObserver
2054 CAToken_t caToken = NULL;
2055 CAResult_t caResult = CAGenerateToken(&caToken);
2056 if (caResult != CA_STATUS_OK)
2058 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2059 CADestroyToken(caToken);
2060 return OC_STACK_ERROR;
2063 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
2064 &multiCastAddr, (OCResource *)presenceResource.handle, OC_LOW_QOS,
2065 &addressInfo, CA_WIFI);
2068 // Each time OCStartPresence is called
2069 // a different random 32-bit integer number is used
2070 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2072 return SendPresenceNotification(NULL);
2076 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
2077 * presence notifications to clients via multicast. Once this API has been called with a success,
2078 * this server's stack will not respond to clients querying for this server's presence.
2080 * Server can call this function when it is terminating, going offline, or when going
2081 * away from network.
2084 * OC_STACK_OK - No errors; Success
2086 OCStackResult OCStopPresence()
2088 OCStackResult result = OC_STACK_ERROR;
2089 //make resource inactive
2090 result = OCChangeResourceProperty(
2091 &(((OCResource *) presenceResource.handle)->resourceProperties),
2093 result = SendPresenceNotification(NULL);
2100 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
2102 defaultDeviceHandler = entityHandler;
2107 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2109 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
2111 if(myStackMode == OC_CLIENT)
2113 return OC_STACK_ERROR;
2116 return SaveDeviceInfo(deviceInfo);
2122 * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
2123 * @param resourceTypeName - name of resource type. Example: "core.led"
2124 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2125 * @param uri - URI of the resource. Example: "/a/led"
2126 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2127 * NULL for default entity handler
2128 * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
2131 * OC_STACK_OK - no errors
2132 * OC_STACK_ERROR - stack process error
2134 OCStackResult OCCreateResource(OCResourceHandle *handle,
2135 const char *resourceTypeName,
2136 const char *resourceInterfaceName,
2137 const char *uri, OCEntityHandler entityHandler,
2138 uint8_t resourceProperties) {
2140 OCResource *pointer = NULL;
2143 OCStackResult result = OC_STACK_ERROR;
2145 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
2147 if(myStackMode == OC_CLIENT)
2151 // Validate parameters
2152 if(!uri || (strlen(uri) == 0))
2154 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
2155 return OC_STACK_INVALID_URI;
2157 // Is it presented during resource discovery?
2158 if (!handle || !resourceTypeName) {
2159 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
2160 return OC_STACK_INVALID_PARAM;
2163 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
2164 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2167 // Make sure resourceProperties bitmask has allowed properties specified
2168 if (resourceProperties
2169 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
2170 OC_LOG(ERROR, TAG, PCF("Invalid property"));
2171 return OC_STACK_INVALID_PARAM;
2174 // If the headResource is NULL, then no resources have been created...
2175 pointer = headResource;
2177 // At least one resources is in the resource list, so we need to search for
2178 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2180 if (strcmp(uri, pointer->uri) == 0) {
2181 OC_LOG(ERROR, TAG, PCF("URI already in use"));
2182 return OC_STACK_INVALID_PARAM;
2184 pointer = pointer->next;
2187 // Create the pointer and insert it into the resource list
2188 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
2192 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2194 insertResource(pointer);
2197 size = strlen(uri) + 1;
2198 str = (char *) OCMalloc(size);
2202 strncpy(str, uri, size);
2205 // Set properties. Set OC_ACTIVE
2206 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2209 // Add the resourcetype to the resource
2210 result = BindResourceTypeToResource(pointer, resourceTypeName);
2211 if (result != OC_STACK_OK) {
2212 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2216 // Add the resourceinterface to the resource
2217 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2218 if (result != OC_STACK_OK) {
2219 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2223 // If an entity handler has been passed, attach it to the newly created
2224 // resource. Otherwise, set the default entity handler.
2227 pointer->entityHandler = entityHandler;
2231 pointer->entityHandler = defaultResourceEHandler;
2235 result = OC_STACK_OK;
2237 #ifdef WITH_PRESENCE
2238 if(presenceResource.handle)
2240 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2241 SendPresenceNotification(pointer->rsrcType);
2245 if (result != OC_STACK_OK)
2247 // Deep delete of resource and other dynamic elements that it contains
2248 deleteResource(pointer);
2257 * Create a resource. with host ip address for remote resource
2259 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2260 * Used to refer to resource
2261 * @param resourceTypeName - name of resource type. Example: "core.led"
2262 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2263 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2264 * @param uri - URI of the resource. Example: "/a/led"
2265 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2266 * NULL for default entity handler
2267 * @param resourceProperties - properties supported by resource.
2268 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2271 * OC_STACK_OK - no errors
2272 * OC_STACK_ERROR - stack process error
2275 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2276 const char *resourceTypeName,
2277 const char *resourceInterfaceName,
2280 OCEntityHandler entityHandler,
2281 uint8_t resourceProperties)
2285 OCStackResult result = OC_STACK_ERROR;
2287 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2288 uri, entityHandler, resourceProperties);
2290 if (result != OC_STACK_ERROR)
2293 size = strlen(host) + 1;
2294 str = (char *) OCMalloc(size);
2297 return OC_STACK_ERROR;
2299 strncpy(str, host, size);
2300 ((OCResource *) *handle)->host = str;
2307 * Add a resource to a collection resource.
2309 * @param collectionHandle - handle to the collection resource
2310 * @param resourceHandle - handle to resource to be added to the collection resource
2313 * OC_STACK_OK - no errors
2314 * OC_STACK_ERROR - stack process error
2315 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2317 OCStackResult OCBindResource(
2318 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2319 OCResource *resource;
2322 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2324 // Validate parameters
2325 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2326 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2327 // Container cannot contain itself
2328 if (collectionHandle == resourceHandle) {
2329 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2330 return OC_STACK_INVALID_PARAM;
2333 // Use the handle to find the resource in the resource linked list
2334 resource = findResource((OCResource *) collectionHandle);
2336 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2337 return OC_STACK_INVALID_PARAM;
2340 // Look for an open slot to add add the child resource.
2341 // If found, add it and return success
2342 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2343 if (!resource->rsrcResources[i]) {
2344 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2345 OC_LOG(INFO, TAG, PCF("resource bound"));
2350 #ifdef WITH_PRESENCE
2351 if(presenceResource.handle)
2353 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2354 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2358 // Unable to add resourceHandle, so return error
2359 return OC_STACK_ERROR;
2363 * Remove a resource from a collection resource.
2365 * @param collectionHandle - handle to the collection resource
2366 * @param resourceHandle - handle to resource to be added to the collection resource
2369 * OC_STACK_OK - no errors
2370 * OC_STACK_ERROR - stack process error
2371 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2373 OCStackResult OCUnBindResource(
2374 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
2375 OCResource *resource;
2378 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2380 // Validate parameters
2381 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2382 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2383 // Container cannot contain itself
2384 if (collectionHandle == resourceHandle) {
2385 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2386 return OC_STACK_INVALID_PARAM;
2389 // Use the handle to find the resource in the resource linked list
2390 resource = findResource((OCResource *) collectionHandle);
2392 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2393 return OC_STACK_INVALID_PARAM;
2396 // Look for an open slot to add add the child resource.
2397 // If found, add it and return success
2398 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
2399 if (resourceHandle == resource->rsrcResources[i]) {
2400 resource->rsrcResources[i] = (OCResource *) NULL;
2401 OC_LOG(INFO, TAG, PCF("resource unbound"));
2406 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2408 #ifdef WITH_PRESENCE
2409 if(presenceResource.handle)
2411 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2412 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2416 // Unable to add resourceHandle, so return error
2417 return OC_STACK_ERROR;
2420 OCStackResult BindResourceTypeToResource(OCResource* resource,
2421 const char *resourceTypeName)
2423 OCResourceType *pointer = NULL;
2426 OCStackResult result = OC_STACK_ERROR;
2428 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2430 // Validate parameters
2431 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2432 // TODO: Does resource attribute resentation really have to be maintained in stack?
2433 // Is it presented during resource discovery?
2435 //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2437 // Create the resourcetype and insert it into the resource list
2438 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2443 // Set the resourceTypeName
2444 size = strlen(resourceTypeName) + 1;
2445 str = (char *) OCMalloc(size);
2449 strncpy(str, resourceTypeName, size);
2450 pointer->resourcetypename = str;
2452 insertResourceType(resource, pointer);
2453 result = OC_STACK_OK;
2455 exit: if (result != OC_STACK_OK) {
2463 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2464 const char *resourceInterfaceName)
2466 OCResourceInterface *pointer = NULL;
2469 OCStackResult result = OC_STACK_ERROR;
2471 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2473 // Validate parameters
2474 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2476 //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2478 // Create the resourceinterface and insert it into the resource list
2479 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2484 // Set the resourceinterface name
2485 size = strlen(resourceInterfaceName) + 1;
2486 str = (char *) OCMalloc(size);
2490 strncpy(str, resourceInterfaceName, size);
2491 pointer->name = str;
2493 // Bind the resourceinterface to the resource
2494 insertResourceInterface(resource, pointer);
2496 result = OC_STACK_OK;
2498 exit: if (result != OC_STACK_OK) {
2507 * Bind a resourcetype to a resource.
2509 * @param handle - handle to the resource
2510 * @param resourceTypeName - name of resource type. Example: "core.led"
2513 * OC_STACK_OK - no errors
2514 * OC_STACK_ERROR - stack process error
2516 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2517 const char *resourceTypeName) {
2519 OCStackResult result = OC_STACK_ERROR;
2520 OCResource *resource;
2522 // Make sure resource exists
2523 resource = findResource((OCResource *) handle);
2525 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2526 return OC_STACK_ERROR;
2529 // call internal function
2530 result = BindResourceTypeToResource(resource, resourceTypeName);
2532 #ifdef WITH_PRESENCE
2533 if(presenceResource.handle)
2535 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2536 SendPresenceNotification(resource->rsrcType);
2544 * Bind a resourceinterface to a resource.
2546 * @param handle - handle to the resource
2547 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2550 * OC_STACK_OK - no errors
2551 * OC_STACK_ERROR - stack process error
2554 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2555 const char *resourceInterfaceName) {
2557 OCStackResult result = OC_STACK_ERROR;
2558 OCResource *resource;
2560 // Make sure resource exists
2561 resource = findResource((OCResource *) handle);
2563 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2564 return OC_STACK_ERROR;
2567 // call internal function
2568 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2570 #ifdef WITH_PRESENCE
2571 if(presenceResource.handle)
2573 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2574 SendPresenceNotification(resource->rsrcType);
2582 * Get the number of resources that have been created in the stack.
2584 * @param numResources - pointer to count variable
2587 * OC_STACK_OK - no errors
2588 * OC_STACK_ERROR - stack process error
2591 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2592 OCResource *pointer = headResource;
2594 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2595 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2598 *numResources = *numResources + 1;
2599 pointer = pointer->next;
2605 * Get a resource handle by index.
2607 * @param index - index of resource, 0 to Count - 1
2610 * Resource handle - if found
2611 * NULL - if not found
2613 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2614 OCResource *pointer = headResource;
2617 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2619 // Iterate through the list
2620 while ((i < index) && pointer) {
2622 pointer = pointer->next;
2624 return (OCResourceHandle) pointer;
2628 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2631 * @param handle - handle of resource to be deleted
2634 * OC_STACK_OK - no errors
2635 * OC_STACK_ERROR - stack process error
2636 * OC_STACK_NO_RESOURCE - resource not found
2637 * OC_STACK_INVALID_PARAM - invalid param
2639 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2640 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2643 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2644 return OC_STACK_INVALID_PARAM;
2647 OCResource *resource = findResource((OCResource *) handle);
2648 if (resource == NULL) {
2649 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2650 return OC_STACK_NO_RESOURCE;
2653 if (deleteResource((OCResource *) handle) == 0) {
2654 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2655 return OC_STACK_ERROR;
2662 * Get the URI of the resource specified by handle.
2664 * @param handle - handle of resource
2666 * URI string - if resource found
2667 * NULL - resource not found
2669 const char *OCGetResourceUri(OCResourceHandle handle) {
2670 OCResource *resource;
2671 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2673 resource = findResource((OCResource *) handle);
2675 return resource->uri;
2677 return (const char *) NULL;
2681 * Get the properties of the resource specified by handle.
2682 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2683 * for the resource by the stack.
2685 * @param handle - handle of resource
2687 * property bitmap - if resource found
2688 * NULL - resource not found
2690 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2691 OCResource *resource;
2692 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2694 resource = findResource((OCResource *) handle);
2696 return resource->resourceProperties;
2702 * Get the number of resource types of the resource.
2704 * @param handle - handle of resource
2705 * @param numResourceTypes - pointer to count variable
2708 * OC_STACK_OK - no errors
2709 * OC_STACK_ERROR - stack process error
2711 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2712 uint8_t *numResourceTypes) {
2713 OCResource *resource;
2714 OCResourceType *pointer;
2716 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2717 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2718 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2720 *numResourceTypes = 0;
2722 resource = findResource((OCResource *) handle);
2724 pointer = resource->rsrcType;
2726 *numResourceTypes = *numResourceTypes + 1;
2727 pointer = pointer->next;
2734 * Get name of resource type of the resource.
2736 * @param handle - handle of resource
2737 * @param index - index of resource, 0 to Count - 1
2740 * resource type name - if resource found
2741 * NULL - resource not found
2743 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2744 OCResourceType *resourceType;
2746 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2748 resourceType = findResourceTypeAtIndex(handle, index);
2750 return resourceType->resourcetypename;
2752 return (const char *) NULL;
2758 * Get the number of resource interfaces of the resource.
2760 * @param handle - handle of resource
2761 * @param numResources - pointer to count variable
2764 * OC_STACK_OK - no errors
2765 * OC_STACK_ERROR - stack process error
2767 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2768 uint8_t *numResourceInterfaces) {
2769 OCResourceInterface *pointer;
2770 OCResource *resource;
2772 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2774 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2775 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2777 *numResourceInterfaces = 0;
2778 resource = findResource((OCResource *) handle);
2780 pointer = resource->rsrcInterface;
2782 *numResourceInterfaces = *numResourceInterfaces + 1;
2783 pointer = pointer->next;
2790 * Get name of resource interface of the resource.
2792 * @param handle - handle of resource
2793 * @param index - index of resource, 0 to Count - 1
2796 * resource interface name - if resource found
2797 * NULL - resource not found
2799 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2800 OCResourceInterface *resourceInterface;
2802 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2804 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2805 if (resourceInterface) {
2806 return resourceInterface->name;
2808 return (const char *) NULL;
2812 * Get resource handle from the collection resource by index.
2814 * @param collectionHandle - handle of collection resource
2815 * @param index - index of contained resource, 0 to Count - 1
2818 * handle to resource - if resource found
2819 * NULL - resource not found
2821 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2823 OCResource *resource;
2825 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2827 if (index >= MAX_CONTAINED_RESOURCES) {
2831 resource = findResource((OCResource *) collectionHandle);
2836 return resource->rsrcResources[index];
2840 * Bind an entity handler to the resource.
2842 * @param handle - handle to the resource that the contained resource is to be bound
2843 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2845 * OC_STACK_OK - no errors
2846 * OC_STACK_ERROR - stack process error
2848 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2849 OCEntityHandler entityHandler) {
2850 OCResource *resource;
2852 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2854 // Validate parameters
2855 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2856 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2858 // Use the handle to find the resource in the resource linked list
2859 resource = findResource((OCResource *)handle);
2861 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2862 return OC_STACK_ERROR;
2866 resource->entityHandler = entityHandler;
2868 #ifdef WITH_PRESENCE
2869 if(presenceResource.handle)
2871 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2872 SendPresenceNotification(resource->rsrcType);
2880 * Get the entity handler for a resource.
2882 * @param handle - handle of resource
2885 * entity handler - if resource found
2886 * NULL - resource not found
2888 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2889 OCResource *resource;
2891 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2893 // Use the handle to find the resource in the resource linked list
2894 resource = findResource((OCResource *)handle);
2896 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2901 return resource->entityHandler;
2904 void incrementSequenceNumber(OCResource * resPtr)
2906 // Increment the sequence number
2907 resPtr->sequenceNum += 1;
2908 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2910 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2916 * Notify Presence subscribers that a resource has been modified
2918 * @param resourceType - Handle to the resourceType linked list of resource
2919 * that was modified.
2920 * @param qos - Quality Of Service
2923 #ifdef WITH_PRESENCE
2924 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2926 OCResource *resPtr = NULL;
2927 OCStackResult result;
2928 OCMethod method = OC_REST_PRESENCE;
2929 uint32_t maxAge = 0;
2930 resPtr = findResource((OCResource *) presenceResource.handle);
2933 return OC_STACK_NO_RESOURCE;
2935 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2937 maxAge = presenceResource.presenceTTL;
2944 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2948 #endif // WITH_PRESENCE
2950 * Notify observers that an observed value has changed.
2952 * @param handle - handle of resource
2955 * OC_STACK_OK - no errors
2956 * OC_STACK_NO_RESOURCE - invalid resource handle
2957 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2959 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
2961 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2963 OCResource *resPtr = NULL;
2964 OCStackResult result;
2965 OCMethod method = OC_REST_NOMETHOD;
2966 uint32_t maxAge = 0;
2968 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2969 #ifdef WITH_PRESENCE
2970 if(handle == presenceResource.handle)
2974 #endif // WITH_PRESENCE
2975 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2977 // Verify that the resource exists
2978 resPtr = findResource ((OCResource *) handle);
2981 return OC_STACK_NO_RESOURCE;
2985 //only increment in the case of regular observing (not presence)
2986 incrementSequenceNumber(resPtr);
2987 method = OC_REST_OBSERVE;
2988 maxAge = MAX_OBSERVE_AGE;
2989 #ifdef WITH_PRESENCE
2990 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
2992 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
2999 OCNotifyListOfObservers (OCResourceHandle handle,
3000 OCObservationId *obsIdList,
3001 uint8_t numberOfIds,
3002 unsigned char *notificationJSONPayload,
3003 OCQualityOfService qos)
3005 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
3007 OCResource *resPtr = NULL;
3008 //TODO: we should allow the server to define this
3009 uint32_t maxAge = MAX_OBSERVE_AGE;
3011 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3012 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3013 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
3015 // Verify that the resource exists
3016 resPtr = findResource ((OCResource *) handle);
3017 if (NULL == resPtr || myStackMode == OC_CLIENT)
3019 return OC_STACK_NO_RESOURCE;
3023 incrementSequenceNumber(resPtr);
3025 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3026 notificationJSONPayload, maxAge, qos));
3030 * Send a response to a request.
3031 * The response can be a regular, slow, or block (i.e. a response that
3032 * is too large to be sent in a single PDU and must span multiple transmissions)
3034 * @param response - pointer to structure that contains response parameters
3037 * OC_STACK_OK - No errors; Success
3038 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
3039 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
3040 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
3041 * persistent response buffer is necessary
3043 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3045 OCStackResult result = OC_STACK_ERROR;
3046 OCServerRequest *serverRequest = NULL;
3048 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
3050 // Validate input parameters
3051 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3052 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3054 // TODO: Placeholder for creating a response entry when implementing
3055 // block transfer feature
3057 // If a response payload is present, check if block transfer is required
3058 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
3059 (const char *)ehResponse->payload, ehResponse->payloadSize))
3061 OC_LOG(INFO, TAG, PCF("Block transfer required"));
3063 // Persistent response buffer is needed for block transfer
3064 if (!ehResponse->persistentBufferFlag)
3066 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
3067 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
3069 // TODO: Placeholder for block transfer handling
3070 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
3071 // when implementing the block transfer feature
3076 // Get pointer to request info
3077 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3080 result = serverRequest->ehResponseHandler(ehResponse);
3087 * Cancel a response. Applies to a block response
3089 * @param responseHandle - response handle set by stack in OCServerResponse after
3090 * OCDoResponse is called
3093 * OC_STACK_OK - No errors; Success
3094 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
3096 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
3098 OCStackResult result = OC_STACK_NOTIMPL;
3100 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
3102 // TODO: validate response handle
3107 //-----------------------------------------------------------------------------
3108 // Private internal function definitions
3109 //-----------------------------------------------------------------------------
3111 * Generate handle of OCDoResource invocation for callback management.
3113 static OCDoHandle GenerateInvocationHandle()
3115 OCDoHandle handle = NULL;
3116 // Generate token here, it will be deleted when the transaction is deleted
3117 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3120 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3125 #ifdef WITH_PRESENCE
3126 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3127 OCResourceProperty resourceProperties, uint8_t enable)
3129 if (resourceProperties
3130 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
3131 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3132 return OC_STACK_INVALID_PARAM;
3136 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3140 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3147 * Initialize resource data structures, variables, etc.
3149 OCStackResult initResources() {
3150 OCStackResult result = OC_STACK_OK;
3151 // Init application resource vars
3152 headResource = NULL;
3153 // Init Virtual Resources
3154 #ifdef WITH_PRESENCE
3155 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3156 //presenceResource.token = OCGenerateCoAPToken();
3157 result = OCCreateResource(&presenceResource.handle,
3158 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3163 //make resource inactive
3164 result = OCChangeResourceProperty(
3165 &(((OCResource *) presenceResource.handle)->resourceProperties),
3172 * Add a resource to the end of the linked list of resources.
3174 * @param resource - resource to be added
3176 void insertResource(OCResource *resource) {
3177 OCResource *pointer;
3179 if (!headResource) {
3180 headResource = resource;
3182 pointer = headResource;
3184 while (pointer->next) {
3185 pointer = pointer->next;
3187 pointer->next = resource;
3189 resource->next = NULL;
3193 * Find a resource in the linked list of resources.
3195 * @param resource - resource to be found
3197 * NULL - resource not found
3198 * pointer to resource - pointer to resource that was found in the linked list
3200 OCResource *findResource(OCResource *resource) {
3201 OCResource *pointer = headResource;
3204 if (pointer == resource) {
3207 pointer = pointer->next;
3212 void deleteAllResources()
3214 OCResource *pointer = headResource;
3219 temp = pointer->next;
3220 #ifdef WITH_PRESENCE
3221 if(pointer != (OCResource *) presenceResource.handle)
3223 #endif // WITH_PRESENCE
3224 deleteResource(pointer);
3225 #ifdef WITH_PRESENCE
3227 #endif // WITH_PRESENCE
3231 #ifdef WITH_PRESENCE
3232 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3233 // presence notification attributed to their deletion to be processed.
3234 deleteResource((OCResource *) presenceResource.handle);
3235 #endif // WITH_PRESENCE
3239 * Delete the resource from the linked list.
3241 * @param resource - resource to be deleted
3246 int deleteResource(OCResource *resource) {
3247 OCResource *prev = NULL;
3250 temp = headResource;
3252 if (temp == resource) {
3253 // Invalidate all Resource Properties.
3254 resource->resourceProperties = (OCResourceProperty) 0;
3255 #ifdef WITH_PRESENCE
3256 if(resource != (OCResource *) presenceResource.handle)
3258 #endif // WITH_PRESENCE
3259 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3260 #ifdef WITH_PRESENCE
3263 if(presenceResource.handle)
3265 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3266 if(resource != (OCResource *) presenceResource.handle)
3268 SendPresenceNotification(resource->rsrcType);
3272 SendPresenceNotification(NULL);
3277 if (temp == headResource) {
3278 headResource = temp->next;
3280 prev->next = temp->next;
3283 deleteResourceElements(temp);
3296 * Delete all of the dynamically allocated elements that were created for the resource.
3298 * @param resource - specified resource
3300 void deleteResourceElements(OCResource *resource) {
3306 OCFree(resource->uri);
3308 // Delete resourcetype linked list
3309 deleteResourceType(resource->rsrcType);
3311 // Delete resourceinterface linked list
3312 deleteResourceInterface(resource->rsrcInterface);
3316 * Delete all of the dynamically allocated elements that were created for the resource type.
3318 * @param resourceType - specified resource type
3320 void deleteResourceType(OCResourceType *resourceType) {
3321 OCResourceType *pointer = resourceType;
3322 OCResourceType *next;
3325 next = pointer->next;
3326 OCFree(pointer->resourcetypename);
3333 * Delete all of the dynamically allocated elements that were created for the resource interface.
3335 * @param resourceInterface - specified resource interface
3337 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
3338 OCResourceInterface *pointer = resourceInterface;
3339 OCResourceInterface *next;
3342 next = pointer->next;
3343 OCFree(pointer->name);
3350 * Insert a resource type into a resource's resource type linked list.
3352 * @param resource - resource where resource type is to be inserted
3353 * @param resourceType - resource type to be inserted
3355 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
3356 OCResourceType *pointer;
3358 if (resource && !resource->rsrcType) {
3359 resource->rsrcType = resourceType;
3363 pointer = resource->rsrcType;
3367 pointer = resourceType;
3369 while (pointer->next) {
3370 pointer = pointer->next;
3372 pointer->next = resourceType;
3374 resourceType->next = NULL;
3378 * Get a resource type at the specified index within a resource.
3380 * @param handle - handle of resource
3381 * @param index - index of resource type
3384 * resourcetype - if found
3387 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
3388 OCResource *resource;
3389 OCResourceType *pointer;
3392 // Find the specified resource
3393 resource = findResource((OCResource *) handle);
3398 // Make sure a resource has a resourcetype
3399 if (!resource->rsrcType) {
3403 // Iterate through the list
3404 pointer = resource->rsrcType;
3406 while ((i < index) && pointer) {
3408 pointer = pointer->next;
3414 * Finds a resource type in an OCResourceType link-list.
3416 * @param resourceTypeList - the link-list to be searched through
3417 * @param resourceTypeName - the key to search for
3420 * resourceType that matches the key (ie. resourceTypeName)
3421 * NULL - either an invalid parameter or this function was unable to find the key.
3423 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3425 if(resourceTypeList && resourceTypeName)
3427 OCResourceType * rtPointer = resourceTypeList;
3428 while(resourceTypeName && rtPointer)
3430 if(rtPointer->resourcetypename &&
3431 strcmp(resourceTypeName, (const char *)
3432 (rtPointer->resourcetypename)) == 0)
3436 rtPointer = rtPointer->next;
3443 * Insert a resource interface into a resource's resource interface linked list.
3445 * @param resource - resource where resource interface is to be inserted
3446 * @param resourceInterface - resource interface to be inserted
3448 void insertResourceInterface(OCResource *resource,
3449 OCResourceInterface *resourceInterface) {
3450 OCResourceInterface *pointer;
3452 if (!resource->rsrcInterface) {
3453 resource->rsrcInterface = resourceInterface;
3455 pointer = resource->rsrcInterface;
3456 while (pointer->next) {
3457 pointer = pointer->next;
3459 pointer->next = resourceInterface;
3461 resourceInterface->next = NULL;
3465 * Get a resource interface at the specified index within a resource.
3467 * @param handle - handle of resource
3468 * @param index - index of resource interface
3471 * resourceinterface - if found
3474 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3476 OCResource *resource;
3477 OCResourceInterface *pointer;
3480 // Find the specified resource
3481 resource = findResource((OCResource *) handle);
3486 // Make sure a resource has a resourceinterface
3487 if (!resource->rsrcInterface) {
3491 // Iterate through the list
3492 pointer = resource->rsrcInterface;
3494 while ((i < index) && pointer) {
3496 pointer = pointer->next;
3502 * Determine if a request/response must be sent in a block transfer because it is too large to be
3503 * sent in a single PDU. This function can be used for either a request or a response
3505 * @param request - NULL or pointer to request
3506 * @param response - NULL or pointer to response
3507 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3508 * the length of the request/response
3511 * 0 - packet transfer NOT required (i.e. normal request/response)
3512 * 1 - packet transfer required (i.e. block transfer needed)
3514 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3518 // Determine if we are checking a request or a response
3521 // If size is greater than 0, use it for the request size value, otherwise
3522 // assume request is null terminated and use strlen for size value
3523 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3530 // If size is greater than 0, use it for the response size value, otherwise
3531 // assume response is null terminated and use strlen for size value
3532 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3541 * Retrieves a resource type based upon a query ontains only just one
3542 * resource attribute (and that has to be of type "rt").
3544 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3545 * before passing in.
3547 * @param query - The quert part of the URI
3548 * @param resourceType - The resource type to be populated; pass by reference.
3551 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3552 * OC_STACK_OK - Success
3554 OCStackResult getResourceType(const char * query, unsigned char** resourceType)
3558 return OC_STACK_INVALID_PARAM;
3561 OCStackResult result = OC_STACK_ERROR;
3563 if(strncmp(query, "rt=", 3) == 0)
3565 *resourceType = (unsigned char *) OCMalloc(strlen(query)-3);
3568 result = OC_STACK_NO_MEMORY;
3571 strcpy((char *)*resourceType, ((const char *)&query[3]));
3572 result = OC_STACK_OK;
3578 OCStackResult getQueryFromUri(const char * uri, unsigned char** query, char ** newURI)
3582 return OC_STACK_INVALID_URI;
3584 if(!query || !newURI)
3586 return OC_STACK_INVALID_PARAM;
3588 char * leftToken = NULL;
3589 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3594 strcpy(tempURI, uri);
3596 leftToken = strtok_r((char *)tempURI, "?", &strTokPtr);
3598 //TODO-CA: This could be simplified. Clean up required.
3599 while(leftToken != NULL)
3601 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3603 *query = (unsigned char *) OCMalloc(strlen(leftToken) + 1);
3609 strcpy((char *)*query, ((const char *)&leftToken[0]));
3612 leftToken = strtok_r(NULL, "?", &strTokPtr);
3620 return OC_STACK_NO_MEMORY;
3623 const ServerID OCGetServerInstanceID(void)
3625 static bool generated = false;
3626 static ServerID sid;
3633 sid = OCGetRandom();
3638 const char* OCGetServerInstanceIDString(void)
3640 // max printed length of a base 10
3641 // uint32 is 10 characters, so 11 includes null.
3642 // This will change as the representation gets switched
3644 static char buffer[11];
3645 int n = sprintf(buffer, "%u", OCGetServerInstanceID());