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