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