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