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