1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //-----------------------------------------------------------------------------
24 //-----------------------------------------------------------------------------
26 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
27 // causes header files to expose definitions
28 // corresponding to the POSIX.1-2001 base
29 // specification (excluding the XSI extension).
30 // For POSIX.1-2001 base specification,
31 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
32 #define _POSIX_C_SOURCE 200112L
37 #include "ocstackinternal.h"
38 #include "ocresourcehandler.h"
39 #include "occlientcb.h"
40 #include "ocobserve.h"
42 #include "oic_malloc.h"
43 #include "oic_string.h"
44 #include "ocserverrequest.h"
45 #include "secureresourcemanager.h"
46 #include "doxmresource.h"
48 #include "cainterface.h"
49 #include "ocpayload.h"
50 #include "ocpayloadcbor.h"
57 #include "coap_time.h"
62 #include <arpa/inet.h>
66 #define UINT32_MAX (0xFFFFFFFFUL)
69 //-----------------------------------------------------------------------------
71 //-----------------------------------------------------------------------------
74 OC_STACK_UNINITIALIZED = 0,
76 OC_STACK_UNINIT_IN_PROGRESS
82 OC_PRESENCE_UNINITIALIZED = 0,
83 OC_PRESENCE_INITIALIZED
87 //-----------------------------------------------------------------------------
89 //-----------------------------------------------------------------------------
90 static OCStackState stackState = OC_STACK_UNINITIALIZED;
92 OCResource *headResource = NULL;
93 static OCResource *tailResource = NULL;
95 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
96 static PresenceResource presenceResource;
97 static uint8_t PresenceTimeOutSize = 0;
98 static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
101 static OCMode myStackMode;
103 //TODO: revisit this design
104 static bool gRASetInfo = false;
106 OCDeviceEntityHandler defaultDeviceHandler;
107 void* defaultDeviceHandlerCallbackParameter = NULL;
110 static const char COAP_TCP[] = "coap+tcp:";
113 //-----------------------------------------------------------------------------
115 //-----------------------------------------------------------------------------
116 #define TAG "OCStack"
117 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
118 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
119 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
120 TAG, #arg " is NULL"); return (retVal); } }
121 #define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OC_LOG((logLevel), \
122 TAG, #arg " is NULL"); return; } }
123 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
126 //TODO: we should allow the server to define this
127 #define MAX_OBSERVE_AGE (0x2FFFFUL)
129 #define MILLISECONDS_PER_SECOND (1000)
131 //-----------------------------------------------------------------------------
132 // Private internal function prototypes
133 //-----------------------------------------------------------------------------
136 * Generate handle of OCDoResource invocation for callback management.
138 * @return Generated OCDoResource handle.
140 static OCDoHandle GenerateInvocationHandle();
143 * Initialize resource data structures, variables, etc.
145 * @return ::OC_STACK_OK on success, some other value upon failure.
147 static OCStackResult initResources();
150 * Add a resource to the end of the linked list of resources.
152 * @param resource Resource to be added
154 static void insertResource(OCResource *resource);
157 * Find a resource in the linked list of resources.
159 * @param resource Resource to be found.
160 * @return Pointer to resource that was found in the linked list or NULL if the resource was not
163 static OCResource *findResource(OCResource *resource);
166 * Insert a resource type into a resource's resource type linked list.
167 * If resource type already exists, it will not be inserted and the
168 * resourceType will be free'd.
169 * resourceType->next should be null to avoid memory leaks.
170 * Function returns silently for null args.
172 * @param resource Resource where resource type is to be inserted.
173 * @param resourceType Resource type to be inserted.
175 static void insertResourceType(OCResource *resource,
176 OCResourceType *resourceType);
179 * Get a resource type at the specified index within a resource.
181 * @param handle Handle of resource.
182 * @param index Index of resource type.
184 * @return Pointer to resource type if found, NULL otherwise.
186 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
190 * Insert a resource interface into a resource's resource interface linked list.
191 * If resource interface already exists, it will not be inserted and the
192 * resourceInterface will be free'd.
193 * resourceInterface->next should be null to avoid memory leaks.
195 * @param resource Resource where resource interface is to be inserted.
196 * @param resourceInterface Resource interface to be inserted.
198 static void insertResourceInterface(OCResource *resource,
199 OCResourceInterface *resourceInterface);
202 * Get a resource interface at the specified index within a resource.
204 * @param handle Handle of resource.
205 * @param index Index of resource interface.
207 * @return Pointer to resource interface if found, NULL otherwise.
209 static OCResourceInterface *findResourceInterfaceAtIndex(
210 OCResourceHandle handle, uint8_t index);
213 * Delete all of the dynamically allocated elements that were created for the resource type.
215 * @param resourceType Specified resource type.
217 static void deleteResourceType(OCResourceType *resourceType);
220 * Delete all of the dynamically allocated elements that were created for the resource interface.
222 * @param resourceInterface Specified resource interface.
224 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
227 * Delete all of the dynamically allocated elements that were created for the resource.
229 * @param resource Specified resource.
231 static void deleteResourceElements(OCResource *resource);
234 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
237 * @param handle Handle of resource to be deleted.
239 * @return ::OC_STACK_OK on success, some other value upon failure.
241 static OCStackResult deleteResource(OCResource *resource);
244 * Delete all of the resources in the resource list.
246 static void deleteAllResources();
249 * Increment resource sequence number. Handles rollover.
251 * @param resPtr Pointer to resource.
253 static void incrementSequenceNumber(OCResource * resPtr);
256 * Verify the lengths of the URI and the query separately.
258 * @param inputUri Input URI and query.
259 * @param uriLen The length of the initial URI with query.
260 * @return ::OC_STACK_OK on success, some other value upon failure.
262 static OCStackResult verifyUriQueryLength(const char * inputUri,
266 * Attempts to initialize every network interface that the CA Layer might have compiled in.
268 * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork
269 * return something other than @ref CA_STATUS_OK, then this function fails.
271 * @return ::CA_STATUS_OK on success, some other value upon failure.
273 static CAResult_t OCSelectNetwork();
276 * Get the CoAP ticks after the specified number of milli-seconds.
278 * @param afterMilliSeconds Milli-seconds.
282 static uint32_t GetTicks(uint32_t afterMilliSeconds);
285 * Convert CAResponseResult_t to OCStackResult.
287 * @param caCode CAResponseResult_t code.
288 * @return ::OC_STACK_OK on success, some other value upon failure.
290 static OCStackResult CAToOCStackResult(CAResponseResult_t caCode);
293 * Convert OCStackResult to CAResponseResult_t.
295 * @param caCode OCStackResult code.
296 * @param method OCMethod method the return code replies to.
297 * @return ::CA_SUCCESS on success, some other value upon failure.
299 static CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method);
302 * Convert OCTransportFlags_t to CATransportModifiers_t.
304 * @param ocConType OCTransportFlags_t input.
305 * @return CATransportFlags
307 static CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocConType);
310 * Convert CATransportFlags_t to OCTransportModifiers_t.
312 * @param caConType CATransportFlags_t input.
313 * @return OCTransportFlags
315 static OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caConType);
318 * Handle response from presence request.
320 * @param endPoint CA remote endpoint.
321 * @param responseInfo CA response info.
322 * @return ::OC_STACK_OK on success, some other value upon failure.
324 static OCStackResult HandlePresenceResponse(const CAEndpoint_t *endPoint,
325 const CAResponseInfo_t *responseInfo);
328 * This function will be called back by CA layer when a response is received.
330 * @param endPoint CA remote endpoint.
331 * @param responseInfo CA response info.
333 static void HandleCAResponses(const CAEndpoint_t* endPoint,
334 const CAResponseInfo_t* responseInfo);
337 * This function will be called back by CA layer when a request is received.
339 * @param endPoint CA remote endpoint.
340 * @param requestInfo CA request info.
342 static void HandleCARequests(const CAEndpoint_t* endPoint,
343 const CARequestInfo_t* requestInfo);
346 * Extract query from a URI.
348 * @param uri Full URI with query.
349 * @param query Pointer to string that will contain query.
350 * @param newURI Pointer to string that will contain URI.
351 * @return ::OC_STACK_OK on success, some other value upon failure.
353 static OCStackResult getQueryFromUri(const char * uri, char** resourceType, char ** newURI);
356 * Finds a resource type in an OCResourceType link-list.
358 * @param resourceTypeList The link-list to be searched through.
359 * @param resourceTypeName The key to search for.
361 * @return Resource type that matches the key (ie. resourceTypeName) or
362 * NULL if there is either an invalid parameter or this function was unable to find the key.
364 static OCResourceType *findResourceType(OCResourceType * resourceTypeList,
365 const char * resourceTypeName);
368 * Reset presence TTL for a ClientCB struct. ttlLevel will be set to 0.
369 * TTL will be set to maxAge.
371 * @param cbNode Callback Node for which presence ttl is to be reset.
372 * @param maxAge New value of ttl in seconds.
374 * @return ::OC_STACK_OK on success, some other value upon failure.
376 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds);
379 * Ensure the accept header option is set appropriatly before sending the requests.
381 * @param object CA remote endpoint.
382 * @param requestInfo CA request info.
384 * @return ::OC_STACK_OK on success, some other value upon failure.
386 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo);
388 //-----------------------------------------------------------------------------
389 // Internal functions
390 //-----------------------------------------------------------------------------
392 uint32_t GetTicks(uint32_t afterMilliSeconds)
397 // Guard against overflow of uint32_t
398 if (afterMilliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) /
399 COAP_TICKS_PER_SECOND)
401 return now + (afterMilliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND;
409 void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out)
411 VERIFY_NON_NULL_NR(in, FATAL);
412 VERIFY_NON_NULL_NR(out, FATAL);
414 out->adapter = (OCTransportAdapter)in->adapter;
415 out->flags = CAToOCTransportFlags(in->flags);
416 OICStrcpy(out->addr, sizeof(out->addr), in->addr);
417 out->port = in->port;
418 out->interface = in->interface;
421 void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
423 VERIFY_NON_NULL_NR(in, FATAL);
424 VERIFY_NON_NULL_NR(out, FATAL);
426 out->adapter = (CATransportAdapter_t)in->adapter;
427 out->flags = OCToCATransportFlags(in->flags);
428 OICStrcpy(out->addr, sizeof(out->addr), in->addr);
429 out->port = in->port;
430 out->interface = in->interface;
433 void FixUpClientResponse(OCClientResponse *cr)
435 VERIFY_NON_NULL_NR(cr, FATAL);
437 cr->addr = &cr->devAddr;
438 cr->connType = (OCConnectivityType)
439 ((cr->devAddr.adapter << CT_ADAPTER_SHIFT) | (cr->devAddr.flags & CT_MASK_FLAGS));
442 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo)
444 // OC stack prefer CBOR encoded payloads.
445 requestInfo->info.acceptFormat = CA_FORMAT_APPLICATION_CBOR;
446 CAResult_t result = CASendRequest(object, requestInfo);
447 if(CA_STATUS_OK != result)
449 OC_LOG_V(ERROR, TAG, "CASendRequest failed with CA error %u", result);
450 return CAResultToOCResult(result);
454 //-----------------------------------------------------------------------------
455 // Internal API function
456 //-----------------------------------------------------------------------------
458 // This internal function is called to update the stack with the status of
459 // observers and communication failures
460 OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t status)
462 OCStackResult result = OC_STACK_ERROR;
463 ResourceObserver * observer = NULL;
464 OCEntityHandlerRequest ehRequest = {0};
468 case OC_OBSERVER_NOT_INTERESTED:
469 OC_LOG(DEBUG, TAG, "observer not interested in our notifications");
470 observer = GetObserverUsingToken (token, tokenLength);
473 result = FormOCEntityHandlerRequest(&ehRequest,
474 (OCRequestHandle)NULL,
477 (OCResourceHandle)NULL,
478 NULL, PAYLOAD_TYPE_REPRESENTATION,
480 OC_OBSERVE_DEREGISTER,
481 observer->observeId);
482 if(result != OC_STACK_OK)
486 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
487 observer->resource->entityHandlerCallbackParam);
490 result = DeleteObserverUsingToken (token, tokenLength);
491 if(result == OC_STACK_OK)
493 OC_LOG(DEBUG, TAG, "Removed observer successfully");
497 result = OC_STACK_OK;
498 OC_LOG(DEBUG, TAG, "Observer Removal failed");
502 case OC_OBSERVER_STILL_INTERESTED:
503 OC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount");
504 observer = GetObserverUsingToken (token, tokenLength);
507 observer->forceHighQos = 0;
508 observer->failedCommCount = 0;
509 result = OC_STACK_OK;
513 result = OC_STACK_OBSERVER_NOT_FOUND;
517 case OC_OBSERVER_FAILED_COMM:
518 OC_LOG(DEBUG, TAG, "observer is unreachable");
519 observer = GetObserverUsingToken (token, tokenLength);
522 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
524 result = FormOCEntityHandlerRequest(&ehRequest,
525 (OCRequestHandle)NULL,
528 (OCResourceHandle)NULL,
529 NULL, PAYLOAD_TYPE_REPRESENTATION,
531 OC_OBSERVE_DEREGISTER,
532 observer->observeId);
533 if(result != OC_STACK_OK)
535 return OC_STACK_ERROR;
537 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
538 observer->resource->entityHandlerCallbackParam);
540 result = DeleteObserverUsingToken (token, tokenLength);
541 if(result == OC_STACK_OK)
543 OC_LOG(DEBUG, TAG, "Removed observer successfully");
547 result = OC_STACK_OK;
548 OC_LOG(DEBUG, TAG, "Observer Removal failed");
553 observer->failedCommCount++;
554 result = OC_STACK_CONTINUE;
556 observer->forceHighQos = 1;
557 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
561 OC_LOG(ERROR, TAG, "Unknown status");
562 result = OC_STACK_ERROR;
567 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
569 OCStackResult ret = OC_STACK_ERROR;
574 ret = OC_STACK_RESOURCE_CREATED;
577 ret = OC_STACK_RESOURCE_DELETED;
584 ret = OC_STACK_INVALID_QUERY;
586 case CA_UNAUTHORIZED_REQ:
587 ret = OC_STACK_UNAUTHORIZED_REQ;
590 ret = OC_STACK_INVALID_OPTION;
593 ret = OC_STACK_NO_RESOURCE;
595 case CA_RETRANSMIT_TIMEOUT:
596 ret = OC_STACK_COMM_ERROR;
604 CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method)
606 CAResponseResult_t ret = CA_INTERNAL_SERVER_ERROR;
615 // This Response Code is like HTTP 204 "No Content" but only used in
616 // response to POST and PUT requests.
620 // This Response Code is like HTTP 200 "OK" but only used in response to
625 // This should not happen but,
626 // give it a value just in case but output an error
628 OC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [d].", method);
631 case OC_STACK_RESOURCE_CREATED:
634 case OC_STACK_RESOURCE_DELETED:
637 case OC_STACK_INVALID_QUERY:
640 case OC_STACK_INVALID_OPTION:
643 case OC_STACK_NO_RESOURCE:
646 case OC_STACK_COMM_ERROR:
647 ret = CA_RETRANSMIT_TIMEOUT;
649 case OC_STACK_UNAUTHORIZED_REQ:
650 ret = CA_UNAUTHORIZED_REQ;
658 CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocFlags)
660 CATransportFlags_t caFlags = (CATransportFlags_t)ocFlags;
662 // supply default behavior.
663 if ((caFlags & (CA_IPV6|CA_IPV4)) == 0)
665 caFlags = (CATransportFlags_t)(caFlags|CA_IPV6|CA_IPV4);
667 if ((caFlags & OC_MASK_SCOPE) == 0)
669 caFlags = (CATransportFlags_t)(caFlags|OC_SCOPE_LINK);
674 OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caFlags)
676 return (OCTransportFlags)caFlags;
679 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds)
681 uint32_t lowerBound = 0;
682 uint32_t higherBound = 0;
684 if (!cbNode || !cbNode->presence || !cbNode->presence->timeOut)
686 return OC_STACK_INVALID_PARAM;
689 OC_LOG_V(INFO, TAG, "Update presence TTL, time is %u", GetTicks(0));
691 cbNode->presence->TTL = maxAgeSeconds;
693 for (int index = 0; index < PresenceTimeOutSize; index++)
695 // Guard against overflow
696 if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index]))
699 lowerBound = GetTicks((PresenceTimeOut[index] *
700 cbNode->presence->TTL *
701 MILLISECONDS_PER_SECOND)/100);
705 lowerBound = GetTicks(UINT32_MAX);
708 if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index+1]))
711 higherBound = GetTicks((PresenceTimeOut[index + 1] *
712 cbNode->presence->TTL *
713 MILLISECONDS_PER_SECOND)/100);
717 higherBound = GetTicks(UINT32_MAX);
720 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
722 OC_LOG_V(DEBUG, TAG, "lowerBound timeout %d", lowerBound);
723 OC_LOG_V(DEBUG, TAG, "higherBound timeout %d", higherBound);
724 OC_LOG_V(DEBUG, TAG, "timeOut entry %d", cbNode->presence->timeOut[index]);
727 cbNode->presence->TTLlevel = 0;
729 OC_LOG_V(DEBUG, TAG, "this TTL level %d", cbNode->presence->TTLlevel);
733 const char *convertTriggerEnumToString(OCPresenceTrigger trigger)
735 if (trigger == OC_PRESENCE_TRIGGER_CREATE)
737 return OC_RSRVD_TRIGGER_CREATE;
739 else if (trigger == OC_PRESENCE_TRIGGER_CHANGE)
741 return OC_RSRVD_TRIGGER_CHANGE;
745 return OC_RSRVD_TRIGGER_DELETE;
749 OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr)
753 return OC_PRESENCE_TRIGGER_CREATE;
755 else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CREATE) == 0)
757 return OC_PRESENCE_TRIGGER_CREATE;
759 else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CHANGE) == 0)
761 return OC_PRESENCE_TRIGGER_CHANGE;
765 return OC_PRESENCE_TRIGGER_DELETE;
770 * The cononical presence allows constructed URIs to be string compared.
772 * requestUri must be a char array of size CA_MAX_URI_LENGTH
774 static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint, char *resourceUri,
777 VERIFY_NON_NULL(endpoint , FATAL, OC_STACK_INVALID_PARAM);
778 VERIFY_NON_NULL(resourceUri, FATAL, OC_STACK_INVALID_PARAM);
779 VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM);
781 CAEndpoint_t *ep = (CAEndpoint_t *)endpoint;
783 if (ep->adapter == CA_ADAPTER_IP)
785 if ((ep->flags & CA_IPV6) && !(ep->flags & CA_IPV4))
787 if ('\0' == ep->addr[0]) // multicast
789 return snprintf(presenceUri, CA_MAX_URI_LENGTH, OC_RSRVD_PRESENCE_URI);
793 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://[%s]:%u%s",
794 ep->addr, ep->port, OC_RSRVD_PRESENCE_URI);
799 if ('\0' == ep->addr[0]) // multicast
801 OICStrcpy(ep->addr, sizeof(ep->addr), OC_MULTICAST_IP);
802 ep->port = OC_MULTICAST_PORT;
804 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s:%u%s",
805 ep->addr, ep->port, OC_RSRVD_PRESENCE_URI);
809 // might work for other adapters (untested, but better than nothing)
810 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s%s", ep->addr,
811 OC_RSRVD_PRESENCE_URI);
815 OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
816 const CAResponseInfo_t *responseInfo)
818 VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
819 VERIFY_NON_NULL(responseInfo, FATAL, OC_STACK_INVALID_PARAM);
821 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
822 ClientCB * cbNode = NULL;
823 char *resourceTypeName = NULL;
824 OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
825 OCStackResult result = OC_STACK_ERROR;
828 char presenceUri[CA_MAX_URI_LENGTH];
830 int presenceSubscribe = 0;
831 int multicastPresenceSubscribe = 0;
833 if (responseInfo->result != CA_CONTENT)
835 OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
836 return OC_STACK_ERROR;
839 // check for unicast presence
840 uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri);
841 if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri))
843 return OC_STACK_INVALID_URI;
846 cbNode = GetClientCB(NULL, 0, NULL, presenceUri);
849 presenceSubscribe = 1;
853 // check for multiicast presence
854 CAEndpoint_t ep = { .adapter = endpoint->adapter,
855 .flags = endpoint->flags };
857 uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri);
859 cbNode = GetClientCB(NULL, 0, NULL, presenceUri);
862 multicastPresenceSubscribe = 1;
866 if (!presenceSubscribe && !multicastPresenceSubscribe)
868 OC_LOG(ERROR, TAG, "Received a presence notification, but no callback, ignoring");
872 response.payload = NULL;
873 response.result = OC_STACK_OK;
875 CopyEndpointToDevAddr(endpoint, &response.devAddr);
876 FixUpClientResponse(&response);
878 if (responseInfo->info.payload)
880 result = OCParsePayload(&response.payload,
881 PAYLOAD_TYPE_PRESENCE,
882 responseInfo->info.payload,
883 responseInfo->info.payloadSize);
885 if(result != OC_STACK_OK)
887 OC_LOG(ERROR, TAG, "Presence parse failed");
890 if(!response.payload || response.payload->type != PAYLOAD_TYPE_PRESENCE)
892 OC_LOG(ERROR, TAG, "Presence payload was wrong type");
893 result = OC_STACK_ERROR;
896 response.sequenceNumber = ((OCPresencePayload*)response.payload)->sequenceNumber;
897 resourceTypeName = ((OCPresencePayload*)response.payload)->resourceType;
898 maxAge = ((OCPresencePayload*)response.payload)->maxAge;
901 if (presenceSubscribe)
903 if(cbNode->sequenceNumber == response.sequenceNumber)
905 OC_LOG(INFO, TAG, "No presence change");
911 OC_LOG(INFO, TAG, "Stopping presence");
912 response.result = OC_STACK_PRESENCE_STOPPED;
915 OICFree(cbNode->presence->timeOut);
916 OICFree(cbNode->presence);
917 cbNode->presence = NULL;
922 if(!cbNode->presence)
924 cbNode->presence = (OCPresence *)OICMalloc(sizeof (OCPresence));
926 if(!(cbNode->presence))
928 OC_LOG(ERROR, TAG, "Could not allocate memory for cbNode->presence");
929 result = OC_STACK_NO_MEMORY;
933 VERIFY_NON_NULL_V(cbNode->presence);
934 cbNode->presence->timeOut = NULL;
935 cbNode->presence->timeOut = (uint32_t *)
936 OICMalloc(PresenceTimeOutSize * sizeof(uint32_t));
937 if(!(cbNode->presence->timeOut)){
939 "Could not allocate memory for cbNode->presence->timeOut");
940 OICFree(cbNode->presence);
941 result = OC_STACK_NO_MEMORY;
946 ResetPresenceTTL(cbNode, maxAge);
948 cbNode->sequenceNumber = response.sequenceNumber;
950 // Ensure that a filter is actually applied.
951 if( resourceTypeName && cbNode->filterResourceType)
953 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
962 // This is the multicast case
963 OCMulticastNode* mcNode = NULL;
964 mcNode = GetMCPresenceNode(presenceUri);
968 if(mcNode->nonce == response.sequenceNumber)
970 OC_LOG(INFO, TAG, "No presence change (Multicast)");
973 mcNode->nonce = response.sequenceNumber;
977 OC_LOG(INFO, TAG, "Stopping presence");
978 response.result = OC_STACK_PRESENCE_STOPPED;
983 char* uri = OICStrdup(presenceUri);
987 "No Memory for URI to store in the presence node");
988 result = OC_STACK_NO_MEMORY;
992 result = AddMCPresenceNode(&mcNode, uri, response.sequenceNumber);
993 if(result == OC_STACK_NO_MEMORY)
996 "No Memory for Multicast Presence Node");
1000 // presence node now owns uri
1003 // Ensure that a filter is actually applied.
1004 if(resourceTypeName && cbNode->filterResourceType)
1006 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1013 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
1015 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1017 FindAndDeleteClientCB(cbNode);
1021 OCPayloadDestroy(response.payload);
1025 void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
1027 VERIFY_NON_NULL_NR(endPoint, FATAL);
1028 VERIFY_NON_NULL_NR(responseInfo, FATAL);
1030 OC_LOG(INFO, TAG, "Enter HandleCAResponses");
1032 if(responseInfo->info.resourceUri &&
1033 strcmp(responseInfo->info.resourceUri, OC_RSRVD_PRESENCE_URI) == 0)
1035 HandlePresenceResponse(endPoint, responseInfo);
1039 ClientCB *cbNode = GetClientCB(responseInfo->info.token,
1040 responseInfo->info.tokenLength, NULL, NULL);
1042 ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token,
1043 responseInfo->info.tokenLength);
1047 OC_LOG(INFO, TAG, "There is a cbNode associated with the response token");
1048 if(responseInfo->result == CA_EMPTY)
1050 OC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1051 // We do not have a case for the client to receive a RESET
1052 if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1054 //This is the case of receiving an ACK on a request to a slow resource!
1055 OC_LOG(INFO, TAG, "This is a pure ACK");
1056 //TODO: should we inform the client
1057 // app that at least the request was received at the server?
1060 else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1062 OC_LOG(INFO, TAG, "Receiving A Timeout for this token");
1063 OC_LOG(INFO, TAG, "Calling into application address space");
1065 OCClientResponse response =
1066 {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
1067 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1068 FixUpClientResponse(&response);
1069 response.resourceUri = responseInfo->info.resourceUri;
1070 memcpy(response.identity.id, responseInfo->info.identity.id,
1071 sizeof (response.identity.id));
1072 response.identity.id_length = responseInfo->info.identity.id_length;
1074 response.result = CAToOCStackResult(responseInfo->result);
1075 cbNode->callBack(cbNode->context,
1076 cbNode->handle, &response);
1077 FindAndDeleteClientCB(cbNode);
1081 OC_LOG(INFO, TAG, "This is a regular response, A client call back is found");
1082 OC_LOG(INFO, TAG, "Calling into application address space");
1084 OCClientResponse response =
1085 {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
1086 response.sequenceNumber = OC_OBSERVE_NO_OPTION;
1087 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1088 FixUpClientResponse(&response);
1089 response.resourceUri = responseInfo->info.resourceUri;
1090 memcpy(response.identity.id, responseInfo->info.identity.id,
1091 sizeof (response.identity.id));
1092 response.identity.id_length = responseInfo->info.identity.id_length;
1094 response.result = CAToOCStackResult(responseInfo->result);
1096 if(responseInfo->info.payload &&
1097 responseInfo->info.payloadSize)
1099 OCPayloadType type = PAYLOAD_TYPE_INVALID;
1100 // check the security resource
1101 if (SRMIsSecurityResourceURI(cbNode->requestUri))
1103 type = PAYLOAD_TYPE_SECURITY;
1105 else if (cbNode->method == OC_REST_DISCOVER)
1107 if (strncmp(OC_RSRVD_WELL_KNOWN_URI,cbNode->requestUri,
1108 sizeof(OC_RSRVD_WELL_KNOWN_URI) - 1) == 0)
1110 type = PAYLOAD_TYPE_DISCOVERY;
1112 else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
1114 type = PAYLOAD_TYPE_DEVICE;
1116 else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
1118 type = PAYLOAD_TYPE_PLATFORM;
1122 OC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
1123 cbNode->method, cbNode->requestUri);
1127 else if (cbNode->method == OC_REST_GET ||
1128 cbNode->method == OC_REST_PUT ||
1129 cbNode->method == OC_REST_POST ||
1130 cbNode->method == OC_REST_OBSERVE ||
1131 cbNode->method == OC_REST_OBSERVE_ALL ||
1132 cbNode->method == OC_REST_DELETE)
1134 OC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
1135 cbNode->method, cbNode->requestUri);
1136 type = PAYLOAD_TYPE_REPRESENTATION;
1140 OC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
1141 cbNode->method, cbNode->requestUri);
1145 if(OC_STACK_OK != OCParsePayload(&response.payload,
1147 responseInfo->info.payload,
1148 responseInfo->info.payloadSize))
1150 OC_LOG(ERROR, TAG, "Error converting payload");
1151 OCPayloadDestroy(response.payload);
1156 response.numRcvdVendorSpecificHeaderOptions = 0;
1157 if(responseInfo->info.numOptions > 0)
1160 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
1161 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
1164 uint32_t observationOption;
1165 uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
1166 for (observationOption=0, i=0;
1167 i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
1171 (observationOption << 8) | optionData[i];
1173 response.sequenceNumber = observationOption;
1175 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
1180 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
1183 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
1185 OC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
1186 OCPayloadDestroy(response.payload);
1190 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
1192 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
1193 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
1197 if (cbNode->method == OC_REST_OBSERVE &&
1198 response.sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
1199 response.sequenceNumber <= cbNode->sequenceNumber)
1201 OC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
1202 response.sequenceNumber);
1206 OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
1209 cbNode->sequenceNumber = response.sequenceNumber;
1211 if (appFeedback == OC_STACK_DELETE_TRANSACTION)
1213 FindAndDeleteClientCB(cbNode);
1217 // To keep discovery callbacks active.
1218 cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
1219 MILLISECONDS_PER_SECOND);
1223 //Need to send ACK when the response is CON
1224 if(responseInfo->info.type == CA_MSG_CONFIRM)
1226 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1227 CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL);
1230 OCPayloadDestroy(response.payload);
1237 OC_LOG(INFO, TAG, "There is an observer associated with the response token");
1238 if(responseInfo->result == CA_EMPTY)
1240 OC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1241 if(responseInfo->info.type == CA_MSG_RESET)
1243 OC_LOG(INFO, TAG, "This is a RESET");
1244 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1245 OC_OBSERVER_NOT_INTERESTED);
1247 else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1249 OC_LOG(INFO, TAG, "This is a pure ACK");
1250 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1251 OC_OBSERVER_STILL_INTERESTED);
1254 else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1256 OC_LOG(INFO, TAG, "Receiving Time Out for an observer");
1257 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1258 OC_OBSERVER_FAILED_COMM);
1263 if(!cbNode && !observer)
1265 if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER)
1267 OC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
1268 if(responseInfo->result == CA_EMPTY)
1270 OC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
1274 OC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
1275 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1276 CA_MSG_RESET, 0, NULL, NULL, 0, NULL);
1280 if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
1282 OC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
1283 if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1285 OC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
1286 responseInfo->info.messageId);
1288 if (responseInfo->info.type == CA_MSG_RESET)
1290 OC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
1291 responseInfo->info.messageId);
1298 OC_LOG(INFO, TAG, "Exit HandleCAResponses");
1302 * This function handles error response from CA
1303 * code shall be added to handle the errors
1305 void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errrorInfo)
1307 OC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
1309 if(NULL == endPoint)
1311 OC_LOG(ERROR, TAG, "endPoint is NULL");
1315 if(NULL == errrorInfo)
1317 OC_LOG(ERROR, TAG, "errrorInfo is NULL");
1320 OC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
1324 * This function sends out Direct Stack Responses. These are responses that are not coming
1325 * from the application entity handler. These responses have no payload and are usually ACKs,
1326 * RESETs or some error conditions that were caught by the stack.
1328 OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
1329 const CAResponseResult_t responseResult, const CAMessageType_t type,
1330 const uint8_t numOptions, const CAHeaderOption_t *options,
1331 CAToken_t token, uint8_t tokenLength, const char *resourceUri)
1333 CAResponseInfo_t respInfo = {
1334 .result = responseResult
1336 respInfo.info.messageId = coapID;
1337 respInfo.info.numOptions = numOptions;
1338 respInfo.info.options = (CAHeaderOption_t*)options;
1339 respInfo.info.payload = NULL;
1340 respInfo.info.token = token;
1341 respInfo.info.tokenLength = tokenLength;
1342 respInfo.info.type = type;
1343 respInfo.info.resourceUri = OICStrdup (resourceUri);
1344 respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED;
1346 CAResult_t caResult = CASendResponse(endPoint, &respInfo);
1348 // resourceUri in the info field is cloned in the CA layer and
1349 // thus ownership is still here.
1350 OICFree (respInfo.info.resourceUri);
1352 if(caResult != CA_STATUS_OK)
1354 OC_LOG(ERROR, TAG, "CASendResponse error");
1355 return OC_STACK_ERROR;
1360 //This function will be called back by CA layer when a request is received
1361 void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
1363 OC_LOG(INFO, TAG, "Enter HandleCARequests");
1366 OC_LOG(ERROR, TAG, "endPoint is NULL");
1372 OC_LOG(ERROR, TAG, "requestInfo is NULL");
1376 OCStackResult requestResult = OC_STACK_ERROR;
1378 if(myStackMode == OC_CLIENT)
1380 //TODO: should the client be responding to requests?
1384 OCServerProtocolRequest serverRequest = {0};
1386 OC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
1388 char * uriWithoutQuery = NULL;
1389 char * query = NULL;
1391 requestResult = getQueryFromUri(requestInfo->info.resourceUri, &query, &uriWithoutQuery);
1393 if (requestResult != OC_STACK_OK || !uriWithoutQuery)
1395 OC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
1398 OC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
1399 OC_LOG_V(INFO, TAG, "Query : %s", query);
1401 if(strlen(uriWithoutQuery) < MAX_URI_LENGTH)
1403 OICStrcpy(serverRequest.resourceUrl, sizeof(serverRequest.resourceUrl), uriWithoutQuery);
1404 OICFree(uriWithoutQuery);
1408 OC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
1409 OICFree(uriWithoutQuery);
1416 if(strlen(query) < MAX_QUERY_LENGTH)
1418 OICStrcpy(serverRequest.query, sizeof(serverRequest.query), query);
1423 OC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
1429 if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
1431 serverRequest.reqTotalSize = requestInfo->info.payloadSize;
1432 serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
1433 memcpy (serverRequest.payload, requestInfo->info.payload,
1434 requestInfo->info.payloadSize);
1438 serverRequest.reqTotalSize = 0;
1441 switch (requestInfo->method)
1444 serverRequest.method = OC_REST_GET;
1447 serverRequest.method = OC_REST_PUT;
1450 serverRequest.method = OC_REST_POST;
1453 serverRequest.method = OC_REST_DELETE;
1456 OC_LOG_V(ERROR, TAG, "Received CA method %d not supported", requestInfo->method);
1457 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
1458 requestInfo->info.type, requestInfo->info.numOptions,
1459 requestInfo->info.options, requestInfo->info.token,
1460 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1461 OICFree(serverRequest.payload);
1465 OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token,
1466 requestInfo->info.tokenLength);
1467 serverRequest.requestToken = (CAToken_t)OICMalloc(requestInfo->info.tokenLength);
1468 serverRequest.tokenLength = requestInfo->info.tokenLength;
1470 if (!serverRequest.requestToken)
1472 OC_LOG(FATAL, TAG, "Allocation for token failed.");
1473 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
1474 requestInfo->info.type, requestInfo->info.numOptions,
1475 requestInfo->info.options, requestInfo->info.token,
1476 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1477 OICFree(serverRequest.payload);
1480 memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
1482 switch (requestInfo->info.acceptFormat)
1484 case CA_FORMAT_APPLICATION_CBOR:
1485 serverRequest.acceptFormat = OC_FORMAT_CBOR;
1487 case CA_FORMAT_UNDEFINED:
1488 serverRequest.acceptFormat = OC_FORMAT_UNDEFINED;
1491 serverRequest.acceptFormat = OC_FORMAT_UNSUPPORTED;
1494 if (requestInfo->info.type == CA_MSG_CONFIRM)
1496 serverRequest.qos = OC_HIGH_QOS;
1500 serverRequest.qos = OC_LOW_QOS;
1502 // CA does not need the following field
1503 // Are we sure CA does not need them? how is it responding to multicast
1504 serverRequest.delayedResNeeded = 0;
1506 serverRequest.coapID = requestInfo->info.messageId;
1508 CopyEndpointToDevAddr(endPoint, &serverRequest.devAddr);
1510 // copy vendor specific header options
1511 uint8_t tempNum = (requestInfo->info.numOptions);
1512 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
1513 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
1516 "The request info numOptions is greater than MAX_HEADER_OPTIONS");
1517 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
1518 requestInfo->info.type, requestInfo->info.numOptions,
1519 requestInfo->info.options, requestInfo->info.token,
1520 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1521 OICFree(serverRequest.payload);
1522 OICFree(serverRequest.requestToken);
1525 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
1526 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
1528 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
1529 sizeof(CAHeaderOption_t)*tempNum);
1532 requestResult = HandleStackRequests (&serverRequest);
1534 // Send ACK to client as precursor to slow response
1535 if(requestResult == OC_STACK_SLOW_RESOURCE)
1537 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
1538 CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL);
1540 else if(requestResult != OC_STACK_OK)
1542 OC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
1544 CAResponseResult_t stackResponse =
1545 OCToCAStackResult(requestResult, serverRequest.method);
1547 SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
1548 requestInfo->info.type, requestInfo->info.numOptions,
1549 requestInfo->info.options, requestInfo->info.token,
1550 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1552 // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
1553 // The token is copied in there, and is thus still owned by this function.
1554 OICFree(serverRequest.payload);
1555 OICFree(serverRequest.requestToken);
1556 OC_LOG(INFO, TAG, "Exit HandleCARequests");
1559 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
1561 OC_LOG(INFO, TAG, "Entering HandleStackRequests (OCStack Layer)");
1562 OCStackResult result = OC_STACK_ERROR;
1563 ResourceHandling resHandling;
1564 OCResource *resource;
1565 if(!protocolRequest)
1567 OC_LOG(ERROR, TAG, "protocolRequest is NULL");
1568 return OC_STACK_INVALID_PARAM;
1571 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken,
1572 protocolRequest->tokenLength);
1575 OC_LOG(INFO, TAG, "This is a new Server Request");
1576 result = AddServerRequest(&request, protocolRequest->coapID,
1577 protocolRequest->delayedResNeeded, 0, protocolRequest->method,
1578 protocolRequest->numRcvdVendorSpecificHeaderOptions,
1579 protocolRequest->observationOption, protocolRequest->qos,
1580 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
1581 protocolRequest->payload, protocolRequest->requestToken,
1582 protocolRequest->tokenLength, protocolRequest->resourceUrl,
1583 protocolRequest->reqTotalSize, protocolRequest->acceptFormat,
1584 &protocolRequest->devAddr);
1585 if (OC_STACK_OK != result)
1587 OC_LOG(ERROR, TAG, "Error adding server request");
1593 OC_LOG(ERROR, TAG, "Out of Memory");
1594 return OC_STACK_NO_MEMORY;
1597 if(!protocolRequest->reqMorePacket)
1599 request->requestComplete = 1;
1604 OC_LOG(INFO, TAG, "This is either a repeated or blocked Server Request");
1607 if(request->requestComplete)
1609 OC_LOG(INFO, TAG, "This Server Request is complete");
1610 result = DetermineResourceHandling (request, &resHandling, &resource);
1611 if (result == OC_STACK_OK)
1613 result = ProcessRequest(resHandling, resource, request);
1618 OC_LOG(INFO, TAG, "This Server Request is incomplete");
1619 result = OC_STACK_CONTINUE;
1624 bool validatePlatformInfo(OCPlatformInfo info)
1627 if (!info.platformID)
1629 OC_LOG(ERROR, TAG, "No platform ID found.");
1633 if (info.manufacturerName)
1635 size_t lenManufacturerName = strlen(info.manufacturerName);
1637 if(lenManufacturerName == 0 || lenManufacturerName > MAX_MANUFACTURER_NAME_LENGTH)
1639 OC_LOG(ERROR, TAG, "Manufacturer name fails length requirements.");
1645 OC_LOG(ERROR, TAG, "No manufacturer name present");
1649 if (info.manufacturerUrl)
1651 if(strlen(info.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
1653 OC_LOG(ERROR, TAG, "Manufacturer url fails length requirements.");
1660 //-----------------------------------------------------------------------------
1662 //-----------------------------------------------------------------------------
1664 OCStackResult OCSetRAInfo(const OCRAInfo_t *raInfo)
1667 !raInfo->username ||
1668 !raInfo->hostname ||
1669 !raInfo->xmpp_domain)
1672 return OC_STACK_INVALID_PARAM;
1674 OCStackResult result = CAResultToOCResult(CASetRAInfo((const CARAInfo_t *) raInfo));
1675 gRASetInfo = (result == OC_STACK_OK)? true : false;
1681 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1685 return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
1688 OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags)
1690 if(stackState == OC_STACK_INITIALIZED)
1692 OC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
1693 OCStop() between them are ignored.");
1700 OC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
1701 return OC_STACK_ERROR;
1705 OCStackResult result = OC_STACK_ERROR;
1706 OC_LOG(INFO, TAG, "Entering OCInit");
1709 if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
1711 OC_LOG(ERROR, TAG, "Invalid mode");
1712 return OC_STACK_ERROR;
1716 if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER)
1718 caglobals.client = true;
1720 if (mode == OC_SERVER || mode == OC_CLIENT_SERVER)
1722 caglobals.server = true;
1725 caglobals.serverFlags = (CATransportFlags_t)serverFlags;
1726 if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
1728 caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
1730 caglobals.clientFlags = (CATransportFlags_t)clientFlags;
1731 if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
1733 caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
1737 if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
1739 caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4);
1741 if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
1743 caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4);
1747 defaultDeviceHandler = NULL;
1748 defaultDeviceHandlerCallbackParameter = NULL;
1751 result = CAResultToOCResult(CAInitialize());
1752 VERIFY_SUCCESS(result, OC_STACK_OK);
1754 result = CAResultToOCResult(OCSelectNetwork());
1755 VERIFY_SUCCESS(result, OC_STACK_OK);
1757 switch (myStackMode)
1760 CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1761 result = CAResultToOCResult(CAStartDiscoveryServer());
1762 OC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
1765 SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1766 result = CAResultToOCResult(CAStartListeningServer());
1767 OC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
1769 case OC_CLIENT_SERVER:
1770 SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1771 result = CAResultToOCResult(CAStartListeningServer());
1772 if(result == OC_STACK_OK)
1774 result = CAResultToOCResult(CAStartDiscoveryServer());
1778 VERIFY_SUCCESS(result, OC_STACK_OK);
1780 #ifdef WITH_PRESENCE
1781 PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
1782 #endif // WITH_PRESENCE
1784 //Update Stack state to initialized
1785 stackState = OC_STACK_INITIALIZED;
1787 // Initialize resource
1788 if(myStackMode != OC_CLIENT)
1790 result = initResources();
1793 // Initialize the SRM Policy Engine
1794 if(result == OC_STACK_OK)
1796 result = SRMInitPolicyEngine();
1797 // TODO after BeachHead delivery: consolidate into single SRMInit()
1801 if(result != OC_STACK_OK)
1803 OC_LOG(ERROR, TAG, "Stack initialization error");
1804 deleteAllResources();
1806 stackState = OC_STACK_UNINITIALIZED;
1811 OCStackResult OCStop()
1813 OC_LOG(INFO, TAG, "Entering OCStop");
1815 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1817 OC_LOG(DEBUG, TAG, "Stack already stopping, exiting");
1820 else if (stackState != OC_STACK_INITIALIZED)
1822 OC_LOG(ERROR, TAG, "Stack not initialized");
1823 return OC_STACK_ERROR;
1826 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1828 #ifdef WITH_PRESENCE
1829 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1830 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1831 presenceResource.presenceTTL = 0;
1832 #endif // WITH_PRESENCE
1834 // Free memory dynamically allocated for resources
1835 deleteAllResources();
1837 DeletePlatformInfo();
1839 // Remove all observers
1840 DeleteObserverList();
1841 // Remove all the client callbacks
1842 DeleteClientCBList();
1844 // De-init the SRM Policy Engine
1845 // TODO after BeachHead delivery: consolidate into single SRMDeInit()
1846 SRMDeInitPolicyEngine();
1849 stackState = OC_STACK_UNINITIALIZED;
1853 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1858 return CA_MSG_CONFIRM;
1863 return CA_MSG_NONCONFIRM;
1867 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1871 query = strchr (inputUri, '?');
1875 if((query - inputUri) > MAX_URI_LENGTH)
1877 return OC_STACK_INVALID_URI;
1880 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1882 return OC_STACK_INVALID_QUERY;
1885 else if(uriLen > MAX_URI_LENGTH)
1887 return OC_STACK_INVALID_URI;
1893 * A request uri consists of the following components in order:
1896 * CoAP over UDP prefix "coap://"
1897 * CoAP over TCP prefix "coap+tcp://"
1899 * IPv6 address "[1234::5678]"
1900 * IPv4 address "192.168.1.1"
1901 * optional port ":5683"
1902 * resource uri "/oc/core..."
1904 * for PRESENCE requests, extract resource type.
1906 static OCStackResult ParseRequestUri(const char *fullUri,
1907 OCTransportAdapter adapter,
1908 OCTransportFlags flags,
1909 OCDevAddr **devAddr,
1911 char **resourceType)
1913 VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
1915 OCStackResult result = OC_STACK_OK;
1916 OCDevAddr *da = NULL;
1920 // provide defaults for all returned values
1927 *resourceUri = NULL;
1931 *resourceType = NULL;
1934 // delimit url prefix, if any
1935 const char *start = fullUri;
1936 char *slash2 = strstr(start, "//");
1941 char *slash = strchr(start, '/');
1944 return OC_STACK_INVALID_URI;
1948 // process url scheme
1949 size_t prefixLen = slash2 - fullUri;
1953 if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
1960 // TODO: this logic should come in with unit tests exercising the various strings
1961 // processs url prefix, if any
1962 size_t urlLen = slash - start;
1966 if (urlLen && devAddr)
1967 { // construct OCDevAddr
1968 if (start[0] == '[')
1970 char *close = strchr(++start, ']');
1971 if (!close || close > slash)
1973 return OC_STACK_INVALID_URI;
1976 if (close[1] == ':')
1980 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
1981 flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
1985 char *dot = strchr(start, '.');
1986 if (dot && dot < slash)
1988 colon = strchr(start, ':');
1989 end = (colon && colon < slash) ? colon : slash;
1993 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
1998 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
1999 flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
2008 if (len >= sizeof(da->addr))
2010 return OC_STACK_INVALID_URI;
2012 // collect port, if any
2013 if (colon && colon < slash)
2015 for (colon++; colon < slash; colon++)
2018 if (c < '0' || c > '9')
2020 return OC_STACK_INVALID_URI;
2022 port = 10 * port + c - '0';
2027 if (len >= sizeof(da->addr))
2029 return OC_STACK_INVALID_URI;
2032 da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
2035 return OC_STACK_NO_MEMORY;
2037 OICStrcpyPartial(da->addr, sizeof(da->addr), start, len);
2039 da->adapter = adapter;
2041 if (!strncmp(fullUri, "coaps:", 6))
2043 da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
2048 // process resource uri, if any
2050 { // request uri and query
2051 size_t ulen = strlen(slash); // resource uri length
2052 size_t tlen = 0; // resource type length
2055 static const char strPresence[] = "/oic/ad?rt=";
2056 static const size_t lenPresence = sizeof(strPresence) - 1;
2057 if (!strncmp(slash, strPresence, lenPresence))
2059 type = slash + lenPresence;
2060 tlen = ulen - lenPresence;
2065 *resourceUri = (char *)OICMalloc(ulen + 1);
2068 result = OC_STACK_NO_MEMORY;
2071 strcpy(*resourceUri, slash);
2074 if (type && resourceType)
2076 *resourceType = (char *)OICMalloc(tlen + 1);
2079 result = OC_STACK_NO_MEMORY;
2083 OICStrcpy(*resourceType, (tlen+1), type);
2090 // free all returned values
2097 OICFree(*resourceUri);
2101 OICFree(*resourceType);
2106 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
2107 char *resourceUri, char **requestUri)
2109 char uri[CA_MAX_URI_LENGTH];
2111 FormCanonicalPresenceUri(endpoint, resourceUri, uri);
2113 *requestUri = OICStrdup(uri);
2116 return OC_STACK_NO_MEMORY;
2123 * Discover or Perform requests on a specified resource
2125 OCStackResult OCDoResource(OCDoHandle *handle,
2127 const char *requestUri,
2128 const OCDevAddr *destination,
2130 OCConnectivityType connectivityType,
2131 OCQualityOfService qos,
2132 OCCallbackData *cbData,
2133 OCHeaderOption *options,
2136 OC_LOG(INFO, TAG, "Entering OCDoResource");
2138 // Validate input parameters
2139 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
2140 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
2141 VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI);
2143 OCStackResult result = OC_STACK_ERROR;
2144 CAResult_t caResult;
2145 CAToken_t token = NULL;
2146 uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2147 ClientCB *clientCB = NULL;
2148 OCDoHandle resHandle = NULL;
2149 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2150 OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
2152 OCTransportAdapter adapter;
2153 OCTransportFlags flags;
2154 // the request contents are put here
2155 CARequestInfo_t requestInfo = {.method = CA_GET};
2156 // requestUri will be parsed into the following three variables
2157 OCDevAddr *devAddr = NULL;
2158 char *resourceUri = NULL;
2159 char *resourceType = NULL;
2161 // To track if memory is allocated for additional header options
2162 uint8_t hdrOptionMemAlloc = 0;
2164 // This validation is broken, but doesn't cause harm
2165 size_t uriLen = strlen(requestUri );
2166 if ((result = verifyUriQueryLength(requestUri , uriLen)) != OC_STACK_OK)
2172 * Support original behavior with address on resourceUri argument.
2174 adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2175 flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2177 result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2179 if (result != OC_STACK_OK)
2181 OC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2188 case OC_REST_OBSERVE:
2189 case OC_REST_OBSERVE_ALL:
2190 case OC_REST_CANCEL_OBSERVE:
2191 requestInfo.method = CA_GET;
2194 requestInfo.method = CA_PUT;
2197 requestInfo.method = CA_POST;
2199 case OC_REST_DELETE:
2200 requestInfo.method = CA_DELETE;
2202 case OC_REST_DISCOVER:
2204 if (destination || devAddr)
2206 requestInfo.isMulticast = false;
2210 tmpDevAddr.adapter = adapter;
2211 tmpDevAddr.flags = flags;
2212 destination = &tmpDevAddr;
2213 requestInfo.isMulticast = true;
2215 // CA_DISCOVER will become GET and isMulticast
2216 requestInfo.method = CA_GET;
2218 #ifdef WITH_PRESENCE
2219 case OC_REST_PRESENCE:
2220 // Replacing method type with GET because "presence"
2221 // is a stack layer only implementation.
2222 requestInfo.method = CA_GET;
2226 result = OC_STACK_INVALID_METHOD;
2230 if (!devAddr && !destination)
2232 OC_LOG(DEBUG, TAG, "no devAddr and no destination");
2233 result = OC_STACK_INVALID_PARAM;
2237 /* If not original behavior, use destination argument */
2238 if (destination && !devAddr)
2240 devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2243 result = OC_STACK_NO_MEMORY;
2246 *devAddr = *destination;
2249 resHandle = GenerateInvocationHandle();
2252 result = OC_STACK_NO_MEMORY;
2256 caResult = CAGenerateToken(&token, tokenLength);
2257 if (caResult != CA_STATUS_OK)
2259 OC_LOG(ERROR, TAG, "CAGenerateToken error");
2260 result= OC_STACK_ERROR;
2264 // fill in request data
2265 requestInfo.info.type = qualityOfServiceToMessageType(qos);
2266 requestInfo.info.token = token;
2267 requestInfo.info.tokenLength = tokenLength;
2268 requestInfo.info.resourceUri = resourceUri;
2270 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
2272 result = CreateObserveHeaderOption (&(requestInfo.info.options),
2273 options, numOptions, OC_OBSERVE_REGISTER);
2274 if (result != OC_STACK_OK)
2278 hdrOptionMemAlloc = 1;
2279 requestInfo.info.numOptions = numOptions + 1;
2283 requestInfo.info.options = (CAHeaderOption_t*)options;
2284 requestInfo.info.numOptions = numOptions;
2287 CopyDevAddrToEndpoint(devAddr, &endpoint);
2292 OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
2295 OC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
2298 requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
2302 requestInfo.info.payload = NULL;
2303 requestInfo.info.payloadSize = 0;
2304 requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
2307 if (result != OC_STACK_OK)
2309 OC_LOG(ERROR, TAG, "CACreateEndpoint error");
2313 // prepare for response
2314 #ifdef WITH_PRESENCE
2315 if (method == OC_REST_PRESENCE)
2317 char *presenceUri = NULL;
2318 result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
2319 if (OC_STACK_OK != result)
2324 // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
2325 // Presence notification will form a canonical uri to
2326 // look for callbacks into the application.
2327 resourceUri = presenceUri;
2331 ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
2332 result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
2333 method, devAddr, resourceUri, resourceType, ttl);
2334 if (OC_STACK_OK != result)
2339 devAddr = NULL; // Client CB list entry now owns it
2340 resourceUri = NULL; // Client CB list entry now owns it
2341 resourceType = NULL; // Client CB list entry now owns it
2344 result = OCSendRequest(&endpoint, &requestInfo);
2345 if (OC_STACK_OK != result)
2352 *handle = resHandle;
2356 if (result != OC_STACK_OK)
2358 OC_LOG(ERROR, TAG, "OCDoResource error");
2359 FindAndDeleteClientCB(clientCB);
2360 CADestroyToken(token);
2368 // This is the owner of the payload object, so we free it
2369 OCPayloadDestroy(payload);
2370 OICFree(requestInfo.info.payload);
2372 OICFree(resourceUri);
2373 OICFree(resourceType);
2374 if (hdrOptionMemAlloc)
2376 OICFree(requestInfo.info.options);
2381 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
2385 * This ftn is implemented one of two ways in the case of observation:
2387 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
2388 * Remove the callback associated on client side.
2389 * When the next notification comes in from server,
2390 * reply with RESET message to server.
2391 * Keep in mind that the server will react to RESET only
2392 * if the last notification was sent as CON
2394 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
2395 * and it is associated with an observe request
2396 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
2397 * Send CON Observe request to server with
2398 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
2399 * Remove the callback associated on client side.
2401 OCStackResult ret = OC_STACK_OK;
2402 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2403 CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2404 CARequestInfo_t requestInfo = {.method = CA_GET};
2408 return OC_STACK_INVALID_PARAM;
2411 ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
2414 OC_LOG(ERROR, TAG, "Client callback not found. Called OCCancel twice?");
2418 switch (clientCB->method)
2420 case OC_REST_OBSERVE:
2421 case OC_REST_OBSERVE_ALL:
2422 OC_LOG_V(INFO, TAG, "Canceling observation for resource %s",
2423 clientCB->requestUri);
2424 if (qos != OC_HIGH_QOS)
2426 FindAndDeleteClientCB(clientCB);
2431 OC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
2434 requestData.type = qualityOfServiceToMessageType(qos);
2435 requestData.token = clientCB->token;
2436 requestData.tokenLength = clientCB->tokenLength;
2437 if (CreateObserveHeaderOption (&(requestData.options),
2438 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
2440 return OC_STACK_ERROR;
2442 requestData.numOptions = numOptions + 1;
2443 requestData.resourceUri = OICStrdup (clientCB->requestUri);
2445 requestInfo.method = CA_GET;
2446 requestInfo.info = requestData;
2448 CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
2451 ret = OCSendRequest(&endpoint, &requestInfo);
2454 #ifdef WITH_PRESENCE
2455 case OC_REST_PRESENCE:
2456 FindAndDeleteClientCB(clientCB);
2461 ret = OC_STACK_INVALID_METHOD;
2466 if (requestData.numOptions > 0)
2468 OICFree(requestData.options);
2470 if (requestData.resourceUri)
2472 OICFree (requestData.resourceUri);
2478 * @brief Register Persistent storage callback.
2479 * @param persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
2481 * OC_STACK_OK - No errors; Success
2482 * OC_STACK_INVALID_PARAM - Invalid parameter
2484 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
2486 OC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
2487 if(!persistentStorageHandler)
2489 OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2490 return OC_STACK_INVALID_PARAM;
2494 if( !persistentStorageHandler->open ||
2495 !persistentStorageHandler->close ||
2496 !persistentStorageHandler->read ||
2497 !persistentStorageHandler->unlink ||
2498 !persistentStorageHandler->write)
2500 OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2501 return OC_STACK_INVALID_PARAM;
2504 return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
2507 #ifdef WITH_PRESENCE
2509 OCStackResult OCProcessPresence()
2511 OCStackResult result = OC_STACK_OK;
2513 // the following line floods the log with messages that are irrelevant
2514 // to most purposes. Uncomment as needed.
2515 //OC_LOG(INFO, TAG, "Entering RequestPresence");
2516 ClientCB* cbNode = NULL;
2517 OCClientResponse clientResponse;
2518 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
2520 LL_FOREACH(cbList, cbNode)
2522 if (OC_REST_PRESENCE != cbNode->method || !cbNode->presence)
2527 uint32_t now = GetTicks(0);
2528 OC_LOG_V(DEBUG, TAG, "this TTL level %d",
2529 cbNode->presence->TTLlevel);
2530 OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
2532 if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
2537 if (cbNode->presence->TTLlevel < PresenceTimeOutSize)
2539 OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
2540 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2542 if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2544 OC_LOG(DEBUG, TAG, "No more timeout ticks");
2546 clientResponse.sequenceNumber = 0;
2547 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
2548 clientResponse.devAddr = *cbNode->devAddr;
2549 FixUpClientResponse(&clientResponse);
2550 clientResponse.payload = NULL;
2552 // Increment the TTLLevel (going to a next state), so we don't keep
2553 // sending presence notification to client.
2554 cbNode->presence->TTLlevel++;
2555 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
2556 cbNode->presence->TTLlevel);
2558 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
2559 if (cbResult == OC_STACK_DELETE_TRANSACTION)
2561 FindAndDeleteClientCB(cbNode);
2565 if (now < cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2570 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2571 CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2572 CARequestInfo_t requestInfo = {.method = CA_GET};
2574 OC_LOG(DEBUG, TAG, "time to test server presence");
2576 CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
2578 requestData.type = CA_MSG_NONCONFIRM;
2579 requestData.token = cbNode->token;
2580 requestData.tokenLength = cbNode->tokenLength;
2581 requestData.resourceUri = OC_RSRVD_PRESENCE_URI;
2582 requestInfo.method = CA_GET;
2583 requestInfo.info = requestData;
2585 result = OCSendRequest(&endpoint, &requestInfo);
2586 if (OC_STACK_OK != result)
2591 cbNode->presence->TTLlevel++;
2592 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel);
2595 if (result != OC_STACK_OK)
2597 OC_LOG(ERROR, TAG, "OCProcessPresence error");
2602 #endif // WITH_PRESENCE
2604 OCStackResult OCProcess()
2606 #ifdef WITH_PRESENCE
2607 OCProcessPresence();
2609 CAHandleRequestResponse();
2614 #ifdef WITH_PRESENCE
2615 OCStackResult OCStartPresence(const uint32_t ttl)
2617 uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2618 OCChangeResourceProperty(
2619 &(((OCResource *)presenceResource.handle)->resourceProperties),
2622 if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
2624 presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
2625 OC_LOG(INFO, TAG, "Setting Presence TTL to max value");
2629 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
2630 OC_LOG(INFO, TAG, "Setting Presence TTL to default value");
2634 presenceResource.presenceTTL = ttl;
2636 OC_LOG_V(DEBUG, TAG, "Presence TTL is %lu seconds", presenceResource.presenceTTL);
2638 if (OC_PRESENCE_UNINITIALIZED == presenceState)
2640 presenceState = OC_PRESENCE_INITIALIZED;
2642 OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
2644 CAToken_t caToken = NULL;
2645 CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
2646 if (caResult != CA_STATUS_OK)
2648 OC_LOG(ERROR, TAG, "CAGenerateToken error");
2649 CADestroyToken(caToken);
2650 return OC_STACK_ERROR;
2653 AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
2654 (OCResource *)presenceResource.handle, OC_LOW_QOS, OC_FORMAT_UNDEFINED, &devAddr);
2655 CADestroyToken(caToken);
2658 // Each time OCStartPresence is called
2659 // a different random 32-bit integer number is used
2660 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2662 return SendPresenceNotification(((OCResource *)presenceResource.handle)->rsrcType,
2663 OC_PRESENCE_TRIGGER_CREATE);
2666 OCStackResult OCStopPresence()
2668 OCStackResult result = OC_STACK_ERROR;
2670 if(presenceResource.handle)
2672 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2674 // make resource inactive
2675 result = OCChangeResourceProperty(
2676 &(((OCResource *) presenceResource.handle)->resourceProperties),
2680 if(result != OC_STACK_OK)
2683 "Changing the presence resource properties to ACTIVE not successful");
2687 return SendStopNotification();
2691 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler,
2692 void* callbackParameter)
2694 defaultDeviceHandler = entityHandler;
2695 defaultDeviceHandlerCallbackParameter = callbackParameter;
2700 OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
2702 OC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2704 if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
2706 if (validatePlatformInfo(platformInfo))
2708 return SavePlatformInfo(platformInfo);
2712 return OC_STACK_INVALID_PARAM;
2717 return OC_STACK_ERROR;
2721 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2723 OC_LOG(INFO, TAG, "Entering OCSetDeviceInfo");
2725 if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
2727 OC_LOG(ERROR, TAG, "Null or empty device name.");
2728 return OC_STACK_INVALID_PARAM;
2731 return SaveDeviceInfo(deviceInfo);
2734 OCStackResult OCCreateResource(OCResourceHandle *handle,
2735 const char *resourceTypeName,
2736 const char *resourceInterfaceName,
2737 const char *uri, OCEntityHandler entityHandler,
2738 void* callbackParam,
2739 uint8_t resourceProperties)
2742 OCResource *pointer = NULL;
2744 OCStackResult result = OC_STACK_ERROR;
2746 OC_LOG(INFO, TAG, "Entering OCCreateResource");
2748 if(myStackMode == OC_CLIENT)
2750 return OC_STACK_INVALID_PARAM;
2752 // Validate parameters
2753 if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
2755 OC_LOG(ERROR, TAG, "URI is empty or too long");
2756 return OC_STACK_INVALID_URI;
2758 // Is it presented during resource discovery?
2759 if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
2761 OC_LOG(ERROR, TAG, "Input parameter is NULL");
2762 return OC_STACK_INVALID_PARAM;
2765 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
2767 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2770 // Make sure resourceProperties bitmask has allowed properties specified
2771 if (resourceProperties
2772 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
2773 OC_EXPLICIT_DISCOVERABLE))
2775 OC_LOG(ERROR, TAG, "Invalid property");
2776 return OC_STACK_INVALID_PARAM;
2779 // If the headResource is NULL, then no resources have been created...
2780 pointer = headResource;
2783 // At least one resources is in the resource list, so we need to search for
2784 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2787 if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
2789 OC_LOG_V(ERROR, TAG, "Resource %s already exists", uri);
2790 return OC_STACK_INVALID_PARAM;
2792 pointer = pointer->next;
2795 // Create the pointer and insert it into the resource list
2796 pointer = (OCResource *) OICCalloc(1, sizeof(OCResource));
2799 result = OC_STACK_NO_MEMORY;
2802 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2804 insertResource(pointer);
2807 str = OICStrdup(uri);
2810 result = OC_STACK_NO_MEMORY;
2815 // Set properties. Set OC_ACTIVE
2816 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2819 // Add the resourcetype to the resource
2820 result = BindResourceTypeToResource(pointer, resourceTypeName);
2821 if (result != OC_STACK_OK)
2823 OC_LOG(ERROR, TAG, "Error adding resourcetype");
2827 // Add the resourceinterface to the resource
2828 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2829 if (result != OC_STACK_OK)
2831 OC_LOG(ERROR, TAG, "Error adding resourceinterface");
2835 // If an entity handler has been passed, attach it to the newly created
2836 // resource. Otherwise, set the default entity handler.
2839 pointer->entityHandler = entityHandler;
2840 pointer->entityHandlerCallbackParam = callbackParam;
2844 pointer->entityHandler = defaultResourceEHandler;
2845 pointer->entityHandlerCallbackParam = NULL;
2849 result = OC_STACK_OK;
2851 #ifdef WITH_PRESENCE
2852 if (presenceResource.handle)
2854 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2855 SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
2859 if (result != OC_STACK_OK)
2861 // Deep delete of resource and other dynamic elements that it contains
2862 deleteResource(pointer);
2869 OCStackResult OCBindResource(
2870 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2872 OCResource *resource = NULL;
2875 OC_LOG(INFO, TAG, "Entering OCBindResource");
2877 // Validate parameters
2878 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2879 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2880 // Container cannot contain itself
2881 if (collectionHandle == resourceHandle)
2883 OC_LOG(ERROR, TAG, "Added handle equals collection handle");
2884 return OC_STACK_INVALID_PARAM;
2887 // Use the handle to find the resource in the resource linked list
2888 resource = findResource((OCResource *) collectionHandle);
2891 OC_LOG(ERROR, TAG, "Collection handle not found");
2892 return OC_STACK_INVALID_PARAM;
2895 // Look for an open slot to add add the child resource.
2896 // If found, add it and return success
2897 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2899 if (!resource->rsrcResources[i])
2901 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2902 OC_LOG(INFO, TAG, "resource bound");
2904 #ifdef WITH_PRESENCE
2905 if (presenceResource.handle)
2907 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2908 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
2909 OC_PRESENCE_TRIGGER_CHANGE);
2917 // Unable to add resourceHandle, so return error
2918 return OC_STACK_ERROR;
2921 OCStackResult OCUnBindResource(
2922 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2924 OCResource *resource = NULL;
2927 OC_LOG(INFO, TAG, "Entering OCUnBindResource");
2929 // Validate parameters
2930 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2931 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2932 // Container cannot contain itself
2933 if (collectionHandle == resourceHandle)
2935 OC_LOG(ERROR, TAG, "removing handle equals collection handle");
2936 return OC_STACK_INVALID_PARAM;
2939 // Use the handle to find the resource in the resource linked list
2940 resource = findResource((OCResource *) collectionHandle);
2943 OC_LOG(ERROR, TAG, "Collection handle not found");
2944 return OC_STACK_INVALID_PARAM;
2947 // Look for an open slot to add add the child resource.
2948 // If found, add it and return success
2949 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2951 if (resourceHandle == resource->rsrcResources[i])
2953 resource->rsrcResources[i] = (OCResource *) NULL;
2954 OC_LOG(INFO, TAG, "resource unbound");
2956 // Send notification when resource is unbounded successfully.
2957 #ifdef WITH_PRESENCE
2958 if (presenceResource.handle)
2960 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2961 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
2962 OC_PRESENCE_TRIGGER_CHANGE);
2969 OC_LOG(INFO, TAG, "resource not found in collection");
2971 // Unable to add resourceHandle, so return error
2972 return OC_STACK_ERROR;
2975 OCStackResult BindResourceTypeToResource(OCResource* resource,
2976 const char *resourceTypeName)
2978 OCResourceType *pointer = NULL;
2980 OCStackResult result = OC_STACK_ERROR;
2982 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2984 pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
2987 result = OC_STACK_NO_MEMORY;
2991 str = OICStrdup(resourceTypeName);
2994 result = OC_STACK_NO_MEMORY;
2997 pointer->resourcetypename = str;
2999 insertResourceType(resource, pointer);
3000 result = OC_STACK_OK;
3003 if (result != OC_STACK_OK)
3012 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
3013 const char *resourceInterfaceName)
3015 OCResourceInterface *pointer = NULL;
3017 OCStackResult result = OC_STACK_ERROR;
3019 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
3021 OC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
3023 pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
3026 result = OC_STACK_NO_MEMORY;
3030 str = OICStrdup(resourceInterfaceName);
3033 result = OC_STACK_NO_MEMORY;
3036 pointer->name = str;
3038 // Bind the resourceinterface to the resource
3039 insertResourceInterface(resource, pointer);
3041 result = OC_STACK_OK;
3044 if (result != OC_STACK_OK)
3053 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
3054 const char *resourceTypeName)
3057 OCStackResult result = OC_STACK_ERROR;
3058 OCResource *resource = NULL;
3060 resource = findResource((OCResource *) handle);
3063 OC_LOG(ERROR, TAG, "Resource not found");
3064 return OC_STACK_ERROR;
3067 result = BindResourceTypeToResource(resource, resourceTypeName);
3069 #ifdef WITH_PRESENCE
3070 if(presenceResource.handle)
3072 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3073 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3080 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
3081 const char *resourceInterfaceName)
3084 OCStackResult result = OC_STACK_ERROR;
3085 OCResource *resource = NULL;
3087 resource = findResource((OCResource *) handle);
3090 OC_LOG(ERROR, TAG, "Resource not found");
3091 return OC_STACK_ERROR;
3094 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
3096 #ifdef WITH_PRESENCE
3097 if (presenceResource.handle)
3099 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3100 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3107 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
3109 OCResource *pointer = headResource;
3111 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
3115 *numResources = *numResources + 1;
3116 pointer = pointer->next;
3121 OCResourceHandle OCGetResourceHandle(uint8_t index)
3123 OCResource *pointer = headResource;
3125 for( uint8_t i = 0; i < index && pointer; ++i)
3127 pointer = pointer->next;
3129 return (OCResourceHandle) pointer;
3132 OCStackResult OCDeleteResource(OCResourceHandle handle)
3136 OC_LOG(ERROR, TAG, "Invalid handle for deletion");
3137 return OC_STACK_INVALID_PARAM;
3140 OCResource *resource = findResource((OCResource *) handle);
3141 if (resource == NULL)
3143 OC_LOG(ERROR, TAG, "Resource not found");
3144 return OC_STACK_NO_RESOURCE;
3147 if (deleteResource((OCResource *) handle) != OC_STACK_OK)
3149 OC_LOG(ERROR, TAG, "Error deleting resource");
3150 return OC_STACK_ERROR;
3156 const char *OCGetResourceUri(OCResourceHandle handle)
3158 OCResource *resource = NULL;
3160 resource = findResource((OCResource *) handle);
3163 return resource->uri;
3165 return (const char *) NULL;
3168 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
3170 OCResource *resource = NULL;
3172 resource = findResource((OCResource *) handle);
3175 return resource->resourceProperties;
3177 return (OCResourceProperty)-1;
3180 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
3181 uint8_t *numResourceTypes)
3183 OCResource *resource = NULL;
3184 OCResourceType *pointer = NULL;
3186 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
3187 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3189 *numResourceTypes = 0;
3191 resource = findResource((OCResource *) handle);
3194 pointer = resource->rsrcType;
3197 *numResourceTypes = *numResourceTypes + 1;
3198 pointer = pointer->next;
3204 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
3206 OCResourceType *resourceType = NULL;
3208 resourceType = findResourceTypeAtIndex(handle, index);
3211 return resourceType->resourcetypename;
3213 return (const char *) NULL;
3216 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
3217 uint8_t *numResourceInterfaces)
3219 OCResourceInterface *pointer = NULL;
3220 OCResource *resource = NULL;
3222 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3223 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
3225 *numResourceInterfaces = 0;
3226 resource = findResource((OCResource *) handle);
3229 pointer = resource->rsrcInterface;
3232 *numResourceInterfaces = *numResourceInterfaces + 1;
3233 pointer = pointer->next;
3239 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
3241 OCResourceInterface *resourceInterface = NULL;
3243 resourceInterface = findResourceInterfaceAtIndex(handle, index);
3244 if (resourceInterface)
3246 return resourceInterface->name;
3248 return (const char *) NULL;
3251 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
3254 OCResource *resource = NULL;
3256 if (index >= MAX_CONTAINED_RESOURCES)
3261 resource = findResource((OCResource *) collectionHandle);
3267 return resource->rsrcResources[index];
3270 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
3271 OCEntityHandler entityHandler,
3272 void* callbackParam)
3274 OCResource *resource = NULL;
3276 // Validate parameters
3277 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3279 // Use the handle to find the resource in the resource linked list
3280 resource = findResource((OCResource *)handle);
3283 OC_LOG(ERROR, TAG, "Resource not found");
3284 return OC_STACK_ERROR;
3288 resource->entityHandler = entityHandler;
3289 resource->entityHandlerCallbackParam = callbackParam;
3291 #ifdef WITH_PRESENCE
3292 if (presenceResource.handle)
3294 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3295 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3302 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
3304 OCResource *resource = NULL;
3306 resource = findResource((OCResource *)handle);
3309 OC_LOG(ERROR, TAG, "Resource not found");
3314 return resource->entityHandler;
3317 void incrementSequenceNumber(OCResource * resPtr)
3319 // Increment the sequence number
3320 resPtr->sequenceNum += 1;
3321 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3323 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3328 #ifdef WITH_PRESENCE
3329 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
3330 OCPresenceTrigger trigger)
3332 OCResource *resPtr = NULL;
3333 OCStackResult result = OC_STACK_ERROR;
3334 OCMethod method = OC_REST_PRESENCE;
3335 uint32_t maxAge = 0;
3336 resPtr = findResource((OCResource *) presenceResource.handle);
3339 return OC_STACK_NO_RESOURCE;
3342 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3344 maxAge = presenceResource.presenceTTL;
3346 result = SendAllObserverNotification(method, resPtr, maxAge,
3347 trigger, resourceType, OC_LOW_QOS);
3353 OCStackResult SendStopNotification()
3355 OCResource *resPtr = NULL;
3356 OCStackResult result = OC_STACK_ERROR;
3357 OCMethod method = OC_REST_PRESENCE;
3358 resPtr = findResource((OCResource *) presenceResource.handle);
3361 return OC_STACK_NO_RESOURCE;
3364 // maxAge is 0. ResourceType is NULL.
3365 result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
3371 #endif // WITH_PRESENCE
3372 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
3374 OCResource *resPtr = NULL;
3375 OCStackResult result = OC_STACK_ERROR;
3376 OCMethod method = OC_REST_NOMETHOD;
3377 uint32_t maxAge = 0;
3379 OC_LOG(INFO, TAG, "Notifying all observers");
3380 #ifdef WITH_PRESENCE
3381 if(handle == presenceResource.handle)
3385 #endif // WITH_PRESENCE
3386 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3388 // Verify that the resource exists
3389 resPtr = findResource ((OCResource *) handle);
3392 return OC_STACK_NO_RESOURCE;
3396 //only increment in the case of regular observing (not presence)
3397 incrementSequenceNumber(resPtr);
3398 method = OC_REST_OBSERVE;
3399 maxAge = MAX_OBSERVE_AGE;
3400 #ifdef WITH_PRESENCE
3401 result = SendAllObserverNotification (method, resPtr, maxAge,
3402 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
3404 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3411 OCNotifyListOfObservers (OCResourceHandle handle,
3412 OCObservationId *obsIdList,
3413 uint8_t numberOfIds,
3414 const OCRepPayload *payload,
3415 OCQualityOfService qos)
3417 OC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
3419 OCResource *resPtr = NULL;
3420 //TODO: we should allow the server to define this
3421 uint32_t maxAge = MAX_OBSERVE_AGE;
3423 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3424 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3425 VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
3427 resPtr = findResource ((OCResource *) handle);
3428 if (NULL == resPtr || myStackMode == OC_CLIENT)
3430 return OC_STACK_NO_RESOURCE;
3434 incrementSequenceNumber(resPtr);
3436 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3437 payload, maxAge, qos));
3440 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3442 OCStackResult result = OC_STACK_ERROR;
3443 OCServerRequest *serverRequest = NULL;
3445 OC_LOG(INFO, TAG, "Entering OCDoResponse");
3447 // Validate input parameters
3448 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3449 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3452 // Get pointer to request info
3453 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3456 // response handler in ocserverrequest.c. Usually HandleSingleResponse.
3457 result = serverRequest->ehResponseHandler(ehResponse);
3463 //-----------------------------------------------------------------------------
3464 // Private internal function definitions
3465 //-----------------------------------------------------------------------------
3466 static OCDoHandle GenerateInvocationHandle()
3468 OCDoHandle handle = NULL;
3469 // Generate token here, it will be deleted when the transaction is deleted
3470 handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3473 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3479 #ifdef WITH_PRESENCE
3480 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3481 OCResourceProperty resourceProperties, uint8_t enable)
3485 return OC_STACK_INVALID_PARAM;
3487 if (resourceProperties
3488 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3490 OC_LOG(ERROR, TAG, "Invalid property");
3491 return OC_STACK_INVALID_PARAM;
3495 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3499 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3505 OCStackResult initResources()
3507 OCStackResult result = OC_STACK_OK;
3509 headResource = NULL;
3510 tailResource = NULL;
3511 // Init Virtual Resources
3512 #ifdef WITH_PRESENCE
3513 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3515 result = OCCreateResource(&presenceResource.handle,
3516 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3518 OC_RSRVD_PRESENCE_URI,
3522 //make resource inactive
3523 result = OCChangeResourceProperty(
3524 &(((OCResource *) presenceResource.handle)->resourceProperties),
3528 if (result == OC_STACK_OK)
3530 result = SRMInitSecureResources();
3536 void insertResource(OCResource *resource)
3540 headResource = resource;
3541 tailResource = resource;
3545 tailResource->next = resource;
3546 tailResource = resource;
3548 resource->next = NULL;
3551 OCResource *findResource(OCResource *resource)
3553 OCResource *pointer = headResource;
3557 if (pointer == resource)
3561 pointer = pointer->next;
3566 void deleteAllResources()
3568 OCResource *pointer = headResource;
3569 OCResource *temp = NULL;
3573 temp = pointer->next;
3574 #ifdef WITH_PRESENCE
3575 if (pointer != (OCResource *) presenceResource.handle)
3577 #endif // WITH_PRESENCE
3578 deleteResource(pointer);
3579 #ifdef WITH_PRESENCE
3581 #endif // WITH_PRESENCE
3585 SRMDeInitSecureResources();
3587 #ifdef WITH_PRESENCE
3588 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3589 // presence notification attributed to their deletion to be processed.
3590 deleteResource((OCResource *) presenceResource.handle);
3591 #endif // WITH_PRESENCE
3594 OCStackResult deleteResource(OCResource *resource)
3596 OCResource *prev = NULL;
3597 OCResource *temp = NULL;
3600 OC_LOG(DEBUG,TAG,"resource is NULL");
3601 return OC_STACK_INVALID_PARAM;
3604 OC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
3606 temp = headResource;
3609 if (temp == resource)
3611 // Invalidate all Resource Properties.
3612 resource->resourceProperties = (OCResourceProperty) 0;
3613 #ifdef WITH_PRESENCE
3614 if(resource != (OCResource *) presenceResource.handle)
3616 #endif // WITH_PRESENCE
3617 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3618 #ifdef WITH_PRESENCE
3621 if(presenceResource.handle)
3623 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3624 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
3627 // Only resource in list.
3628 if (temp == headResource && temp == tailResource)
3630 headResource = NULL;
3631 tailResource = NULL;
3634 else if (temp == headResource)
3636 headResource = temp->next;
3639 else if (temp == tailResource)
3641 tailResource = prev;
3642 tailResource->next = NULL;
3646 prev->next = temp->next;
3649 deleteResourceElements(temp);
3660 return OC_STACK_ERROR;
3663 void deleteResourceElements(OCResource *resource)
3670 OICFree(resource->uri);
3671 deleteResourceType(resource->rsrcType);
3672 deleteResourceInterface(resource->rsrcInterface);
3675 void deleteResourceType(OCResourceType *resourceType)
3677 OCResourceType *pointer = resourceType;
3678 OCResourceType *next = NULL;
3682 next = pointer->next;
3683 OICFree(pointer->resourcetypename);
3689 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3691 OCResourceInterface *pointer = resourceInterface;
3692 OCResourceInterface *next = NULL;
3696 next = pointer->next;
3697 OICFree(pointer->name);
3703 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3705 OCResourceType *pointer = NULL;
3706 OCResourceType *previous = NULL;
3707 if (!resource || !resourceType)
3711 // resource type list is empty.
3712 else if (!resource->rsrcType)
3714 resource->rsrcType = resourceType;
3718 pointer = resource->rsrcType;
3722 if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
3724 OC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
3725 OICFree(resourceType->resourcetypename);
3726 OICFree(resourceType);
3730 pointer = pointer->next;
3732 previous->next = resourceType;
3734 resourceType->next = NULL;
3736 OC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
3739 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3741 OCResource *resource = NULL;
3742 OCResourceType *pointer = NULL;
3744 // Find the specified resource
3745 resource = findResource((OCResource *) handle);
3751 // Make sure a resource has a resourcetype
3752 if (!resource->rsrcType)
3757 // Iterate through the list
3758 pointer = resource->rsrcType;
3759 for(uint8_t i = 0; i< index && pointer; ++i)
3761 pointer = pointer->next;
3766 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3768 if(resourceTypeList && resourceTypeName)
3770 OCResourceType * rtPointer = resourceTypeList;
3771 while(resourceTypeName && rtPointer)
3773 if(rtPointer->resourcetypename &&
3774 strcmp(resourceTypeName, (const char *)
3775 (rtPointer->resourcetypename)) == 0)
3779 rtPointer = rtPointer->next;
3787 * Insert a new interface into interface linked list only if not already present.
3788 * If alredy present, 2nd arg is free'd.
3789 * Default interface will always be first if present.
3791 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
3793 OCResourceInterface *pointer = NULL;
3794 OCResourceInterface *previous = NULL;
3796 newInterface->next = NULL;
3798 OCResourceInterface **firstInterface = &(resource->rsrcInterface);
3800 if (!*firstInterface)
3802 *firstInterface = newInterface;
3804 else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3806 if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3808 OICFree(newInterface->name);
3809 OICFree(newInterface);
3814 newInterface->next = *firstInterface;
3815 *firstInterface = newInterface;
3820 pointer = *firstInterface;
3823 if (strcmp(newInterface->name, pointer->name) == 0)
3825 OICFree(newInterface->name);
3826 OICFree(newInterface);
3830 pointer = pointer->next;
3832 previous->next = newInterface;
3836 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3839 OCResource *resource = NULL;
3840 OCResourceInterface *pointer = NULL;
3842 // Find the specified resource
3843 resource = findResource((OCResource *) handle);
3849 // Make sure a resource has a resourceinterface
3850 if (!resource->rsrcInterface)
3855 // Iterate through the list
3856 pointer = resource->rsrcInterface;
3858 for (uint8_t i = 0; i < index && pointer; ++i)
3860 pointer = pointer->next;
3866 * This function splits the uri using the '?' delimiter.
3867 * "uriWithoutQuery" is the block of characters between the beginning
3868 * till the delimiter or '\0' which ever comes first.
3869 * "query" is whatever is to the right of the delimiter if present.
3870 * No delimiter sets the query to NULL.
3871 * If either are present, they will be malloc'ed into the params 2, 3.
3872 * The first param, *uri is left untouched.
3874 * NOTE: This function does not account for whitespace at the end of the uri NOR
3875 * malformed uri's with '??'. Whitespace at the end will be assumed to be
3876 * part of the query.
3878 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
3882 return OC_STACK_INVALID_URI;
3884 if(!query || !uriWithoutQuery)
3886 return OC_STACK_INVALID_PARAM;
3890 *uriWithoutQuery = NULL;
3892 size_t uriWithoutQueryLen = 0;
3893 size_t queryLen = 0;
3894 size_t uriLen = strlen(uri);
3896 char *pointerToDelimiter = strstr(uri, "?");
3898 uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
3899 queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
3901 if (uriWithoutQueryLen)
3903 *uriWithoutQuery = (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
3904 if (!*uriWithoutQuery)
3908 OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
3912 *query = (char *) OICCalloc(queryLen + 1, 1);
3915 OICFree(*uriWithoutQuery);
3916 *uriWithoutQuery = NULL;
3919 OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
3925 return OC_STACK_NO_MEMORY;
3928 const OicUuid_t* OCGetServerInstanceID(void)
3930 static bool generated = false;
3931 static OicUuid_t sid;
3937 if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
3939 OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
3946 const char* OCGetServerInstanceIDString(void)
3948 static bool generated = false;
3949 static char sidStr[UUID_STRING_SIZE];
3956 const OicUuid_t* sid = OCGetServerInstanceID();
3958 if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
3960 OC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
3968 CAResult_t OCSelectNetwork()
3970 CAResult_t retResult = CA_STATUS_FAILED;
3971 CAResult_t caResult = CA_STATUS_OK;
3973 CATransportAdapter_t connTypes[] = {
3975 CA_ADAPTER_RFCOMM_BTEDR,
3976 CA_ADAPTER_GATT_BTLE
3979 ,CA_ADAPTER_REMOTE_ACCESS
3982 int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
3984 for(int i = 0; i<numConnTypes; i++)
3986 // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
3987 if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
3989 caResult = CASelectNetwork(connTypes[i]);
3990 if(caResult == CA_STATUS_OK)
3992 retResult = CA_STATUS_OK;
3997 if(retResult != CA_STATUS_OK)
3999 return caResult; // Returns error of appropriate transport that failed fatally.
4005 OCStackResult CAResultToOCResult(CAResult_t caResult)
4011 case CA_STATUS_INVALID_PARAM:
4012 return OC_STACK_INVALID_PARAM;
4013 case CA_ADAPTER_NOT_ENABLED:
4014 return OC_STACK_ADAPTER_NOT_ENABLED;
4015 case CA_SERVER_STARTED_ALREADY:
4017 case CA_SERVER_NOT_STARTED:
4018 return OC_STACK_ERROR;
4019 case CA_DESTINATION_NOT_REACHABLE:
4020 return OC_STACK_COMM_ERROR;
4021 case CA_SOCKET_OPERATION_FAILED:
4022 return OC_STACK_COMM_ERROR;
4023 case CA_SEND_FAILED:
4024 return OC_STACK_COMM_ERROR;
4025 case CA_RECEIVE_FAILED:
4026 return OC_STACK_COMM_ERROR;
4027 case CA_MEMORY_ALLOC_FAILED:
4028 return OC_STACK_NO_MEMORY;
4029 case CA_REQUEST_TIMEOUT:
4030 return OC_STACK_TIMEOUT;
4031 case CA_DESTINATION_DISCONNECTED:
4032 return OC_STACK_COMM_ERROR;
4033 case CA_STATUS_FAILED:
4034 return OC_STACK_ERROR;
4035 case CA_NOT_SUPPORTED:
4036 return OC_STACK_NOTIMPL;
4038 return OC_STACK_ERROR;