Merge "[CA] [All] URI support , Optimization , License verification" into connectivit...
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocstack.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 //-----------------------------------------------------------------------------
23 // Includes
24 //-----------------------------------------------------------------------------
25 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocresourcehandler.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
30 #include "ocrandom.h"
31 #include "debug.h"
32 #include "occoap.h"
33 #include "ocmalloc.h"
34 #include "ocserverrequest.h"
35
36 #ifdef CA_INT
37     #include "cacommon.h"
38     #include "cainterface.h"
39 #endif
40
41 //-----------------------------------------------------------------------------
42 // Typedefs
43 //-----------------------------------------------------------------------------
44 typedef enum {
45     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
46 } OCStackState;
47
48 #ifdef WITH_PRESENCE
49 typedef enum {
50     OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
51 } OCPresenceState;
52 #endif
53
54 //-----------------------------------------------------------------------------
55 // Private variables
56 //-----------------------------------------------------------------------------
57 static OCStackState stackState = OC_STACK_UNINITIALIZED;
58
59 OCResource *headResource = NULL;
60 #ifdef WITH_PRESENCE
61 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
62 static PresenceResource presenceResource;
63 uint8_t PresenceTimeOutSize = 0;
64 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
65 #endif
66
67 OCMode myStackMode;
68 OCDeviceEntityHandler defaultDeviceHandler;
69
70 //-----------------------------------------------------------------------------
71 // Macros
72 //-----------------------------------------------------------------------------
73 #define TAG  PCF("OCStack")
74 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
75             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
76 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
77              TAG, PCF(#arg " is NULL")); return (retVal); } }
78 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
79     goto exit;} }
80
81 //TODO: we should allow the server to define this
82 #define MAX_OBSERVE_AGE (0x2FFFFUL)
83
84 //-----------------------------------------------------------------------------
85 // Externs
86 //-----------------------------------------------------------------------------
87 extern void DeinitOCSecurityInfo();
88
89 //-----------------------------------------------------------------------------
90 // Internal API function
91 //-----------------------------------------------------------------------------
92
93 // This internal function is called to update the stack with the status of
94 // observers and communication failures
95 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
96 {
97     OCStackResult result = OC_STACK_ERROR;
98     ResourceObserver * observer = NULL;
99     OCEntityHandlerRequest ehRequest = {0};
100
101     switch(status)
102     {
103     case OC_OBSERVER_NOT_INTERESTED:
104         OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
105         observer = GetObserverUsingToken (token);
106         if(observer)
107         {
108             result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
109                     OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
110                     NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
111             if(result != OC_STACK_OK)
112             {
113                 return result;
114             }
115             observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
116         }
117         //observer is not observing anymore
118         result = DeleteObserverUsingToken (token);
119         if(result == OC_STACK_OK)
120         {
121             OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
122         }
123         else
124         {
125             result = OC_STACK_OK;
126             OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
127         }
128         break;
129     case OC_OBSERVER_STILL_INTERESTED:
130         //observer is still interested
131         OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
132                 notifications, reset the failedCount"));
133         observer = GetObserverUsingToken(token);
134         if(observer)
135         {
136             observer->forceHighQos = 0;
137             observer->failedCommCount = 0;
138             result = OC_STACK_OK;
139         }
140         else
141         {
142             result = OC_STACK_OBSERVER_NOT_FOUND;
143         }
144         break;
145     case OC_OBSERVER_FAILED_COMM:
146         //observer is not reachable
147         OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
148         observer = GetObserverUsingToken(token);
149         if(observer)
150         {
151             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
152             {
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)
157                 {
158                     return OC_STACK_ERROR;
159                 }
160                 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
161                 //observer is unreachable
162                 result = DeleteObserverUsingToken (token);
163                 if(result == OC_STACK_OK)
164                 {
165                     OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
166                 }
167                 else
168                 {
169                     result = OC_STACK_OK;
170                     OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
171                 }
172             }
173             else
174             {
175                 observer->failedCommCount++;
176                 result = OC_STACK_CONTINUE;
177             }
178             observer->forceHighQos = 1;
179             OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
180         }
181         break;
182     default:
183         OC_LOG(ERROR, TAG, PCF("Unknown status"));
184         result = OC_STACK_ERROR;
185         break;
186         }
187     return result;
188 }
189
190 #ifdef CA_INT
191 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
192 {
193     OCStackResult ret = OC_STACK_ERROR;
194
195     switch(caCode)
196     {
197         case CA_SUCCESS:
198             ret = OC_STACK_OK;
199             break;
200         case CA_CREATED:
201             ret = OC_STACK_RESOURCE_CREATED;
202             break;
203         case CA_DELETED:
204             ret = OC_STACK_RESOURCE_DELETED;
205             break;
206         case CA_BAD_REQ:
207             ret = OC_STACK_INVALID_QUERY;
208             break;
209         case CA_BAD_OPT:
210             ret = OC_STACK_INVALID_OPTION;
211             break;
212         case CA_NOT_FOUND:
213             ret = OC_STACK_NO_RESOURCE;
214             break;
215         default:
216             break;
217     }
218     return ret;
219 }
220
221 //This function will be called back by CA layer when a response is received
222 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
223 {
224     OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
225     printf ("Received payload: %s\n", (char *)responseInfo->info.payload);
226     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
227     ClientCB *cbNode = GetClientCB((CAToken_t *)&responseInfo->info.token, NULL, NULL);
228     if (cbNode)
229     {
230         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
231         OCClientResponse response;
232         struct sockaddr_in sa;
233
234         inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
235         sa.sin_port = htons(endPoint->addressInfo.IP.port);
236         static OCDevAddr address;
237         memcpy((void*)&address.addr, &(sa), sizeof(sa));
238         response.addr = &address;
239         response.result = CAToOCStackResult(responseInfo->result);
240         response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
241         response.numRcvdVendorSpecificHeaderOptions = 0;
242         if(responseInfo->info.numOptions > 0)
243         {
244             //First option alwas with option ID COAP_OPTION_OBSERVE if it is availbale
245             if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
246             {
247                 memcpy (&(response.sequenceNumber),
248                 &(responseInfo->info.options[0].optionData), 4);
249             }
250             else
251             {
252                memcpy (&(response.rcvdVendorSpecificHeaderOptions[0]),
253                  &(responseInfo->info.options[0]), sizeof(OCHeaderOption));
254             }
255             for (uint8_t i = 1; i < responseInfo->info.numOptions; i++)
256             {
257                 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i]),
258                  &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
259             }
260             response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
261         }
262         result = cbNode->callBack(cbNode->context,
263                 cbNode->handle, &response);
264         if (result == OC_STACK_DELETE_TRANSACTION)
265         {
266             FindAndDeleteClientCB(cbNode);
267         }
268     }
269     OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
270     OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
271 }
272
273 //This function will be called back by CA layer when a request is received
274 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
275 {
276     CAInfo_t responseData;
277     CAResponseInfo_t responseInfo;
278     OCStackResult requestResult = OC_STACK_ERROR;
279
280     OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
281
282 #if 1
283     if(myStackMode == OC_CLIENT)
284     {
285         //TODO: should the client be responding to requests?
286         return;
287     }
288
289     OCServerProtocolRequest serverRequest;
290
291     memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
292     // copy URI of resource
293     memcpy (&(serverRequest.resourceUrl), endPoint->resourceUri, strlen(endPoint->resourceUri));
294     //copy query
295     // TODO-CA: Is the query part of header option?
296     //copy request payload
297     if (requestInfo->info.payload)
298     {
299         serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
300         memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
301                 strlen(requestInfo->info.payload));
302         serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
303     }
304     else
305     {
306         serverRequest.reqTotalSize = 1;
307     }
308
309     switch (requestInfo->method)
310     {
311         case CA_GET:
312             {
313                 serverRequest.method = OC_REST_GET;
314                 break;
315             }
316         case CA_PUT:
317             {
318                 serverRequest.method = OC_REST_PUT;
319                 break;
320             }
321         case CA_POST:
322             {
323                 serverRequest.method = OC_REST_POST;
324                 break;
325             }
326         case CA_DELETE:
327             {
328                 serverRequest.method = OC_REST_DELETE;
329                 break;
330             }
331         default:
332             {
333                 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
334                 return;
335             }
336     }
337
338     // copy token
339     OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", strlen(requestInfo->info.token));
340     OC_LOG_BUFFER(INFO, TAG, requestInfo->info.token, strlen(requestInfo->info.token));
341     // TODO-CA: For CA integration currently copying CAToken to OCCoapToken:
342     // Need to remove OCCoapToken
343     memcpy (&(serverRequest.requestToken.token), requestInfo->info.token,
344             strlen(requestInfo->info.token));
345     serverRequest.requestToken.tokenLength = strlen(requestInfo->info.token);
346
347     if (requestInfo->info.type == CA_MSG_CONFIRM)
348     {
349         serverRequest.qos = OC_HIGH_QOS;
350     }
351     else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
352     {
353         serverRequest.qos = OC_LOW_QOS;
354     }
355     else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
356     {
357         // TODO-CA: Need to handle this
358     }
359     else if (requestInfo->info.type == CA_MSG_RESET)
360     {
361         // TODO-CA: Need to handle this
362     }
363     // CA does not need the following 3 fields
364     serverRequest.coapID = 0;
365     serverRequest.delayedResNeeded = 0;
366     serverRequest.secured = 0;
367
368     // copy the address
369     serverRequest.addressInfo      = endPoint->addressInfo;
370     serverRequest.connectivityType = endPoint->connectivityType;
371     if (requestInfo->info.token)
372     {
373         strncpy(serverRequest.token, requestInfo->info.token, sizeof(serverRequest.token) - 1);
374     }
375 #if 0
376     struct sockaddr_in sa;
377     inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
378     sa.sin_port = htons(endPoint->addressInfo.IP.port);
379     memcpy((void*)&serverRequest.requesterAddr, &(sa), sizeof(sa));
380 #endif
381     // copy vendor specific header options
382     // TODO-CA: CA is including non-vendor header options as well, like observe.
383     // Need to filter those out
384     GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &(requestInfo->info.numOptions));
385     printf("\n*****************************\nobservation is %u\n**********************************\n",serverRequest.observationOption);
386     if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
387     {
388         // TODO-CA: Need to send an error indicating the num of options is incorrect
389         return;
390     }
391     serverRequest.numRcvdVendorSpecificHeaderOptions = requestInfo->info.numOptions;
392     if (serverRequest.numRcvdVendorSpecificHeaderOptions)
393     {
394         memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
395             sizeof(CAHeaderOption_t)*requestInfo->info.numOptions);
396     }
397
398     requestResult = HandleStackRequests (&serverRequest);
399 #endif
400
401 #if 0
402     // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
403     memset(&responseData, 0, sizeof(CAInfo_t));
404     responseData.token = (requestInfo != NULL) ? requestInfo->info.token : "";
405
406     // TODO : I guess we need to allocate memeory?
407     responseData.payload = "{\"oc\":[{\"href\":\"/a/led\",\"sid\":\"\",\"prop\":{\"rt\":[\"core.led\"],\"if\":[\"oc.mi.def\"],\"obs\":1}}]}";
408
409     //responseInfo = (CAResponseInfo*) malloc(sizeof(CAResponseInfo));
410     memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
411     responseInfo.result = 200;
412     responseInfo.info = responseData;
413
414     // send request (connectivityType from remoteEndpoint of request Info)
415     OC_LOG(INFO, TAG, PCF("CASendResponse in HandleCARequests"));
416     //TODO-CA: CASendResponse returns the result (we need to check if the
417     // result is ok)
418     CAResult_t caResult = CASendResponse(endPoint, &responseInfo);
419     if(caResult != CA_STATUS_OK)
420     {
421         OC_LOG(ERROR, TAG, PCF("CASendResponse error"));
422     }
423 #endif
424
425     OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
426 }
427
428 #endif // CA_INT
429
430 //This function will be called back by occoap layer when a request is received
431 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
432 {
433     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
434
435     OCStackResult result = OC_STACK_ERROR;
436     ResourceHandling resHandling;
437     OCResource *resource;
438
439     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
440     if(!request)
441     {
442         OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
443 #ifdef CA_INT
444         result = AddServerCARequest(&request, protocolRequest->coapID,
445                 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
446                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
447                 protocolRequest->observationOption, protocolRequest->qos,
448                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
449                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
450                 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
451                 protocolRequest->reqTotalSize,
452                 &protocolRequest->addressInfo, protocolRequest->connectivityType, protocolRequest->token);
453 #else
454         result = AddServerRequest(&request, protocolRequest->coapID,
455                 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
456                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
457                 protocolRequest->observationOption, protocolRequest->qos,
458                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
459                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
460                 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
461                 protocolRequest->reqTotalSize);
462 #endif
463         if (OC_STACK_OK != result)
464         {
465             OC_LOG(ERROR, TAG, PCF("Error adding server request"));
466             return result;
467         }
468         VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
469
470         if(!protocolRequest->reqMorePacket)
471         {
472             request->requestComplete = 1;
473         }
474     }
475     else
476     {
477         OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
478     }
479
480     if(request->requestComplete)
481     {
482         OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
483         result = DetermineResourceHandling (request, &resHandling, &resource);
484         if (result == OC_STACK_OK)
485         {
486             result = ProcessRequest(resHandling, resource, request);
487         }
488         else
489         {
490             result = OC_STACK_ERROR;
491         }
492     }
493     else
494     {
495         OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
496         result = OC_STACK_CONTINUE;
497     }
498     return result;
499 }
500
501 //This function will be called back by occoap layer when a response is received
502 OCStackResult HandleStackResponses(OCResponse * response)
503 {
504     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
505     OCStackResult result = OC_STACK_OK;
506     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
507     uint8_t isObserveNotification = 0;
508     ClientCB * cbNode = NULL;
509     #ifdef WITH_PRESENCE
510     uint8_t isPresenceNotification = 0;
511     uint8_t isMulticastPresence = 0;
512     char * resourceTypeName = NULL;
513     uint32_t lowerBound = 0;
514     uint32_t higherBound = 0;
515     char * tok = NULL;
516     unsigned char * bufRes = response->bufRes;
517     #endif // WITH_PRESENCE
518
519     cbNode = response->cbNode;
520     if(!cbNode)
521     {
522         cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
523     }
524
525     if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
526     {
527         isObserveNotification = 1;
528         OC_LOG(INFO, TAG, PCF("Received an observe notification"));
529     }
530
531     OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
532             response->clientResponse->sequenceNumber);
533     OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
534     OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
535
536 #ifdef WITH_PRESENCE
537     if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
538         isPresenceNotification = 1;
539         if(!bufRes)
540         {
541             result = OC_STACK_INVALID_PARAM;
542             goto exit;
543         }
544         tok = strtok((char *)bufRes, "[:]}");
545         bufRes[strlen((char *)bufRes)] = ':';
546         tok = strtok(NULL, "[:]}");
547         bufRes[strlen((char *)bufRes)] = ':';
548         response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
549         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
550         tok = strtok(NULL, "[:]}");
551         response->maxAge = (uint32_t )atoi(tok);
552         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
553         tok = strtok(NULL, "[:]}");
554         if(tok)
555         {
556             resourceTypeName = (char *)OCMalloc(strlen(tok));
557             if(!resourceTypeName)
558             {
559                 goto exit;
560             }
561             bufRes[strlen((char *)bufRes)] = ':';
562             strcpy(resourceTypeName, tok);
563             OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
564                     resourceTypeName);
565         }
566         bufRes[strlen((char *)bufRes)] = ']';
567     }
568
569     // Check if the application subcribed for presence
570     if(!cbNode)
571     {
572         cbNode = GetClientCB(NULL, NULL, response->fullUri);
573     }
574
575     // Check if application subscribed for multicast presence
576     if(!cbNode)
577     {
578         snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
579                 OC_MULTICAST_IP, response->rcvdUri);
580         cbNode = GetClientCB(NULL, NULL, response->fullUri);
581         if(cbNode)
582         {
583             isMulticastPresence = 1;
584             isPresenceNotification = 0;
585         }
586     }
587
588     if(cbNode && isPresenceNotification)
589     {
590         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
591         if(!cbNode->presence)
592         {
593             cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
594             VERIFY_NON_NULL_V(cbNode->presence);
595             cbNode->presence->timeOut = NULL;
596             cbNode->presence->timeOut = (uint32_t *)
597                     OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
598             if(!(cbNode->presence->timeOut)){
599                 OCFree(cbNode->presence);
600                 result = OC_STACK_NO_MEMORY;
601             }
602         }
603         if(response->maxAge == 0)
604         {
605             OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
606             response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
607             if(cbNode->presence)
608             {
609                 OCFree(cbNode->presence->timeOut);
610                 OCFree(cbNode->presence);
611                 cbNode->presence = NULL;
612             }
613         }
614         else
615         {
616             OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
617             cbNode->presence->TTL = response->maxAge;
618             for(int index = 0; index < PresenceTimeOutSize; index++)
619             {
620                 lowerBound = GetTime(((float)(PresenceTimeOut[index])
621                         /(float)100)*(float)cbNode->presence->TTL);
622                 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
623                         /(float)100)*(float)cbNode->presence->TTL);
624                 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
625                 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
626                 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
627                 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
628                         cbNode->presence->timeOut[index]);
629             }
630             cbNode->presence->TTLlevel = 0;
631             OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
632             if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
633             {
634                 OC_LOG(INFO, TAG, PCF("===============No presence change"));
635                 goto exit;
636             }
637             OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
638             cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
639         }
640
641         // Ensure that a filter is actually applied.
642         if(resourceTypeName && cbNode->filterResourceType)
643         {
644             if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
645             {
646                 goto exit;
647             }
648         }
649     }
650     else if(cbNode && isMulticastPresence)
651     {
652         // Check if the same nonce for a given host
653         OCMulticastNode* mcNode = NULL;
654         mcNode = GetMCPresenceNode(response->fullUri);
655
656         if(response->maxAge == 0)
657         {
658             OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
659             response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
660             if(cbNode->presence)
661             {
662                 OCFree(cbNode->presence->timeOut);
663                 OCFree(cbNode->presence);
664                 cbNode->presence = NULL;
665             }
666         }
667         else if(mcNode != NULL)
668         {
669             if(mcNode->nonce == response->clientResponse->sequenceNumber)
670             {
671                 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
672                 result = OC_STACK_NO_MEMORY;
673                 goto exit;
674             }
675             mcNode->nonce = response->clientResponse->sequenceNumber;
676         }
677         else
678         {
679             uint32_t uriLen = strlen((char*)response->fullUri);
680             unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
681             if(uri)
682             {
683                 memcpy(uri, response->fullUri, (uriLen + 1));
684             }
685             else
686             {
687                 OC_LOG(INFO, TAG,
688                     PCF("===============No Memory for URI to store in the presence node"));
689                 result = OC_STACK_NO_MEMORY;
690                 goto exit;
691             }
692             result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
693                     response->clientResponse->sequenceNumber);
694             if(result == OC_STACK_NO_MEMORY)
695             {
696                 OC_LOG(INFO, TAG,
697                     PCF("===============No Memory for Multicast Presence Node"));
698                 result = OC_STACK_NO_MEMORY;
699                 goto exit;
700             }
701         }
702
703         // Ensure that a filter is actually applied.
704         if(resourceTypeName && cbNode->filterResourceType)
705         {
706             if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
707             {
708                 goto exit;
709             }
710         }
711     }
712
713     else if(!cbNode && isPresenceNotification)
714     {
715     OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
716                  ------------ ignoring"));
717     }
718     #endif // WITH_PRESENCE
719
720     if(cbNode)
721     {
722         if(isObserveNotification)
723         {
724             OC_LOG(INFO, TAG, PCF("Received an observe notification"));
725             //TODO: check the standard for methods to detect wrap around condition
726             if(cbNode->method == OC_REST_OBSERVE &&
727                     (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
728                             (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
729                                     response->clientResponse->sequenceNumber ==
730                                             MAX_SEQUENCE_NUMBER)))
731             {
732                 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
733                         Ignoring Incoming:%d  Against Current:%d.",
734                         response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
735                 goto exit;
736             }
737             if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
738                 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
739             }
740         }
741
742         response->clientResponse->resJSONPayload = bufRes;
743
744         cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
745
746         if (cbResult == OC_STACK_DELETE_TRANSACTION ||
747                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
748                 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
749                         !isPresenceNotification && !isMulticastPresence))
750         {
751             FindAndDeleteClientCB(cbNode);
752         }
753     }
754     else
755     {
756         result = OC_STACK_ERROR;
757     }
758
759     exit:
760     #ifdef WITH_PRESENCE
761     OCFree(resourceTypeName);
762     #endif
763     return result;
764 }
765
766 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
767 {
768     size_t index = 0;
769     unsigned char *itr, *coap;
770     uint8_t dotCount = 0;
771
772     ipAddr[index] = 0;
773     *port = 0;
774     /* search for scheme */
775     itr = ipAddrStr;
776     if (!isdigit((unsigned char) *ipAddrStr))
777     {
778         coap = (unsigned char *) OC_COAP_SCHEME;
779         while (*coap && tolower(*itr) == *coap)
780         {
781             coap++;
782             itr++;
783         }
784     }
785     ipAddrStr = itr;
786
787     while (*ipAddrStr) {
788         if (isdigit((unsigned char) *ipAddrStr))
789         {
790             ipAddr[index] *= 10;
791             ipAddr[index] += *ipAddrStr - '0';
792         }
793         else if ((unsigned char) *ipAddrStr == '.')
794         {
795             index++;
796             dotCount++;
797             ipAddr[index] = 0;
798         }
799         else
800         {
801             break;
802         }
803         ipAddrStr++;
804     }
805     if(*ipAddrStr == ':')
806     {
807         ipAddrStr++;
808         while (*ipAddrStr){
809             if (isdigit((unsigned char) *ipAddrStr))
810             {
811                 *port *= 10;
812                 *port += *ipAddrStr - '0';
813             }
814             else
815             {
816                 break;
817             }
818             ipAddrStr++;
819         }
820     }
821
822
823     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
824             && dotCount == 3)
825     {
826         return 1;
827     }
828     else
829     {
830         return 0;
831     }
832 }
833
834 //-----------------------------------------------------------------------------
835 // Private internal function prototypes
836 //-----------------------------------------------------------------------------
837
838 static OCDoHandle GenerateInvocationHandle();
839 static OCStackResult initResources();
840 static void insertResource(OCResource *resource);
841 static OCResource *findResource(OCResource *resource);
842 static void insertResourceType(OCResource *resource,
843         OCResourceType *resourceType);
844 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
845         uint8_t index);
846 static void insertResourceInterface(OCResource *resource,
847         OCResourceInterface *resourceInterface);
848 static OCResourceInterface *findResourceInterfaceAtIndex(
849         OCResourceHandle handle, uint8_t index);
850 static void deleteResourceType(OCResourceType *resourceType);
851 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
852 static void deleteResourceElements(OCResource *resource);
853 static int deleteResource(OCResource *resource);
854 static void deleteAllResources();
855 static void incrementSequenceNumber(OCResource * resPtr);
856 static OCStackResult verifyUriQueryLength(const char * inputUri,
857         uint16_t uriLen);
858 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
859 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
860
861 //-----------------------------------------------------------------------------
862 // Public APIs
863 //-----------------------------------------------------------------------------
864
865 /**
866  * Initialize the OC Stack.  Must be called prior to starting the stack.
867  *
868  * @param ipAddr
869  *     IP Address of host device
870  * @param port
871  *     Port of host device
872  * @param mode
873  *     Host device is client, server, or client-server
874  *
875  * @return
876  *     OC_STACK_OK    - no errors
877  *     OC_STACK_ERROR - stack init error
878  */
879 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
880 {
881     OCStackResult result = OC_STACK_ERROR;
882     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
883
884     if (ipAddr)
885     {
886         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
887     }
888 #ifdef CA_INT
889     CAInitialize();
890     //It is ok to select network to CA_WIFI for now
891     CAResult_t caResult = CASelectNetwork(CA_WIFI);
892     if(caResult == CA_STATUS_OK)
893     {
894         OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
895         caResult = CARegisterHandler(HandleCARequests, HandleCAResponses);
896         if(caResult == CA_STATUS_OK)
897         {
898             OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
899             stackState = OC_STACK_INITIALIZED;
900             result = OC_STACK_OK;
901             switch (mode)
902             {
903                 case OC_CLIENT:
904                     caResult = CAStartDiscoveryServer();
905                     OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
906                     break;
907                 case OC_SERVER:
908                     caResult = CAStartListeningServer();
909                     OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
910                     break;
911                 case OC_CLIENT_SERVER:
912                     caResult = CAStartListeningServer();
913                     if(caResult == CA_STATUS_OK)
914                     {
915                         caResult = CAStartDiscoveryServer();
916                     }
917                     OC_LOG(INFO, TAG, PCF("Client-server mode"));
918                     break;
919                 default:
920                     OC_LOG(ERROR, TAG, PCF("Invalid mode"));
921                     return OC_STACK_ERROR;
922                     break;
923             }
924
925         }
926         if (caResult == CA_STATUS_OK)
927         {
928             result = OC_STACK_OK;
929         }
930         else
931         {
932             result = OC_STACK_ERROR;
933         }
934     }
935 #else
936     switch (mode)
937     {
938     case OC_CLIENT:
939         OC_LOG(INFO, TAG, PCF("Client mode"));
940         break;
941     case OC_SERVER:
942         OC_LOG(INFO, TAG, PCF("Server mode"));
943         break;
944     case OC_CLIENT_SERVER:
945         OC_LOG(INFO, TAG, PCF("Client-server mode"));
946         break;
947     default:
948         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
949         return OC_STACK_ERROR;
950         break;
951     }
952
953     // Make call to OCCoAP layer
954     result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
955 #endif //CA_INT
956
957     myStackMode = mode;
958     defaultDeviceHandler = NULL;
959
960 #ifdef WITH_PRESENCE
961     PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
962 #endif // WITH_PRESENCE
963
964     if (result == OC_STACK_OK)
965     {
966         stackState = OC_STACK_INITIALIZED;
967     }
968     // Initialize resource
969     if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
970     {
971         result = initResources();
972     }
973     if(result != OC_STACK_OK)
974     {
975         OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
976     }
977     return result;
978 }
979
980 /**
981  * Stop the OC stack.  Use for a controlled shutdown.
982  * @return
983  *     OC_STACK_OK    - no errors
984  *     OC_STACK_ERROR - stack not initialized
985  */
986 OCStackResult OCStop()
987 {
988     OCStackResult result = OC_STACK_ERROR;
989
990     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
991
992     if (stackState != OC_STACK_INITIALIZED)
993     {
994         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
995         return OC_STACK_ERROR;
996     }
997
998     #ifdef WITH_PRESENCE
999     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1000     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1001     presenceResource.presenceTTL = 0;
1002     #endif // WITH_PRESENCE
1003
1004     // Free memory dynamically allocated for resources
1005     deleteAllResources();
1006
1007     // Make call to OCCoAP layer
1008     if (OCStopCoAP() == OC_STACK_OK)
1009     {
1010         // Remove all observers
1011         DeleteObserverList();
1012         // Remove all the client callbacks
1013         DeleteClientCBList();
1014         stackState = OC_STACK_UNINITIALIZED;
1015         result = OC_STACK_OK;
1016     } else {
1017         result = OC_STACK_ERROR;
1018     }
1019
1020     // Deinit security blob
1021     DeinitOCSecurityInfo();
1022
1023     if (result != OC_STACK_OK) {
1024         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1025     }
1026
1027     return result;
1028 }
1029
1030 /**
1031  * Verify the lengths of the URI and the query separately
1032  *
1033  * @param inputUri       - Input URI and query.
1034  * @param uriLen         - The length of the initial URI with query.
1035  *
1036  * Note: The '?' that appears after the URI is not considered as
1037  * a part of the query.
1038  */
1039 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1040 {
1041     char *query;
1042
1043     query = strchr (inputUri, '?');
1044
1045     if (query != NULL)
1046     {
1047         if((query - inputUri) > MAX_URI_LENGTH)
1048         {
1049             return OC_STACK_INVALID_URI;
1050         }
1051
1052         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1053         {
1054             return OC_STACK_INVALID_QUERY;
1055         }
1056     }
1057     else if(uriLen > MAX_URI_LENGTH)
1058     {
1059         return OC_STACK_INVALID_URI;
1060     }
1061     return OC_STACK_OK;
1062 }
1063
1064 /**
1065  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
1066  *
1067  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
1068  * @param method             - @ref OCMethod to perform on the resource
1069  * @param requiredUri        - URI of the resource to interact with
1070  * @param referenceUri       - URI of the reference resource
1071  * @param request            - JSON encoded request
1072  * @param qos                - quality of service
1073  * @param cbData             - struct that contains asynchronous callback function that is invoked
1074  *                             by the stack when discovery or resource interaction is complete
1075  * @param options            - The address of an array containing the vendor specific header
1076  *                             header options to be sent with the request
1077  * @param numOptions         - Number of vendor specific header options to be included
1078  *
1079  * @return
1080  *     OC_STACK_OK               - no errors
1081  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1082  *     OC_STACK_INVALID_METHOD   - invalid resource method
1083  *     OC_STACK_INVALID_URI      - invalid required or reference URI
1084  */
1085
1086 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1087                            const char *referenceUri, const char *request,
1088                            OCQualityOfService qos, OCCallbackData *cbData,
1089                            OCHeaderOption * options, uint8_t numOptions)
1090 {
1091     OCStackResult result = OC_STACK_ERROR;
1092     OCCoAPToken token;
1093     ClientCB *clientCB = NULL;
1094     unsigned char * requestUri = NULL;
1095     unsigned char * resourceType = NULL;
1096     char * newUri = (char *)requiredUri;
1097     (void) referenceUri;
1098 #ifdef CA_INT
1099     CARemoteEndpoint_t* endpoint = NULL;
1100     CAResult_t caResult;
1101     CAToken_t caToken = NULL;
1102     CAInfo_t requestData;
1103     CARequestInfo_t requestInfo;
1104     // To track if memory is allocated for additional header options
1105     uint8_t hdrOptionMemAlloc = 0;
1106 #endif // CA_INT
1107
1108     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1109
1110     // Validate input parameters
1111     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1112     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1113
1114     TODO ("Need to form the final query by concatenating require and reference URI's");
1115     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1116
1117     uint16_t uriLen = strlen(requiredUri);
1118
1119     // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
1120     switch (method)
1121     {
1122         case OC_REST_GET:
1123         case OC_REST_PUT:
1124         case OC_REST_POST:
1125         case OC_REST_DELETE:
1126         case OC_REST_OBSERVE:
1127         case OC_REST_OBSERVE_ALL:
1128         case OC_REST_CANCEL_OBSERVE:
1129             break;
1130         #ifdef WITH_PRESENCE
1131         case OC_REST_PRESENCE:
1132             break;
1133         #endif
1134         default:
1135             result = OC_STACK_INVALID_METHOD;
1136             goto exit;
1137     }
1138
1139     if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1140     {
1141         goto exit;
1142     }
1143
1144     if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1145     {
1146         result = OC_STACK_INVALID_PARAM;
1147         goto exit;
1148     }
1149
1150 #ifdef WITH_PRESENCE
1151     if(method == OC_REST_PRESENCE)
1152     {
1153         result = getResourceType(requiredUri, &resourceType, &newUri);
1154         if(resourceType) {
1155             OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1156         }
1157         else
1158         {
1159             OC_LOG(DEBUG, TAG, PCF("Got Resource Type is NULL."));
1160         }
1161         if(result != OC_STACK_OK)
1162         {
1163             goto exit;
1164         }
1165     }
1166 #endif // WITH_PRESENCE
1167
1168     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1169     if(requestUri)
1170     {
1171         memcpy(requestUri, newUri, (uriLen + 1));
1172     }
1173     else
1174     {
1175         result = OC_STACK_NO_MEMORY;
1176         goto exit;
1177     }
1178
1179     *handle = GenerateInvocationHandle();
1180     if(!*handle)
1181     {
1182         result = OC_STACK_NO_MEMORY;
1183         goto exit;
1184     }
1185
1186 #ifdef CA_INT
1187     memset(&requestData, 0, sizeof(CAInfo_t));
1188     memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1189     switch (method)
1190     {
1191         case OC_REST_GET:
1192         case OC_REST_OBSERVE:
1193         case OC_REST_OBSERVE_ALL:
1194         case OC_REST_CANCEL_OBSERVE:
1195             {
1196                 requestInfo.method = CA_GET;
1197                 break;
1198             }
1199         case OC_REST_PUT:
1200             {
1201                 requestInfo.method = CA_PUT;
1202                 break;
1203             }
1204         case OC_REST_POST:
1205             {
1206                 requestInfo.method = CA_POST;
1207                 break;
1208             }
1209         case OC_REST_DELETE:
1210             {
1211                 requestInfo.method = CA_DELETE;
1212                 break;
1213             }
1214         #ifdef WITH_PRESENCE
1215         case OC_REST_PRESENCE:
1216             //TODO-CA: What should be the CA method?
1217             break;
1218         #endif
1219         default:
1220             result = OC_STACK_INVALID_METHOD;
1221             goto exit;
1222     }
1223
1224     // TODO-CA: Handle multi-cast scenario
1225     // Create remote end point
1226     caResult = CACreateRemoteEndpoint(newUri, CA_WIFI, &endpoint);
1227     // TODO-CA: Connectivity type should be passed to API
1228     endpoint->connectivityType = CA_WIFI;
1229     if (caResult != CA_STATUS_OK)
1230     {
1231         OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1232         goto exit;
1233     }
1234
1235     // create token
1236     caResult = CAGenerateToken(&caToken);
1237
1238     if (caResult != CA_STATUS_OK)
1239     {
1240         OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1241         caToken = NULL;
1242         goto exit;
1243     }
1244
1245     // TODO-CA: Map QoS to the right CA msg type
1246     requestData.type = CA_MSG_NONCONFIRM;
1247     requestData.token = caToken;
1248     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1249     {
1250         result = CreateObserveHeaderOption (&(requestData.options), options, 
1251                                     numOptions, OC_OBSERVE_REGISTER);
1252         if (result != OC_STACK_OK)
1253         {
1254             goto exit;
1255         }
1256         hdrOptionMemAlloc = 1;
1257         requestData.numOptions = numOptions + 1;
1258     }
1259     else
1260     {
1261         requestData.options = (CAHeaderOption_t*)options;
1262         requestData.numOptions = numOptions;
1263     }
1264     requestData.payload = (char *)request;
1265
1266     requestInfo.info = requestData;
1267
1268     // send request
1269     caResult = CASendRequest(endpoint, &requestInfo);
1270     if (caResult != CA_STATUS_OK)
1271     {
1272         OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1273         goto exit;
1274     }
1275
1276     if((result = AddClientCB(&clientCB, cbData, &caToken, handle, method,
1277                              requestUri, resourceType)) != OC_STACK_OK)
1278     {
1279         result = OC_STACK_NO_MEMORY;
1280         goto exit;
1281     }
1282
1283 #else // CA_INT
1284
1285     // Generate token which will be used by OCStack to match responses received
1286     // with the request
1287     OCGenerateCoAPToken(&token);
1288
1289     if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
1290             != OC_STACK_OK)
1291     {
1292         result = OC_STACK_NO_MEMORY;
1293         goto exit;
1294     }
1295
1296 #ifdef WITH_PRESENCE
1297     if(method == OC_REST_PRESENCE)
1298     {
1299         // Replacing method type with GET because "presence" is a stack layer only implementation.
1300         method = OC_REST_GET;
1301     }
1302 #endif
1303
1304     // Make call to OCCoAP layer
1305     result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
1306 #endif // CA_INT
1307
1308 exit:
1309     if(newUri != requiredUri)
1310     {
1311         OCFree(newUri);
1312     }
1313     if (result != OC_STACK_OK)
1314     {
1315         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1316         FindAndDeleteClientCB(clientCB);
1317     }
1318 #ifdef CA_INT
1319     CADestroyRemoteEndpoint(endpoint);
1320     if (hdrOptionMemAlloc)
1321     {
1322         OCFree(requestData.options);
1323     }
1324     //TODO-CA: CADestroyToken here
1325 #endif // CA_INT
1326     return result;
1327 }
1328
1329 /**
1330  * Cancel a request associated with a specific @ref OCDoResource invocation.
1331  *
1332  * @param handle - Used to identify a specific OCDoResource invocation.
1333  * @param qos    - used to specify Quality of Service (read below for more info)
1334  * @param options- used to specify vendor specific header options when sending
1335  *                 explicit observe cancellation
1336  * @param numOptions- Number of header options to be included
1337  *
1338  * @return
1339  *     OC_STACK_OK               - No errors; Success
1340  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
1341  */
1342 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1343         uint8_t numOptions) {
1344     /*
1345      * This ftn is implemented one of two ways in the case of observation:
1346      *
1347      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1348      *      Remove the callback associated on client side.
1349      *      When the next notification comes in from server,
1350      *      reply with RESET message to server.
1351      *      Keep in mind that the server will react to RESET only
1352      *      if the last notification was sent ans CON
1353      *
1354      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1355      *      and it is associated with an observe request
1356      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1357      *      Send CON Observe request to server with
1358      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1359      *      Remove the callback associated on client side.
1360      */
1361     OCStackResult ret = OC_STACK_OK;
1362
1363     if(!handle) {
1364         return OC_STACK_INVALID_PARAM;
1365     }
1366
1367     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1368
1369     ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1370
1371     if(clientCB) {
1372         switch (clientCB->method)
1373         {
1374             case OC_REST_OBSERVE:
1375             case OC_REST_OBSERVE_ALL:
1376                 if(qos == OC_HIGH_QOS)
1377                 {
1378                     ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
1379                             &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
1380                             numOptions);
1381                 }
1382                 else
1383                 {
1384                     FindAndDeleteClientCB(clientCB);
1385                 }
1386                 break;
1387             #ifdef WITH_PRESENCE
1388             case OC_REST_PRESENCE:
1389                 FindAndDeleteClientCB(clientCB);
1390                 break;
1391             #endif
1392             default:
1393                 return OC_STACK_INVALID_METHOD;
1394         }
1395     }
1396     return ret;
1397 }
1398 #ifdef WITH_PRESENCE
1399 OCStackResult OCProcessPresence()
1400 {
1401     OCStackResult result = OC_STACK_OK;
1402     uint8_t ipAddr[4] = { 0 };
1403     uint16_t port = 0;
1404
1405     OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1406     ClientCB* cbNode = NULL;
1407     OCDevAddr dst;
1408     OCClientResponse clientResponse;
1409     OCResponse * response = NULL;
1410
1411     LL_FOREACH(cbList, cbNode) {
1412         if(OC_REST_PRESENCE == cbNode->method)
1413         {
1414             if(cbNode->presence)
1415             {
1416                 uint32_t now = GetTime(0);
1417                 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1418                 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1419
1420
1421                 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1422                 {
1423                     goto exit;
1424                 }
1425
1426                 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1427                     OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1428                             cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1429                 }
1430
1431                 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1432                 {
1433                     OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1434                     if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1435                     {
1436                         OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1437                                 &dst);
1438                         result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
1439                                 (OCDevAddr *) &dst, 0, NULL);
1440                         if(result != OC_STACK_OK)
1441                         {
1442                             goto exit;
1443                         }
1444                         result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1445                                 &cbNode->token, &clientResponse, NULL);
1446                         if(result != OC_STACK_OK)
1447                         {
1448                             goto exit;
1449                         }
1450
1451                         // Increment the TTLLevel (going to a next state), so we don't keep
1452                         // sending presence notification to client.
1453                         cbNode->presence->TTLlevel++;
1454                         OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1455                                                 cbNode->presence->TTLlevel);
1456                     }
1457                     else
1458                     {
1459                         result = OC_STACK_INVALID_IP;
1460                         goto exit;
1461                     }
1462                     HandleStackResponses(response);
1463                 }
1464                 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1465                 {
1466                     OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1467                     OCCoAPToken token;
1468                     OCGenerateCoAPToken(&token);
1469                     result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
1470                             &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
1471                     if(result != OC_STACK_OK)
1472                     {
1473                         goto exit;
1474                     }
1475                     cbNode->presence->TTLlevel++;
1476                     OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
1477                 }
1478             }
1479         }
1480     }
1481 exit:
1482     if (result != OC_STACK_OK)
1483     {
1484         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1485     }
1486     return result;
1487 }
1488 #endif
1489
1490 /**
1491  * Called in main loop of OC client or server.  Allows low-level processing of
1492  * stack services.
1493  *
1494  * @return
1495  *     OC_STACK_OK    - no errors
1496  *     OC_STACK_ERROR - stack process error
1497  */
1498 OCStackResult OCProcess() {
1499
1500     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
1501     #ifdef WITH_PRESENCE
1502     OCProcessPresence();
1503     #endif
1504 #ifdef CA_INT
1505     CAHandleRequestResponse();
1506 #else
1507     OCProcessCoAP();
1508 #endif // CA_INT
1509
1510     return OC_STACK_OK;
1511 }
1512
1513 #ifdef WITH_PRESENCE
1514 /**
1515  * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
1516  * presence notifications to clients via multicast. Once this API has been called with a success,
1517  * clients may query for this server's presence and this server's stack will respond via multicast.
1518  *
1519  * Server can call this function when it comes online for the first time, or when it comes back
1520  * online from offline mode, or when it re enters network.
1521  *
1522  * @param ttl - Time To Live in seconds
1523  * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
1524  *
1525  * @return
1526  *     OC_STACK_OK      - No errors; Success
1527  */
1528 OCStackResult OCStartPresence(const uint32_t ttl)
1529 {
1530     OCChangeResourceProperty(
1531             &(((OCResource *)presenceResource.handle)->resourceProperties),
1532             OC_ACTIVE, 1);
1533
1534     if(ttl > 0)
1535     {
1536         presenceResource.presenceTTL = ttl;
1537     }
1538
1539     if(OC_PRESENCE_UNINITIALIZED == presenceState)
1540     {
1541         OCDevAddr multiCastAddr;
1542         OCCoAPToken token;
1543
1544         presenceState = OC_PRESENCE_INITIALIZED;
1545         OCGenerateCoAPToken(&token);
1546         OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
1547         //add the presence observer
1548         AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
1549             (OCResource *)presenceResource.handle, OC_LOW_QOS);
1550     }
1551
1552     // Each time OCStartPresence is called
1553     // a different random 32-bit integer number is used
1554     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1555
1556     return SendPresenceNotification(NULL);
1557 }
1558
1559 /**
1560  * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
1561  * presence notifications to clients via multicast. Once this API has been called with a success,
1562  * this server's stack will not respond to clients querying for this server's presence.
1563  *
1564  * Server can call this function when it is terminating, going offline, or when going
1565  * away from network.
1566  *
1567  * @return
1568  *     OC_STACK_OK      - No errors; Success
1569  */
1570 OCStackResult OCStopPresence()
1571 {
1572     OCStackResult result = OC_STACK_ERROR;
1573     //make resource inactive
1574     result = OCChangeResourceProperty(
1575             &(((OCResource *) presenceResource.handle)->resourceProperties),
1576             OC_ACTIVE, 0);
1577     result = SendPresenceNotification(NULL);
1578
1579     return result;
1580 }
1581 #endif
1582
1583
1584 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
1585 {
1586     defaultDeviceHandler = entityHandler;
1587
1588     return OC_STACK_OK;
1589 }
1590
1591 /**
1592  * Create a resource
1593  *
1594  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
1595  * @param resourceTypeName - name of resource type.  Example: "core.led"
1596  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1597  * @param uri - URI of the resource.  Example:  "/a/led"
1598  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1599  *                        NULL for default entity handler
1600  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
1601  *
1602  * @return
1603  *     OC_STACK_OK    - no errors
1604  *     OC_STACK_ERROR - stack process error
1605  */
1606 OCStackResult OCCreateResource(OCResourceHandle *handle,
1607         const char *resourceTypeName,
1608         const char *resourceInterfaceName,
1609         const char *uri, OCEntityHandler entityHandler,
1610         uint8_t resourceProperties) {
1611
1612     OCResource *pointer = NULL;
1613     char *str = NULL;
1614     size_t size;
1615     OCStackResult result = OC_STACK_ERROR;
1616
1617     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
1618
1619     if(myStackMode == OC_CLIENT)
1620     {
1621         return result;
1622     }
1623     // Validate parameters
1624     // Is it presented during resource discovery?
1625     if (!handle || !resourceTypeName || !uri) {
1626         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
1627         return OC_STACK_INVALID_PARAM;
1628     }
1629
1630     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
1631         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
1632     }
1633
1634     // Make sure resourceProperties bitmask has allowed properties specified
1635     if (resourceProperties
1636             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
1637         OC_LOG(ERROR, TAG, PCF("Invalid property"));
1638         return OC_STACK_INVALID_PARAM;
1639     }
1640
1641     // If the headResource is NULL, then no resources have been created...
1642     pointer = headResource;
1643     if (pointer) {
1644         // At least one resources is in the resource list, so we need to search for
1645         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
1646         while (pointer) {
1647             if (strcmp(uri, pointer->uri) == 0) {
1648                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
1649                 return OC_STACK_INVALID_PARAM;
1650             }
1651             pointer = pointer->next;
1652         }
1653     }
1654     // Create the pointer and insert it into the resource list
1655     pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
1656     if (!pointer) {
1657         goto exit;
1658     }
1659     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
1660
1661     insertResource(pointer);
1662
1663     // Set the uri
1664     size = strlen(uri) + 1;
1665     str = (char *) OCMalloc(size);
1666     if (!str) {
1667         goto exit;
1668     }
1669     strncpy(str, uri, size);
1670     pointer->uri = str;
1671
1672     // Set properties.  Set OC_ACTIVE
1673     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
1674             | OC_ACTIVE);
1675
1676     // Add the resourcetype to the resource
1677     result = BindResourceTypeToResource(pointer, resourceTypeName);
1678     if (result != OC_STACK_OK) {
1679         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
1680         goto exit;
1681     }
1682
1683     // Add the resourceinterface to the resource
1684     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
1685     if (result != OC_STACK_OK) {
1686         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
1687         goto exit;
1688     }
1689
1690     // If an entity handler has been passed, attach it to the newly created
1691     // resource.  Otherwise, set the default entity handler.
1692     if (entityHandler)
1693     {
1694         pointer->entityHandler = entityHandler;
1695     }
1696     else
1697     {
1698         pointer->entityHandler = defaultResourceEHandler;
1699     }
1700
1701     *handle = pointer;
1702     result = OC_STACK_OK;
1703
1704     #ifdef WITH_PRESENCE
1705     if(presenceResource.handle)
1706     {
1707         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1708         SendPresenceNotification(pointer->rsrcType);
1709     }
1710     #endif
1711 exit:
1712     if (result != OC_STACK_OK)
1713     {
1714         // Deep delete of resource and other dynamic elements that it contains
1715         deleteResource(pointer);
1716         OCFree(str);
1717     }
1718     return result;
1719 }
1720
1721
1722
1723 /**
1724  * Create a resource. with host ip address for remote resource
1725  *
1726  * @param handle - pointer to handle to newly created resource.  Set by ocstack.
1727  *                 Used to refer to resource
1728  * @param resourceTypeName - name of resource type.  Example: "core.led"
1729  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1730  * @param host - HOST address of the remote resource.  Example:  "coap://xxx.xxx.xxx.xxx:xxxxx"
1731  * @param uri - URI of the resource.  Example:  "/a/led"
1732  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1733  *                        NULL for default entity handler
1734  * @param resourceProperties - properties supported by resource.
1735  *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
1736  *
1737  * @return
1738  *     OC_STACK_OK    - no errors
1739  *     OC_STACK_ERROR - stack process error
1740  */
1741
1742 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
1743         const char *resourceTypeName,
1744         const char *resourceInterfaceName,
1745         const char *host,
1746         const char *uri,
1747         OCEntityHandler entityHandler,
1748         uint8_t resourceProperties)
1749 {
1750     char *str = NULL;
1751     size_t size;
1752     OCStackResult result = OC_STACK_ERROR;
1753
1754     result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
1755                                 uri, entityHandler, resourceProperties);
1756
1757     if (result != OC_STACK_ERROR)
1758     {
1759         // Set the uri
1760         size = strlen(host) + 1;
1761         str = (char *) OCMalloc(size);
1762         if (!str)
1763         {
1764             return OC_STACK_ERROR;
1765         }
1766         strncpy(str, host, size);
1767         ((OCResource *) *handle)->host = str;
1768     }
1769
1770     return result;
1771 }
1772
1773 /**
1774  * Add a resource to a collection resource.
1775  *
1776  * @param collectionHandle - handle to the collection resource
1777  * @param resourceHandle - handle to resource to be added to the collection resource
1778  *
1779  * @return
1780  *     OC_STACK_OK    - no errors
1781  *     OC_STACK_ERROR - stack process error
1782  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
1783  */
1784 OCStackResult OCBindResource(
1785         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1786     OCResource *resource;
1787     uint8_t i;
1788
1789     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
1790
1791     // Validate parameters
1792     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1793     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1794     // Container cannot contain itself
1795     if (collectionHandle == resourceHandle) {
1796         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
1797         return OC_STACK_INVALID_PARAM;
1798     }
1799
1800     // Use the handle to find the resource in the resource linked list
1801     resource = findResource((OCResource *) collectionHandle);
1802     if (!resource) {
1803         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1804         return OC_STACK_INVALID_PARAM;
1805     }
1806
1807     // Look for an open slot to add add the child resource.
1808     // If found, add it and return success
1809     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1810         if (!resource->rsrcResources[i]) {
1811             resource->rsrcResources[i] = (OCResource *) resourceHandle;
1812             OC_LOG(INFO, TAG, PCF("resource bound"));
1813             return OC_STACK_OK;
1814         }
1815     }
1816
1817     #ifdef WITH_PRESENCE
1818     if(presenceResource.handle)
1819     {
1820         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1821         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1822     }
1823     #endif
1824
1825     // Unable to add resourceHandle, so return error
1826     return OC_STACK_ERROR;
1827 }
1828
1829 /**
1830  * Remove a resource from a collection resource.
1831  *
1832  * @param collectionHandle - handle to the collection resource
1833  * @param resourceHandle - handle to resource to be added to the collection resource
1834  *
1835  * @return
1836  *     OC_STACK_OK    - no errors
1837  *     OC_STACK_ERROR - stack process error
1838  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
1839  */
1840 OCStackResult OCUnBindResource(
1841         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1842     OCResource *resource;
1843     uint8_t i;
1844
1845     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
1846
1847     // Validate parameters
1848     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1849     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1850     // Container cannot contain itself
1851     if (collectionHandle == resourceHandle) {
1852         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
1853         return OC_STACK_INVALID_PARAM;
1854     }
1855
1856     // Use the handle to find the resource in the resource linked list
1857     resource = findResource((OCResource *) collectionHandle);
1858     if (!resource) {
1859         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1860         return OC_STACK_INVALID_PARAM;
1861     }
1862
1863     // Look for an open slot to add add the child resource.
1864     // If found, add it and return success
1865     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1866         if (resourceHandle == resource->rsrcResources[i]) {
1867             resource->rsrcResources[i] = (OCResource *) NULL;
1868             OC_LOG(INFO, TAG, PCF("resource unbound"));
1869             return OC_STACK_OK;
1870         }
1871     }
1872
1873     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
1874
1875     #ifdef WITH_PRESENCE
1876     if(presenceResource.handle)
1877     {
1878         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1879         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1880     }
1881     #endif
1882
1883     // Unable to add resourceHandle, so return error
1884     return OC_STACK_ERROR;
1885 }
1886
1887 OCStackResult BindResourceTypeToResource(OCResource* resource,
1888                                             const char *resourceTypeName)
1889 {
1890     OCResourceType *pointer = NULL;
1891     char *str = NULL;
1892     size_t size;
1893     OCStackResult result = OC_STACK_ERROR;
1894
1895     OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
1896
1897     // Validate parameters
1898     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
1899     // TODO:  Does resource attribute resentation really have to be maintained in stack?
1900     // Is it presented during resource discovery?
1901
1902     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
1903
1904     // Create the resourcetype and insert it into the resource list
1905     pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
1906     if (!pointer) {
1907         goto exit;
1908     }
1909
1910     // Set the resourceTypeName
1911     size = strlen(resourceTypeName) + 1;
1912     str = (char *) OCMalloc(size);
1913     if (!str) {
1914         goto exit;
1915     }
1916     strncpy(str, resourceTypeName, size);
1917     pointer->resourcetypename = str;
1918
1919     insertResourceType(resource, pointer);
1920     result = OC_STACK_OK;
1921
1922     exit: if (result != OC_STACK_OK) {
1923         OCFree(pointer);
1924         OCFree(str);
1925     }
1926
1927     return result;
1928 }
1929
1930 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
1931         const char *resourceInterfaceName)
1932 {
1933     OCResourceInterface *pointer = NULL;
1934     char *str = NULL;
1935     size_t size;
1936     OCStackResult result = OC_STACK_ERROR;
1937
1938     OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
1939
1940     // Validate parameters
1941     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1942
1943     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1944
1945     // Create the resourceinterface and insert it into the resource list
1946     pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
1947     if (!pointer) {
1948         goto exit;
1949     }
1950
1951     // Set the resourceinterface name
1952     size = strlen(resourceInterfaceName) + 1;
1953     str = (char *) OCMalloc(size);
1954     if (!str) {
1955         goto exit;
1956     }
1957     strncpy(str, resourceInterfaceName, size);
1958     pointer->name = str;
1959
1960     // Bind the resourceinterface to the resource
1961     insertResourceInterface(resource, pointer);
1962
1963     result = OC_STACK_OK;
1964
1965     exit: if (result != OC_STACK_OK) {
1966         OCFree(pointer);
1967         OCFree(str);
1968     }
1969
1970     return result;
1971 }
1972
1973 /**
1974  * Bind a resourcetype to a resource.
1975  *
1976  * @param handle - handle to the resource
1977  * @param resourceTypeName - name of resource type.  Example: "core.led"
1978  *
1979  * @return
1980  *     OC_STACK_OK    - no errors
1981  *     OC_STACK_ERROR - stack process error
1982  */
1983 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
1984         const char *resourceTypeName) {
1985
1986     OCStackResult result = OC_STACK_ERROR;
1987     OCResource *resource;
1988
1989     // Make sure resource exists
1990     resource = findResource((OCResource *) handle);
1991     if (!resource) {
1992         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1993         return OC_STACK_ERROR;
1994     }
1995
1996     // call internal function
1997     result = BindResourceTypeToResource(resource, resourceTypeName);
1998
1999     #ifdef WITH_PRESENCE
2000     if(presenceResource.handle)
2001     {
2002         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2003         SendPresenceNotification(resource->rsrcType);
2004     }
2005     #endif
2006
2007     return result;
2008 }
2009
2010 /**
2011  * Bind a resourceinterface to a resource.
2012  *
2013  * @param handle - handle to the resource
2014  * @param resourceInterfaceName - name of resource interface.  Example: "oc.mi.b"
2015  *
2016  * @return
2017  *     OC_STACK_OK    - no errors
2018  *     OC_STACK_ERROR - stack process error
2019  */
2020
2021 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2022         const char *resourceInterfaceName) {
2023
2024     OCStackResult result = OC_STACK_ERROR;
2025     OCResource *resource;
2026
2027     // Make sure resource exists
2028     resource = findResource((OCResource *) handle);
2029     if (!resource) {
2030         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2031         return OC_STACK_ERROR;
2032     }
2033
2034     // call internal function
2035     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2036
2037     #ifdef WITH_PRESENCE
2038     if(presenceResource.handle)
2039     {
2040         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2041         SendPresenceNotification(resource->rsrcType);
2042     }
2043     #endif
2044
2045     return result;
2046 }
2047
2048 /**
2049  * Get the number of resources that have been created in the stack.
2050  *
2051  * @param numResources - pointer to count variable
2052  *
2053  * @return
2054  *     OC_STACK_OK    - no errors
2055  *     OC_STACK_ERROR - stack process error
2056
2057  */
2058 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2059     OCResource *pointer = headResource;
2060
2061     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2062     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2063     *numResources = 0;
2064     while (pointer) {
2065         *numResources = *numResources + 1;
2066         pointer = pointer->next;
2067     }
2068     return OC_STACK_OK;
2069 }
2070
2071 /**
2072  * Get a resource handle by index.
2073  *
2074  * @param index - index of resource, 0 to Count - 1
2075  *
2076  * @return
2077  *    Resource handle - if found
2078  *    NULL - if not found
2079  */
2080 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2081     OCResource *pointer = headResource;
2082     uint8_t i = 0;
2083
2084     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2085
2086     // Iterate through the list
2087     while ((i < index) && pointer) {
2088         i++;
2089         pointer = pointer->next;
2090     }
2091     return (OCResourceHandle) pointer;
2092 }
2093
2094 /**
2095  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
2096  * linked lists.
2097  *
2098  * @param handle - handle of resource to be deleted
2099  *
2100  * @return
2101  *     OC_STACK_OK              - no errors
2102  *     OC_STACK_ERROR           - stack process error
2103  *     OC_STACK_NO_RESOURCE     - resource not found
2104  *     OC_STACK_INVALID_PARAM   - invalid param
2105  */
2106 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2107     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2108
2109     if (!handle) {
2110         OC_LOG(ERROR, TAG, PCF("Invalid param"));
2111         return OC_STACK_INVALID_PARAM;
2112     }
2113
2114     OCResource *resource = findResource((OCResource *) handle);
2115     if (resource == NULL) {
2116         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2117         return OC_STACK_NO_RESOURCE;
2118     }
2119
2120     if (deleteResource((OCResource *) handle) == 0) {
2121         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2122         return OC_STACK_ERROR;
2123     }
2124
2125     return OC_STACK_OK;
2126 }
2127
2128 /**
2129  * Get the URI of the resource specified by handle.
2130  *
2131  * @param handle - handle of resource
2132  * @return
2133  *    URI string - if resource found
2134  *    NULL - resource not found
2135  */
2136 const char *OCGetResourceUri(OCResourceHandle handle) {
2137     OCResource *resource;
2138     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2139
2140     resource = findResource((OCResource *) handle);
2141     if (resource) {
2142         return resource->uri;
2143     }
2144     return (const char *) NULL;
2145 }
2146
2147 /**
2148  * Get the properties of the resource specified by handle.
2149  * NOTE: that after a resource is created, the OC_ACTIVE property is set
2150  * for the resource by the stack.
2151  *
2152  * @param handle - handle of resource
2153  * @return
2154  *    property bitmap - if resource found
2155  *    NULL - resource not found
2156  */
2157 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2158     OCResource *resource;
2159     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2160
2161     resource = findResource((OCResource *) handle);
2162     if (resource) {
2163         return resource->resourceProperties;
2164     }
2165     return 0;
2166 }
2167
2168 /**
2169  * Get the number of resource types of the resource.
2170  *
2171  * @param handle - handle of resource
2172  * @param numResourceTypes - pointer to count variable
2173  *
2174  * @return
2175  *     OC_STACK_OK    - no errors
2176  *     OC_STACK_ERROR - stack process error
2177  */
2178 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2179         uint8_t *numResourceTypes) {
2180     OCResource *resource;
2181     OCResourceType *pointer;
2182
2183     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2184     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2185     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2186
2187     *numResourceTypes = 0;
2188
2189     resource = findResource((OCResource *) handle);
2190     if (resource) {
2191         pointer = resource->rsrcType;
2192         while (pointer) {
2193             *numResourceTypes = *numResourceTypes + 1;
2194             pointer = pointer->next;
2195         }
2196     }
2197     return OC_STACK_OK;
2198 }
2199
2200 /**
2201  * Get name of resource type of the resource.
2202  *
2203  * @param handle - handle of resource
2204  * @param index - index of resource, 0 to Count - 1
2205  *
2206  * @return
2207  *    resource type name - if resource found
2208  *    NULL - resource not found
2209  */
2210 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2211     OCResourceType *resourceType;
2212
2213     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2214
2215     resourceType = findResourceTypeAtIndex(handle, index);
2216     if (resourceType) {
2217         return resourceType->resourcetypename;
2218     }
2219     return (const char *) NULL;
2220 }
2221
2222
2223
2224 /**
2225  * Get the number of resource interfaces of the resource.
2226  *
2227  * @param handle - handle of resource
2228  * @param numResources - pointer to count variable
2229  *
2230  * @return
2231  *     OC_STACK_OK    - no errors
2232  *     OC_STACK_ERROR - stack process error
2233  */
2234 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2235         uint8_t *numResourceInterfaces) {
2236     OCResourceInterface *pointer;
2237     OCResource *resource;
2238
2239     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2240
2241     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2242     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2243
2244     *numResourceInterfaces = 0;
2245     resource = findResource((OCResource *) handle);
2246     if (resource) {
2247         pointer = resource->rsrcInterface;
2248         while (pointer) {
2249             *numResourceInterfaces = *numResourceInterfaces + 1;
2250             pointer = pointer->next;
2251         }
2252     }
2253     return OC_STACK_OK;
2254 }
2255
2256 /**
2257  * Get name of resource interface of the resource.
2258  *
2259  * @param handle - handle of resource
2260  * @param index - index of resource, 0 to Count - 1
2261  *
2262  * @return
2263  *    resource interface name - if resource found
2264  *    NULL - resource not found
2265  */
2266 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2267     OCResourceInterface *resourceInterface;
2268
2269     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2270
2271     resourceInterface = findResourceInterfaceAtIndex(handle, index);
2272     if (resourceInterface) {
2273         return resourceInterface->name;
2274     }
2275     return (const char *) NULL;
2276 }
2277
2278 /**
2279  * Get resource handle from the collection resource by index.
2280  *
2281  * @param collectionHandle - handle of collection resource
2282  * @param index - index of contained resource, 0 to Count - 1
2283  *
2284  * @return
2285  *    handle to resource - if resource found
2286  *    NULL - resource not found
2287  */
2288 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2289         uint8_t index) {
2290     OCResource *resource;
2291
2292     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2293
2294     if (index >= MAX_CONTAINED_RESOURCES) {
2295         return NULL;
2296     }
2297
2298     resource = findResource((OCResource *) collectionHandle);
2299     if (!resource) {
2300         return NULL;
2301     }
2302
2303     return resource->rsrcResources[index];
2304 }
2305
2306 /**
2307  * Bind an entity handler to the resource.
2308  *
2309  * @param handle - handle to the resource that the contained resource is to be bound
2310  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2311  * @return
2312  *     OC_STACK_OK    - no errors
2313  *     OC_STACK_ERROR - stack process error
2314  */
2315 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2316         OCEntityHandler entityHandler) {
2317     OCResource *resource;
2318
2319     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2320
2321     // Validate parameters
2322     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2323     //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2324
2325     // Use the handle to find the resource in the resource linked list
2326     resource = findResource((OCResource *)handle);
2327     if (!resource) {
2328         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2329         return OC_STACK_ERROR;
2330     }
2331
2332     // Bind the handler
2333     resource->entityHandler = entityHandler;
2334
2335     #ifdef WITH_PRESENCE
2336     if(presenceResource.handle)
2337     {
2338         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2339         SendPresenceNotification(resource->rsrcType);
2340     }
2341     #endif
2342
2343     return OC_STACK_OK;
2344 }
2345
2346 /**
2347  * Get the entity handler for a resource.
2348  *
2349  * @param handle - handle of resource
2350  *
2351  * @return
2352  *    entity handler - if resource found
2353  *    NULL - resource not found
2354  */
2355 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2356     OCResource *resource;
2357
2358     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2359
2360     // Use the handle to find the resource in the resource linked list
2361     resource = findResource((OCResource *)handle);
2362     if (!resource) {
2363         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2364         return NULL;
2365     }
2366
2367     // Bind the handler
2368     return resource->entityHandler;
2369 }
2370
2371 void incrementSequenceNumber(OCResource * resPtr)
2372 {
2373     // Increment the sequence number
2374     resPtr->sequenceNum += 1;
2375     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2376     {
2377         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2378     }
2379     return;
2380 }
2381
2382 /**
2383  * Notify Presence subscribers that a resource has been modified
2384  *
2385  * @param resourceType - Handle to the resourceType linked list of resource
2386  *                       that was modified.
2387  * @param qos          - Quality Of Service
2388  *
2389  */
2390 #ifdef WITH_PRESENCE
2391 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2392 {
2393     OCResource *resPtr = NULL;
2394     OCStackResult result;
2395     OCMethod method = OC_REST_PRESENCE;
2396     uint32_t maxAge = 0;
2397     resPtr = findResource((OCResource *) presenceResource.handle);
2398     if(NULL == resPtr)
2399     {
2400         return OC_STACK_NO_RESOURCE;
2401     }
2402     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2403     {
2404         maxAge = presenceResource.presenceTTL;
2405     }
2406     else
2407     {
2408         maxAge = 0;
2409     }
2410
2411     result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2412     return result;
2413 }
2414 #endif // WITH_PRESENCE
2415 /**
2416  * Notify observers that an observed value has changed.
2417  *
2418  * @param handle - handle of resource
2419  *
2420  * @return
2421  *     OC_STACK_OK    - no errors
2422  *     OC_STACK_NO_RESOURCE - invalid resource handle
2423  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2424  */
2425 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
2426
2427     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2428
2429     OCResource *resPtr = NULL;
2430     OCStackResult result;
2431     OCMethod method = OC_REST_NOMETHOD;
2432     uint32_t maxAge = 0;
2433
2434     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2435     #ifdef WITH_PRESENCE
2436     if(handle == presenceResource.handle)
2437     {
2438         return OC_STACK_OK;
2439     }
2440     #endif // WITH_PRESENCE
2441     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2442
2443     // Verify that the resource exists
2444     resPtr = findResource ((OCResource *) handle);
2445     if (NULL == resPtr)
2446     {
2447         return OC_STACK_NO_RESOURCE;
2448     }
2449     else
2450     {
2451         //only increment in the case of regular observing (not presence)
2452         incrementSequenceNumber(resPtr);
2453         method = OC_REST_OBSERVE;
2454         maxAge = MAX_OBSERVE_AGE;
2455         #ifdef WITH_PRESENCE
2456         result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
2457         #else
2458         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
2459         #endif
2460         return result;
2461     }
2462 }
2463
2464 OCStackResult
2465 OCNotifyListOfObservers (OCResourceHandle handle,
2466                          OCObservationId  *obsIdList,
2467                          uint8_t          numberOfIds,
2468                          unsigned char    *notificationJSONPayload,
2469                          OCQualityOfService qos)
2470 {
2471     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
2472
2473     OCResource *resPtr = NULL;
2474     //TODO: we should allow the server to define this
2475     uint32_t maxAge = MAX_OBSERVE_AGE;
2476
2477     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2478     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
2479     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
2480
2481     // Verify that the resource exists
2482     resPtr = findResource ((OCResource *) handle);
2483     if (NULL == resPtr || myStackMode == OC_CLIENT)
2484     {
2485         return OC_STACK_NO_RESOURCE;
2486     }
2487     else
2488     {
2489         incrementSequenceNumber(resPtr);
2490     }
2491     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
2492             notificationJSONPayload, maxAge, qos));
2493 }
2494
2495 /**
2496  * Send a response to a request.
2497  * The response can be a regular, slow, or block (i.e. a response that
2498  * is too large to be sent in a single PDU and must span multiple transmissions)
2499  *
2500  * @param response - pointer to structure that contains response parameters
2501  *
2502  * @return
2503  *     OC_STACK_OK                         - No errors; Success
2504  *     OC_STACK_INVALID_PARAM              - Invalid pointer to OCServerResponse
2505  *     OC_STACK_INVALID_REQUEST_HANDLE     - Request handle not found
2506  *     OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
2507  *                                           persistent response buffer is necessary
2508  */
2509 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
2510 {
2511     OCStackResult result = OC_STACK_ERROR;
2512     OCServerRequest *serverRequest = NULL;
2513
2514     OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
2515
2516     // Validate input parameters
2517     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
2518     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
2519
2520     // TODO: Placeholder for creating a response entry when implementing
2521     // block transfer feature
2522
2523     // If a response payload is present, check if block transfer is required
2524     if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
2525             (const char *)ehResponse->payload, ehResponse->payloadSize))
2526     {
2527         OC_LOG(INFO, TAG, PCF("Block transfer required"));
2528
2529         // Persistent response buffer is needed for block transfer
2530         if (!ehResponse->persistentBufferFlag)
2531         {
2532             OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
2533             return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
2534         }
2535         // TODO: Placeholder for block transfer handling
2536         // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
2537             // when implementing the block transfer feature
2538     }
2539     else
2540     {
2541         // Normal response
2542
2543         // Get pointer to request info
2544         serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
2545         if(serverRequest)
2546         {
2547             result = serverRequest->ehResponseHandler(ehResponse);
2548         }
2549     }
2550     return result;
2551 }
2552
2553 /**
2554  * Cancel a response.  Applies to a block response
2555  *
2556  * @param responseHandle - response handle set by stack in OCServerResponse after
2557  *                         OCDoResponse is called
2558  *
2559  * @return
2560  *     OC_STACK_OK               - No errors; Success
2561  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
2562  */
2563 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
2564 {
2565     OCStackResult result = OC_STACK_NOTIMPL;
2566
2567     OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
2568
2569     // TODO: validate response handle
2570
2571     return result;
2572 }
2573
2574 //-----------------------------------------------------------------------------
2575 // Private internal function definitions
2576 //-----------------------------------------------------------------------------
2577 /**
2578  * Generate handle of OCDoResource invocation for callback management.
2579  */
2580 static OCDoHandle GenerateInvocationHandle()
2581 {
2582     OCDoHandle handle = NULL;
2583     // Generate token here, it will be deleted when the transaction is deleted
2584     handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
2585     if (handle)
2586     {
2587         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
2588     }
2589
2590     return handle;
2591 }
2592 #ifdef WITH_PRESENCE
2593 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
2594         OCResourceProperty resourceProperties, uint8_t enable)
2595 {
2596     if (resourceProperties
2597             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
2598         OC_LOG(ERROR, TAG, PCF("Invalid property"));
2599         return OC_STACK_INVALID_PARAM;
2600     }
2601     if(!enable)
2602     {
2603         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
2604     }
2605     else
2606     {
2607         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
2608     }
2609     return OC_STACK_OK;
2610 }
2611 #endif
2612
2613 /**
2614  * Initialize resource data structures, variables, etc.
2615  */
2616 OCStackResult initResources() {
2617     OCStackResult result = OC_STACK_OK;
2618     // Init application resource vars
2619     headResource = NULL;
2620     // Init Virtual Resources
2621     #ifdef WITH_PRESENCE
2622     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
2623     //presenceResource.token = OCGenerateCoAPToken();
2624     result = OCCreateResource(&presenceResource.handle,
2625             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
2626             "core.r",
2627             OC_PRESENCE_URI,
2628             NULL,
2629             OC_OBSERVABLE);
2630     //make resource inactive
2631     result = OCChangeResourceProperty(
2632             &(((OCResource *) presenceResource.handle)->resourceProperties),
2633             OC_ACTIVE, 0);
2634     #endif
2635     return result;
2636 }
2637
2638 /**
2639  * Add a resource to the end of the linked list of resources.
2640  *
2641  * @param resource - resource to be added
2642  */
2643 void insertResource(OCResource *resource) {
2644     OCResource *pointer;
2645
2646     if (!headResource) {
2647         headResource = resource;
2648     } else {
2649         pointer = headResource;
2650
2651         while (pointer->next) {
2652             pointer = pointer->next;
2653         }
2654         pointer->next = resource;
2655     }
2656     resource->next = NULL;
2657 }
2658
2659 /**
2660  * Find a resource in the linked list of resources.
2661  *
2662  * @param resource - resource to be found
2663  * @return
2664  *     NULL                - resource not found
2665  *     pointer to resource - pointer to resource that was found in the linked list
2666  */
2667 OCResource *findResource(OCResource *resource) {
2668     OCResource *pointer = headResource;
2669
2670     while (pointer) {
2671         if (pointer == resource) {
2672             return resource;
2673         }
2674         pointer = pointer->next;
2675     }
2676     return NULL;
2677 }
2678
2679 void deleteAllResources()
2680 {
2681     OCResource *pointer = headResource;
2682     OCResource *temp;
2683
2684     while (pointer)
2685     {
2686         temp = pointer->next;
2687         #ifdef WITH_PRESENCE
2688         if(pointer != (OCResource *) presenceResource.handle)
2689         {
2690             #endif // WITH_PRESENCE
2691             deleteResource(pointer);
2692             #ifdef WITH_PRESENCE
2693         }
2694         #endif // WITH_PRESENCE
2695         pointer = temp;
2696     }
2697
2698     #ifdef WITH_PRESENCE
2699     // Ensure that the last resource to be deleted is the presence resource. This allows for all
2700     // presence notification attributed to their deletion to be processed.
2701     deleteResource((OCResource *) presenceResource.handle);
2702     #endif // WITH_PRESENCE
2703 }
2704
2705 /**
2706  * Delete the resource from the linked list.
2707  *
2708  * @param resource - resource to be deleted
2709  * @return
2710  *    0 - error
2711  *    1 - success
2712  */
2713 int deleteResource(OCResource *resource) {
2714     OCResource *prev = NULL;
2715     OCResource *temp;
2716
2717     temp = headResource;
2718     while (temp) {
2719         if (temp == resource) {
2720             // Invalidate all Resource Properties.
2721             resource->resourceProperties = (OCResourceProperty) 0;
2722             #ifdef WITH_PRESENCE
2723             if(resource != (OCResource *) presenceResource.handle)
2724             {
2725             #endif // WITH_PRESENCE
2726                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
2727             #ifdef WITH_PRESENCE
2728             }
2729
2730             if(presenceResource.handle)
2731             {
2732                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2733                 if(resource != (OCResource *) presenceResource.handle)
2734                 {
2735                     SendPresenceNotification(resource->rsrcType);
2736                 }
2737                 else
2738                 {
2739                     SendPresenceNotification(NULL);
2740                 }
2741             }
2742         #endif
2743
2744             if (temp == headResource) {
2745                 headResource = temp->next;
2746             } else {
2747                 prev->next = temp->next;
2748             }
2749
2750             deleteResourceElements(temp);
2751             OCFree(temp);
2752             return 1;
2753         } else {
2754             prev = temp;
2755             temp = temp->next;
2756         }
2757     }
2758
2759     return 0;
2760 }
2761
2762 /**
2763  * Delete all of the dynamically allocated elements that were created for the resource.
2764  *
2765  * @param resource - specified resource
2766  */
2767 void deleteResourceElements(OCResource *resource) {
2768     if (!resource) {
2769         return;
2770     }
2771
2772     // remove URI
2773     OCFree(resource->uri);
2774
2775     // Delete resourcetype linked list
2776     deleteResourceType(resource->rsrcType);
2777
2778     // Delete resourceinterface linked list
2779     deleteResourceInterface(resource->rsrcInterface);
2780 }
2781
2782 /**
2783  * Delete all of the dynamically allocated elements that were created for the resource type.
2784  *
2785  * @param resourceType - specified resource type
2786  */
2787 void deleteResourceType(OCResourceType *resourceType) {
2788     OCResourceType *pointer = resourceType;
2789     OCResourceType *next;
2790
2791     while (pointer) {
2792         next = pointer->next;
2793         OCFree(pointer->resourcetypename);
2794         OCFree(pointer);
2795         pointer = next;
2796     }
2797 }
2798
2799 /**
2800  * Delete all of the dynamically allocated elements that were created for the resource interface.
2801  *
2802  * @param resourceInterface - specified resource interface
2803  */
2804 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
2805     OCResourceInterface *pointer = resourceInterface;
2806     OCResourceInterface *next;
2807
2808     while (pointer) {
2809         next = pointer->next;
2810         OCFree(pointer->name);
2811         OCFree(pointer);
2812         pointer = next;
2813     }
2814 }
2815
2816 /**
2817  * Insert a resource type into a resource's resource type linked list.
2818  *
2819  * @param resource - resource where resource type is to be inserted
2820  * @param resourceType - resource type to be inserted
2821  */
2822 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
2823     OCResourceType *pointer;
2824
2825     if (resource && !resource->rsrcType) {
2826         resource->rsrcType = resourceType;
2827     } else {
2828         if(resource)
2829         {
2830             pointer = resource->rsrcType;
2831         }
2832         else
2833         {
2834             pointer = resourceType;
2835         }
2836         while (pointer->next) {
2837             pointer = pointer->next;
2838         }
2839         pointer->next = resourceType;
2840     }
2841     resourceType->next = NULL;
2842 }
2843
2844 /**
2845  * Get a resource type at the specified index within a resource.
2846  *
2847  * @param handle - handle of resource
2848  * @param index - index of resource type
2849  *
2850  * @return
2851  *    resourcetype - if found
2852  *    NULL - not found
2853  */
2854 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
2855     OCResource *resource;
2856     OCResourceType *pointer;
2857     uint8_t i;
2858
2859     // Find the specified resource
2860     resource = findResource((OCResource *) handle);
2861     if (!resource) {
2862         return NULL;
2863     }
2864
2865     // Make sure a resource has a resourcetype
2866     if (!resource->rsrcType) {
2867         return NULL;
2868     }
2869
2870     // Iterate through the list
2871     pointer = resource->rsrcType;
2872     i = 0;
2873     while ((i < index) && pointer) {
2874         i++;
2875         pointer = pointer->next;
2876     }
2877     return pointer;
2878 }
2879
2880 /**
2881  * Finds a resource type in an OCResourceType link-list.
2882  *
2883  * @param resourceTypeList - the link-list to be searched through
2884  * @param resourceTypeName - the key to search for
2885  *
2886  * @return
2887  *      resourceType that matches the key (ie. resourceTypeName)
2888  *      NULL - either an invalid parameter or this function was unable to find the key.
2889  */
2890 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
2891 {
2892     if(resourceTypeList && resourceTypeName)
2893     {
2894         OCResourceType * rtPointer = resourceTypeList;
2895         while(resourceTypeName && rtPointer)
2896         {
2897             if(rtPointer->resourcetypename &&
2898                     strcmp(resourceTypeName, (const char *)
2899                     (rtPointer->resourcetypename)) == 0)
2900             {
2901                 break;
2902             }
2903             rtPointer = rtPointer->next;
2904         }
2905         return rtPointer;
2906     }
2907     return NULL;
2908 }
2909 /**
2910  * Insert a resource interface into a resource's resource interface linked list.
2911  *
2912  * @param resource - resource where resource interface is to be inserted
2913  * @param resourceInterface - resource interface to be inserted
2914  */
2915 void insertResourceInterface(OCResource *resource,
2916         OCResourceInterface *resourceInterface) {
2917     OCResourceInterface *pointer;
2918
2919     if (!resource->rsrcInterface) {
2920         resource->rsrcInterface = resourceInterface;
2921     } else {
2922         pointer = resource->rsrcInterface;
2923         while (pointer->next) {
2924             pointer = pointer->next;
2925         }
2926         pointer->next = resourceInterface;
2927     }
2928     resourceInterface->next = NULL;
2929 }
2930
2931 /**
2932  * Get a resource interface at the specified index within a resource.
2933  *
2934  * @param handle - handle of resource
2935  * @param index - index of resource interface
2936  *
2937  * @return
2938  *    resourceinterface - if found
2939  *    NULL - not found
2940  */
2941 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
2942         uint8_t index) {
2943     OCResource *resource;
2944     OCResourceInterface *pointer;
2945     uint8_t i = 0;
2946
2947     // Find the specified resource
2948     resource = findResource((OCResource *) handle);
2949     if (!resource) {
2950         return NULL;
2951     }
2952
2953     // Make sure a resource has a resourceinterface
2954     if (!resource->rsrcInterface) {
2955         return NULL;
2956     }
2957
2958     // Iterate through the list
2959     pointer = resource->rsrcInterface;
2960
2961     while ((i < index) && pointer) {
2962         i++;
2963         pointer = pointer->next;
2964     }
2965     return pointer;
2966 }
2967
2968 /**
2969  * Determine if a request/response must be sent in a block transfer because it is too large to be
2970  * sent in a single PDU.  This function can be used for either a request or a response
2971  *
2972  * @param request  - NULL or pointer to request
2973  * @param response - NULL or pointer to response
2974  * @param size     - 0 or size of the request/response.  If 0, strlen is used for determining
2975  *                   the length of the request/response
2976  *
2977  * @return
2978  *    0 - packet transfer NOT required (i.e. normal request/response)
2979  *    1 - packet transfer required (i.e. block transfer needed)
2980  */
2981 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
2982 {
2983     uint8_t result = 0;
2984
2985     // Determine if we are checking a request or a response
2986     if (request)
2987     {
2988         // If size is greater than 0, use it for the request size value, otherwise
2989         // assume request is null terminated and use strlen for size value
2990         if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
2991         {
2992             result = 1;
2993         }
2994     }
2995     else if (response)
2996     {
2997         // If size is greater than 0, use it for the response size value, otherwise
2998         // assume response is null terminated and use strlen for size value
2999         if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3000         {
3001             result = 1;
3002         }
3003     }
3004     return result;
3005 }
3006
3007 /**
3008  * Retrieves a resource type based upon a uri string if the uri string contains only just one
3009  * resource attribute (and that has to be of type "rt").
3010  *
3011  * @remark This API malloc's memory for the resource type and newURI. Do not malloc resourceType
3012  * or newURI before passing in.
3013  *
3014  * @param uri - Valid URI for "requiredUri" parameter to OCDoResource API.
3015  * @param resourceType - The resource type to be populated; pass by reference.
3016  * @param newURI - Return URI without resourceType appended to the end of it. This is used to
3017  *                 ensure that the uri parameter is not modified; pass by reference.
3018  *
3019  * @return
3020  *  OC_STACK_INVALID_URI   - Returns this if the URI is invalid/NULL.
3021  *  OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3022  *  OC_STACK_OK            - Success
3023  */
3024 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI)
3025 {
3026     if(!uri)
3027     {
3028         return OC_STACK_INVALID_URI;
3029     }
3030     if(!resourceType || !newURI)
3031     {
3032         return OC_STACK_INVALID_PARAM;
3033     }
3034     char * leftToken = NULL;
3035     char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3036     if(!tempURI)
3037     {
3038         goto exit;
3039     }
3040     strcpy(tempURI, uri);
3041     leftToken = strtok((char *)tempURI, "?");
3042
3043     while(leftToken != NULL)
3044     {
3045         if(strncmp(leftToken, "rt=", 3) == 0)
3046         {
3047             *resourceType = (unsigned char *) OCMalloc(strlen(leftToken)-3);
3048             if(!*resourceType)
3049             {
3050                 goto exit;
3051             }
3052             strcpy((char *)*resourceType, ((const char *)&leftToken[3]));
3053             break;
3054         }
3055         leftToken = strtok(NULL, "?");
3056     }
3057
3058     *newURI = tempURI;
3059
3060     return OC_STACK_OK;
3061
3062     exit:
3063         return OC_STACK_NO_MEMORY;
3064 }
3065
3066 const ServerID OCGetServerInstanceID(void)
3067 {
3068     static bool generated = false;
3069     static ServerID sid;
3070
3071     if(generated)
3072     {
3073         return sid;
3074     }
3075
3076     sid = OCGetRandom();
3077     generated = true;
3078     return sid;
3079 }
3080
3081 const char* OCGetServerInstanceIDString(void)
3082 {
3083     // max printed length of a base 10
3084     // uint32 is 10 characters, so 11 includes null.
3085     // This will change as the representation gets switched
3086     // to another value
3087     static char buffer[11];
3088     int n = sprintf(buffer, "%u", OCGetServerInstanceID());
3089     if (n < 0)
3090     {
3091         buffer[0]='\0';
3092     }
3093
3094     return buffer;
3095 }