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