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