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