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