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