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