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