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