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