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