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