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