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