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