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