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