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