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