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