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