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