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
33 #ifndef __STDC_FORMAT_MACROS
34 #define __STDC_FORMAT_MACROS
36 #ifndef __STDC_LIMIT_MACROS
37 #define __STDC_LIMIT_MACROS
39 #include "iotivity_config.h"
45 #include "ocstackinternal.h"
46 #include "ocresourcehandler.h"
47 #include "occlientcb.h"
48 #include "ocobserve.h"
50 #include "oic_malloc.h"
51 #include "oic_string.h"
54 #include "ocserverrequest.h"
55 #include "secureresourcemanager.h"
56 #include "psinterface.h"
58 #include "doxmresource.h"
60 #include "cainterface.h"
61 #include "ocpayload.h"
62 #include "ocpayloadcbor.h"
63 #include "cautilinterface.h"
66 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
67 #include "routingutility.h"
68 #ifdef ROUTING_GATEWAY
69 #include "routingmanager.h"
74 #include "oickeepaliveinternal.h"
77 //#ifdef DIRECT_PAIRING
78 #include "directpairing.h"
81 #ifdef HAVE_ARDUINO_TIME_H
84 #ifdef HAVE_SYS_TIME_H
87 #include <coap/coap.h>
89 #ifdef HAVE_ARPA_INET_H
90 #include <arpa/inet.h>
94 #define UINT32_MAX (0xFFFFFFFFUL)
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
102 OC_STACK_UNINITIALIZED = 0,
103 OC_STACK_INITIALIZED,
104 OC_STACK_UNINIT_IN_PROGRESS
110 OC_PRESENCE_UNINITIALIZED = 0,
111 OC_PRESENCE_INITIALIZED
115 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
118 OCOtmEventHandler cb;
120 } OCOtmEventHandler_t;
123 //-----------------------------------------------------------------------------
125 //-----------------------------------------------------------------------------
126 static OCStackState stackState = OC_STACK_UNINITIALIZED;
128 OCResource *headResource = NULL;
129 static OCResource *tailResource = NULL;
130 static OCResourceHandle platformResource = {0};
131 static OCResourceHandle deviceResource = {0};
133 static OCResourceHandle brokerResource = {0};
137 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
138 static PresenceResource presenceResource = {0};
139 static uint8_t PresenceTimeOutSize = 0;
140 static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
143 static OCMode myStackMode;
145 //TODO: revisit this design
146 static bool gRASetInfo = false;
148 OCDeviceEntityHandler defaultDeviceHandler;
149 void* defaultDeviceHandlerCallbackParameter = NULL;
150 static const char COAP_TCP_SCHEME[] = "coap+tcp:";
151 static const char COAPS_TCP_SCHEME[] = "coaps+tcp:";
152 static const char CORESPEC[] = "core";
154 CAAdapterStateChangedCB g_adapterHandler = NULL;
155 CAConnectionStateChangedCB g_connectionHandler = NULL;
157 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
158 static OCOtmEventHandler_t g_otmEventHandler = {NULL, NULL};
161 //-----------------------------------------------------------------------------
163 //-----------------------------------------------------------------------------
164 #define TAG "OIC_RI_STACK"
165 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
166 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
167 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
168 TAG, #arg " is NULL"); return (retVal); } }
169 #define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
170 TAG, #arg " is NULL"); return; } }
171 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL");\
174 //TODO: we should allow the server to define this
175 #define MAX_OBSERVE_AGE (0x2FFFFUL)
177 #define MILLISECONDS_PER_SECOND (1000)
179 //-----------------------------------------------------------------------------
180 // Private internal function prototypes
181 //-----------------------------------------------------------------------------
184 * Generate handle of OCDoResource invocation for callback management.
186 * @return Generated OCDoResource handle.
188 static OCDoHandle GenerateInvocationHandle();
191 * Initialize resource data structures, variables, etc.
193 * @return ::OC_STACK_OK on success, some other value upon failure.
195 static OCStackResult initResources();
198 * Add a resource to the end of the linked list of resources.
200 * @param resource Resource to be added
202 static void insertResource(OCResource *resource);
205 * Find a resource in the linked list of resources.
207 * @param resource Resource to be found.
208 * @return Pointer to resource that was found in the linked list or NULL if the resource was not
211 static OCResource *findResource(OCResource *resource);
214 * Insert a resource type into a resource's resource type linked list.
215 * If resource type already exists, it will not be inserted and the
216 * resourceType will be free'd.
217 * resourceType->next should be null to avoid memory leaks.
218 * Function returns silently for null args.
220 * @param resource Resource where resource type is to be inserted.
221 * @param resourceType Resource type to be inserted.
223 static void insertResourceType(OCResource *resource,
224 OCResourceType *resourceType);
227 * Get a resource type at the specified index within a resource.
229 * @param handle Handle of resource.
230 * @param index Index of resource type.
232 * @return Pointer to resource type if found, NULL otherwise.
234 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
238 * Insert a resource interface into a resource's resource interface linked list.
239 * If resource interface already exists, it will not be inserted and the
240 * resourceInterface will be free'd.
241 * resourceInterface->next should be null to avoid memory leaks.
243 * @param resource Resource where resource interface is to be inserted.
244 * @param resourceInterface Resource interface to be inserted.
246 static void insertResourceInterface(OCResource *resource,
247 OCResourceInterface *resourceInterface);
250 * Get a resource interface at the specified index within a resource.
252 * @param handle Handle of resource.
253 * @param index Index of resource interface.
255 * @return Pointer to resource interface if found, NULL otherwise.
257 static OCResourceInterface *findResourceInterfaceAtIndex(
258 OCResourceHandle handle, uint8_t index);
261 * Delete all of the dynamically allocated elements that were created for the resource type.
263 * @param resourceType Specified resource type.
265 static void deleteResourceType(OCResourceType *resourceType);
268 * Delete all of the dynamically allocated elements that were created for the resource interface.
270 * @param resourceInterface Specified resource interface.
272 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
275 * Delete all child resources.
277 * @param resourceChild Specified binded resource is deleted from parent.
279 static void deleteResourceChild(OCChildResource *resourceChild);
282 * Delete all of the dynamically allocated elements that were created for the resource.
284 * @param resource Specified resource.
286 static void deleteResourceElements(OCResource *resource);
289 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
292 * @param handle Handle of resource to be deleted.
294 * @return ::OC_STACK_OK on success, some other value upon failure.
296 static OCStackResult deleteResource(OCResource *resource);
299 * Delete all of the resources in the resource list.
301 static void deleteAllResources();
304 * Increment resource sequence number. Handles rollover.
306 * @param resPtr Pointer to resource.
308 static void incrementSequenceNumber(OCResource * resPtr);
311 * Attempts to initialize every network interface that the CA Layer might have compiled in.
313 * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork
314 * return something other than @ref CA_STATUS_OK, then this function fails.
315 * @param transportType OCTransportAdapter value to select.
316 * @return ::CA_STATUS_OK on success, some other value upon failure.
318 static CAResult_t OCSelectNetwork(OCTransportAdapter transportType);
321 * Convert CAResponseResult_t to OCStackResult.
323 * @param caCode CAResponseResult_t code.
324 * @return ::OC_STACK_OK on success, some other value upon failure.
326 static OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode);
329 * Convert OCTransportFlags_t to CATransportModifiers_t.
331 * @param ocConType OCTransportFlags_t input.
332 * @return CATransportFlags
334 static CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocConType);
337 * Convert CATransportFlags_t to OCTransportModifiers_t.
339 * @param caConType CATransportFlags_t input.
340 * @return OCTransportFlags
342 static OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caConType);
345 * Handle response from presence request.
347 * @param endPoint CA remote endpoint.
348 * @param responseInfo CA response info.
349 * @return ::OC_STACK_OK on success, some other value upon failure.
351 static OCStackResult HandlePresenceResponse(const CAEndpoint_t *endPoint,
352 const CAResponseInfo_t *responseInfo);
355 * This function will be called back by CA layer when a response is received.
357 * @param endPoint CA remote endpoint.
358 * @param responseInfo CA response info.
360 static void HandleCAResponses(const CAEndpoint_t* endPoint,
361 const CAResponseInfo_t* responseInfo);
364 * This function will be called back by CA layer when a request is received.
366 * @param endPoint CA remote endpoint.
367 * @param requestInfo CA request info.
369 static void HandleCARequests(const CAEndpoint_t* endPoint,
370 const CARequestInfo_t* requestInfo);
373 * Extract query from a URI.
375 * @param uri Full URI with query.
376 * @param query Pointer to string that will contain query.
377 * @param newURI Pointer to string that will contain URI.
378 * @return ::OC_STACK_OK on success, some other value upon failure.
380 static OCStackResult getQueryFromUri(const char * uri, char** resourceType, char ** newURI);
383 * Finds a resource type in an OCResourceType link-list.
385 * @param resourceTypeList The link-list to be searched through.
386 * @param resourceTypeName The key to search for.
388 * @return Resource type that matches the key (ie. resourceTypeName) or
389 * NULL if there is either an invalid parameter or this function was unable to find the key.
391 static OCResourceType *findResourceType(OCResourceType * resourceTypeList,
392 const char * resourceTypeName);
396 * Reset presence TTL for a ClientCB struct. ttlLevel will be set to 0.
397 * TTL will be set to maxAge.
399 * @param cbNode Callback Node for which presence ttl is to be reset.
400 * @param maxAge New value of ttl in seconds.
402 * @return ::OC_STACK_OK on success, some other value upon failure.
404 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds);
408 * Ensure the accept header option is set appropriatly before sending the requests and routing
409 * header option is updated with destination.
411 * @param object CA remote endpoint.
412 * @param requestInfo CA request info.
414 * @return ::OC_STACK_OK on success, some other value upon failure.
416 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo);
419 * default adapter state change callback method
421 * @param adapter CA network adapter type.
422 * @param enabled current adapter state.
424 static void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled);
427 * default connection state change callback method
429 * @param info CAEndpoint which has address, port and etc.
430 * @param isConnected current connection state.
432 static void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected);
435 * Register network monitoring callback.
436 * Network status changes are delivered these callback.
437 * @param adapterHandler Adapter state monitoring callback.
438 * @param connectionHandler Connection state monitoring callback.
440 static void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler,
441 CAConnectionStateChangedCB connectionHandler);
443 //-----------------------------------------------------------------------------
444 // Internal functions
445 //-----------------------------------------------------------------------------
447 bool checkProxyUri(OCHeaderOption *options, uint8_t numOptions)
449 if (!options || 0 == numOptions)
451 OIC_LOG (INFO, TAG, "No options present");
455 for (uint8_t i = 0; i < numOptions; i++)
457 if (options[i].protocolID == OC_COAP_ID && options[i].optionID == OC_RSRVD_PROXY_OPTION_ID)
459 OIC_LOG(DEBUG, TAG, "Proxy URI is present");
466 uint32_t GetTicks(uint32_t milliSeconds)
471 // Guard against overflow of uint32_t
472 if (milliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) /
473 COAP_TICKS_PER_SECOND)
475 return now + (milliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND;
483 void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out)
485 VERIFY_NON_NULL_NR(in, FATAL);
486 VERIFY_NON_NULL_NR(out, FATAL);
488 out->adapter = (OCTransportAdapter)in->adapter;
489 out->flags = CAToOCTransportFlags(in->flags);
490 OICStrcpy(out->addr, sizeof(out->addr), in->addr);
491 out->port = in->port;
492 out->ifindex = in->ifindex;
493 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
494 /* This assert is to prevent accidental mismatch between address size macros defined in
495 * RI and CA and cause crash here. */
496 OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE,
497 "Address size mismatch between RI and CA");
498 memcpy(out->routeData, in->routeData, sizeof(in->routeData));
502 void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
504 VERIFY_NON_NULL_NR(in, FATAL);
505 VERIFY_NON_NULL_NR(out, FATAL);
507 out->adapter = (CATransportAdapter_t)in->adapter;
508 out->flags = OCToCATransportFlags(in->flags);
509 OICStrcpy(out->addr, sizeof(out->addr), in->addr);
510 OICStrcpy(out->remoteId, sizeof(out->remoteId), in->remoteId);
511 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
512 /* This assert is to prevent accidental mismatch between address size macros defined in
513 * RI and CA and cause crash here. */
514 OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE,
515 "Address size mismatch between RI and CA");
516 memcpy(out->routeData, in->routeData, sizeof(in->routeData));
518 out->port = in->port;
519 out->ifindex = in->ifindex;
522 void FixUpClientResponse(OCClientResponse *cr)
524 VERIFY_NON_NULL_NR(cr, FATAL);
526 cr->addr = &cr->devAddr;
527 cr->connType = (OCConnectivityType)
528 ((cr->devAddr.adapter << CT_ADAPTER_SHIFT) | (cr->devAddr.flags & CT_MASK_FLAGS));
531 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo)
533 VERIFY_NON_NULL(object, FATAL, OC_STACK_INVALID_PARAM);
534 VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
535 OIC_TRACE_BEGIN(%s:OCSendRequest, TAG);
537 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
538 OCStackResult rmResult = RMAddInfo(object->routeData, requestInfo, true, NULL);
539 if (OC_STACK_OK != rmResult)
541 OIC_LOG(ERROR, TAG, "Add destination option failed");
547 // OC stack prefer CBOR encoded payloads.
548 requestInfo->info.acceptFormat = CA_FORMAT_APPLICATION_CBOR;
549 CAResult_t result = CASendRequest(object, requestInfo);
550 if(CA_STATUS_OK != result)
552 OIC_LOG_V(ERROR, TAG, "CASendRequest failed with CA error %u", result);
554 return CAResultToOCResult(result);
560 //-----------------------------------------------------------------------------
561 // Internal API function
562 //-----------------------------------------------------------------------------
564 // This internal function is called to update the stack with the status of
565 // observers and communication failures
566 OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t status)
568 OCStackResult result = OC_STACK_ERROR;
569 ResourceObserver * observer = NULL;
570 OCEntityHandlerRequest ehRequest = {0};
574 case OC_OBSERVER_NOT_INTERESTED:
575 OIC_LOG(DEBUG, TAG, "observer not interested in our notifications");
576 observer = GetObserverUsingToken(token, tokenLength);
579 result = FormOCEntityHandlerRequest(&ehRequest,
583 (OCResourceHandle)NULL,
584 NULL, PAYLOAD_TYPE_REPRESENTATION,
586 OC_OBSERVE_DEREGISTER,
589 if (result != OC_STACK_OK)
594 if (observer->resource && observer->resource->entityHandler)
596 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
597 observer->resource->entityHandlerCallbackParam);
601 result = DeleteObserverUsingToken(token, tokenLength);
602 if (result == OC_STACK_OK)
604 OIC_LOG(DEBUG, TAG, "Removed observer successfully");
608 result = OC_STACK_OK;
609 OIC_LOG(DEBUG, TAG, "Observer Removal failed");
613 case OC_OBSERVER_STILL_INTERESTED:
614 OIC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount");
615 observer = GetObserverUsingToken(token, tokenLength);
618 observer->forceHighQos = 0;
619 observer->failedCommCount = 0;
620 result = OC_STACK_OK;
624 result = OC_STACK_OBSERVER_NOT_FOUND;
628 case OC_OBSERVER_FAILED_COMM:
629 OIC_LOG(DEBUG, TAG, "observer is unreachable");
630 observer = GetObserverUsingToken (token, tokenLength);
633 if (observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
635 result = FormOCEntityHandlerRequest(&ehRequest,
639 (OCResourceHandle)NULL,
640 NULL, PAYLOAD_TYPE_REPRESENTATION,
642 OC_OBSERVE_DEREGISTER,
645 if (result != OC_STACK_OK)
647 return OC_STACK_ERROR;
650 if (observer->resource && observer->resource->entityHandler)
652 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
653 observer->resource->entityHandlerCallbackParam);
656 result = DeleteObserverUsingToken(token, tokenLength);
657 if (result == OC_STACK_OK)
659 OIC_LOG(DEBUG, TAG, "Removed observer successfully");
663 result = OC_STACK_OK;
664 OIC_LOG(DEBUG, TAG, "Observer Removal failed");
669 observer->failedCommCount++;
670 observer->forceHighQos = 1;
671 OIC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",
672 observer->failedCommCount);
673 result = OC_STACK_CONTINUE;
678 OIC_LOG(ERROR, TAG, "Unknown status");
679 result = OC_STACK_ERROR;
685 OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode)
687 OCStackResult ret = OC_STACK_ERROR;
691 ret = OC_STACK_RESOURCE_CREATED;
694 ret = OC_STACK_RESOURCE_DELETED;
697 ret = OC_STACK_RESOURCE_CHANGED;
704 ret = OC_STACK_INVALID_QUERY;
706 case CA_UNAUTHORIZED_REQ:
707 ret = OC_STACK_UNAUTHORIZED_REQ;
710 ret = OC_STACK_INVALID_OPTION;
713 ret = OC_STACK_NO_RESOURCE;
715 case CA_REQUEST_ENTITY_TOO_LARGE:
716 ret = OC_STACK_TOO_LARGE_REQ;
718 case CA_METHOD_NOT_ALLOWED:
719 ret = OC_STACK_METHOD_NOT_ALLOWED;
721 case CA_NOT_ACCEPTABLE:
722 ret = OC_STACK_NOT_ACCEPTABLE;
724 case CA_FORBIDDEN_REQ:
725 ret = OC_STACK_FORBIDDEN_REQ;
727 case CA_INTERNAL_SERVER_ERROR:
728 ret = OC_STACK_INTERNAL_SERVER_ERROR;
730 case CA_NOT_IMPLEMENTED:
731 ret = OC_STACK_NOT_IMPLEMENTED;
734 ret = OC_STACK_BAD_GATEWAY;
736 case CA_SERVICE_UNAVAILABLE:
737 ret = OC_STACK_SERVICE_UNAVAILABLE;
739 case CA_RETRANSMIT_TIMEOUT:
740 ret = OC_STACK_GATEWAY_TIMEOUT;
742 case CA_PROXY_NOT_SUPPORTED:
743 ret = OC_STACK_PROXY_NOT_SUPPORTED;
751 CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method)
753 CAResponseResult_t ret = CA_INTERNAL_SERVER_ERROR;
762 // This Response Code is like HTTP 204 "No Content" but only used in
763 // response to POST and PUT requests.
767 // This Response Code is like HTTP 200 "OK" but only used in response to
772 // This should not happen but,
773 // give it a value just in case but output an error
775 OIC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].",
779 case OC_STACK_RESOURCE_CREATED:
782 case OC_STACK_RESOURCE_DELETED:
785 case OC_STACK_RESOURCE_CHANGED:
788 case OC_STACK_INVALID_QUERY:
791 case OC_STACK_INVALID_OPTION:
794 case OC_STACK_NO_RESOURCE:
797 case OC_STACK_COMM_ERROR:
798 ret = CA_RETRANSMIT_TIMEOUT;
800 case OC_STACK_METHOD_NOT_ALLOWED:
801 ret = CA_METHOD_NOT_ALLOWED;
803 case OC_STACK_NOT_ACCEPTABLE:
804 ret = CA_NOT_ACCEPTABLE;
806 case OC_STACK_UNAUTHORIZED_REQ:
807 ret = CA_UNAUTHORIZED_REQ;
809 case OC_STACK_FORBIDDEN_REQ:
810 ret = CA_FORBIDDEN_REQ;
812 case OC_STACK_INTERNAL_SERVER_ERROR:
813 ret = CA_INTERNAL_SERVER_ERROR;
815 case OC_STACK_NOT_IMPLEMENTED:
816 ret = CA_NOT_IMPLEMENTED;
818 case OC_STACK_BAD_GATEWAY:
819 ret = CA_BAD_GATEWAY;
821 case OC_STACK_SERVICE_UNAVAILABLE:
822 ret = CA_SERVICE_UNAVAILABLE;
824 case OC_STACK_GATEWAY_TIMEOUT:
825 ret = CA_RETRANSMIT_TIMEOUT;
827 case OC_STACK_PROXY_NOT_SUPPORTED:
828 ret = CA_PROXY_NOT_SUPPORTED;
836 CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocFlags)
838 CATransportFlags_t caFlags = (CATransportFlags_t)ocFlags;
840 // supply default behavior.
841 if ((caFlags & (CA_IPV6|CA_IPV4)) == 0)
843 caFlags = (CATransportFlags_t)(caFlags|CA_IPV6|CA_IPV4);
845 if ((caFlags & OC_MASK_SCOPE) == 0)
847 caFlags = (CATransportFlags_t)(caFlags|OC_SCOPE_LINK);
852 OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caFlags)
854 return (OCTransportFlags)caFlags;
858 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds)
860 uint32_t lowerBound = 0;
861 uint32_t higherBound = 0;
863 if (!cbNode || !cbNode->presence || !cbNode->presence->timeOut)
865 return OC_STACK_INVALID_PARAM;
868 OIC_LOG_V(INFO, TAG, "Update presence TTL, time is %u", GetTicks(0));
870 cbNode->presence->TTL = maxAgeSeconds;
872 for (int index = 0; index < PresenceTimeOutSize; index++)
874 // Guard against overflow
875 if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index]))
878 lowerBound = GetTicks((PresenceTimeOut[index] *
879 cbNode->presence->TTL *
880 MILLISECONDS_PER_SECOND)/100);
884 lowerBound = GetTicks(UINT32_MAX);
887 if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index+1]))
890 higherBound = GetTicks((PresenceTimeOut[index + 1] *
891 cbNode->presence->TTL *
892 MILLISECONDS_PER_SECOND)/100);
896 higherBound = GetTicks(UINT32_MAX);
899 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
901 OIC_LOG_V(DEBUG, TAG, "lowerBound timeout %d", lowerBound);
902 OIC_LOG_V(DEBUG, TAG, "higherBound timeout %d", higherBound);
903 OIC_LOG_V(DEBUG, TAG, "timeOut entry %d", cbNode->presence->timeOut[index]);
906 cbNode->presence->TTLlevel = 0;
908 OIC_LOG_V(DEBUG, TAG, "this TTL level %d", cbNode->presence->TTLlevel);
912 const char *convertTriggerEnumToString(OCPresenceTrigger trigger)
914 if (trigger == OC_PRESENCE_TRIGGER_CREATE)
916 return OC_RSRVD_TRIGGER_CREATE;
918 else if (trigger == OC_PRESENCE_TRIGGER_CHANGE)
920 return OC_RSRVD_TRIGGER_CHANGE;
924 return OC_RSRVD_TRIGGER_DELETE;
928 OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr)
932 return OC_PRESENCE_TRIGGER_CREATE;
934 else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CREATE) == 0)
936 return OC_PRESENCE_TRIGGER_CREATE;
938 else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CHANGE) == 0)
940 return OC_PRESENCE_TRIGGER_CHANGE;
944 return OC_PRESENCE_TRIGGER_DELETE;
947 #endif // WITH_PRESENCE
949 OCStackResult OCEncodeAddressForRFC6874(char *outputAddress,
951 const char *inputAddress)
953 VERIFY_NON_NULL(inputAddress, FATAL, OC_STACK_INVALID_PARAM);
954 VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM);
956 size_t inputLength = strnlen(inputAddress, outputSize);
958 // inputSize includes the null terminator
959 size_t inputSize = inputLength + 1;
961 if (inputSize > outputSize)
963 OIC_LOG_V(ERROR, TAG,
964 "OCEncodeAddressForRFC6874 failed: "
965 "outputSize (%zu) < inputSize (%zu)",
966 outputSize, inputSize);
968 return OC_STACK_ERROR;
971 char* percentChar = strchr(inputAddress, '%');
973 // If there is no '%' character, then no change is required to the string.
974 if (NULL == percentChar)
976 OICStrcpy(outputAddress, outputSize, inputAddress);
980 const char* addressPart = &inputAddress[0];
981 const char* scopeIdPart = percentChar + 1;
983 // Sanity check to make sure this string doesn't have more '%' characters
984 if (NULL != strchr(scopeIdPart, '%'))
986 return OC_STACK_ERROR;
989 // If no string follows the first '%', then the input was invalid.
990 if (scopeIdPart[0] == '\0')
992 OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Invalid input string: no scope ID!");
993 return OC_STACK_ERROR;
996 // Check to see if the string is already encoded
997 if ((scopeIdPart[0] == '2') && (scopeIdPart[1] == '5'))
999 OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Input string is already encoded");
1000 return OC_STACK_ERROR;
1003 // Fail if we don't have room for encoded string's two additional chars
1004 if (outputSize < (inputSize + 2))
1006 OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: encoded output will not fit!");
1007 return OC_STACK_ERROR;
1010 // Restore the null terminator with an escaped '%' character, per RFC 6874
1011 OICStrcpy(outputAddress, scopeIdPart - addressPart, addressPart);
1012 OICStrcat(outputAddress, outputSize, "%25");
1013 OICStrcat(outputAddress, outputSize, scopeIdPart);
1018 OCStackResult OCDecodeAddressForRFC6874(char *outputAddress,
1020 const char *inputAddress,
1023 VERIFY_NON_NULL(inputAddress, FATAL, OC_STACK_INVALID_PARAM);
1024 VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM);
1028 end = inputAddress + strlen(inputAddress);
1030 size_t inputLength = end - inputAddress;
1032 const char *percent = strchr(inputAddress, '%');
1033 if (!percent || (percent > end))
1035 OICStrcpyPartial(outputAddress, outputSize, inputAddress, inputLength);
1039 if (percent[1] != '2' || percent[2] != '5')
1041 return OC_STACK_INVALID_URI;
1044 int addrlen = percent - inputAddress + 1;
1045 OICStrcpyPartial(outputAddress, outputSize, inputAddress, addrlen);
1046 OICStrcpyPartial(outputAddress + addrlen, outputSize - addrlen,
1047 percent + 3, end - percent - 3);
1053 #ifdef WITH_PRESENCE
1055 * The cononical presence allows constructed URIs to be string compared.
1057 * requestUri must be a char array of size CA_MAX_URI_LENGTH
1059 static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint,
1060 char *presenceUri, bool isMulticast)
1062 VERIFY_NON_NULL(endpoint , FATAL, OC_STACK_INVALID_PARAM);
1063 VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM);
1067 OIC_LOG(DEBUG, TAG, "Make Multicast Presence URI");
1068 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "%s", OC_RSRVD_PRESENCE_URI);
1071 CAEndpoint_t *ep = (CAEndpoint_t *)endpoint;
1072 if (ep->adapter == CA_ADAPTER_IP)
1074 if ((ep->flags & CA_IPV6) && !(ep->flags & CA_IPV4))
1076 if ('\0' == ep->addr[0]) // multicast
1078 return snprintf(presenceUri, CA_MAX_URI_LENGTH, OC_RSRVD_PRESENCE_URI);
1082 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1084 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1085 sizeof(addressEncoded),
1088 if (OC_STACK_OK != result)
1093 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://[%s]:%u%s",
1094 addressEncoded, ep->port, OC_RSRVD_PRESENCE_URI);
1099 if ('\0' == ep->addr[0]) // multicast
1101 OICStrcpy(ep->addr, sizeof(ep->addr), OC_MULTICAST_IP);
1102 ep->port = OC_MULTICAST_PORT;
1104 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s:%u%s",
1105 ep->addr, ep->port, OC_RSRVD_PRESENCE_URI);
1109 // might work for other adapters (untested, but better than nothing)
1110 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s%s", ep->addr,
1111 OC_RSRVD_PRESENCE_URI);
1115 OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
1116 const CAResponseInfo_t *responseInfo)
1118 VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
1119 VERIFY_NON_NULL(responseInfo, FATAL, OC_STACK_INVALID_PARAM);
1121 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1122 ClientCB * cbNode = NULL;
1123 char *resourceTypeName = NULL;
1124 OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
1125 OCStackResult result = OC_STACK_ERROR;
1126 uint32_t maxAge = 0;
1128 char presenceUri[CA_MAX_URI_LENGTH];
1130 int presenceSubscribe = 0;
1131 int multicastPresenceSubscribe = 0;
1133 if (responseInfo->result != CA_CONTENT)
1135 OIC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
1136 return OC_STACK_ERROR;
1139 response.payload = NULL;
1140 response.result = OC_STACK_OK;
1142 CopyEndpointToDevAddr(endpoint, &response.devAddr);
1143 FixUpClientResponse(&response);
1145 if (responseInfo->info.payload)
1147 result = OCParsePayload(&response.payload,
1148 PAYLOAD_TYPE_PRESENCE,
1149 responseInfo->info.payload,
1150 responseInfo->info.payloadSize);
1152 if(result != OC_STACK_OK)
1154 OIC_LOG(ERROR, TAG, "Presence parse failed");
1157 if(!response.payload || response.payload->type != PAYLOAD_TYPE_PRESENCE)
1159 OIC_LOG(ERROR, TAG, "Presence payload was wrong type");
1160 result = OC_STACK_ERROR;
1163 response.sequenceNumber = ((OCPresencePayload*)response.payload)->sequenceNumber;
1164 resourceTypeName = ((OCPresencePayload*)response.payload)->resourceType;
1165 maxAge = ((OCPresencePayload*)response.payload)->maxAge;
1168 // check for unicast presence
1169 uriLen = FormCanonicalPresenceUri(endpoint, presenceUri,
1170 responseInfo->isMulticast);
1171 if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri))
1173 return OC_STACK_INVALID_URI;
1175 OIC_LOG(INFO, TAG, "check for unicast presence");
1176 cbNode = GetClientCB(NULL, 0, NULL, presenceUri);
1179 presenceSubscribe = 1;
1183 // check for multicast presence
1184 OIC_LOG(INFO, TAG, "check for multicast presence");
1185 cbNode = GetClientCB(NULL, 0, NULL, OC_RSRVD_PRESENCE_URI);
1188 multicastPresenceSubscribe = 1;
1192 if (!presenceSubscribe && !multicastPresenceSubscribe)
1194 OIC_LOG(INFO, TAG, "Received a presence notification, "
1195 "but need to register presence callback, ignoring");
1199 if (presenceSubscribe)
1201 if(cbNode->sequenceNumber == response.sequenceNumber)
1203 OIC_LOG(INFO, TAG, "No presence change");
1204 ResetPresenceTTL(cbNode, maxAge);
1205 OIC_LOG_V(INFO, TAG, "ResetPresenceTTL - TTLlevel:%d\n", cbNode->presence->TTLlevel);
1211 OIC_LOG(INFO, TAG, "Stopping presence");
1212 response.result = OC_STACK_PRESENCE_STOPPED;
1213 if(cbNode->presence)
1215 OICFree(cbNode->presence->timeOut);
1216 OICFree(cbNode->presence);
1217 cbNode->presence = NULL;
1222 if(!cbNode->presence)
1224 cbNode->presence = (OCPresence *)OICMalloc(sizeof (OCPresence));
1226 if(!(cbNode->presence))
1228 OIC_LOG(ERROR, TAG, "Could not allocate memory for cbNode->presence");
1229 result = OC_STACK_NO_MEMORY;
1233 VERIFY_NON_NULL_V(cbNode->presence);
1234 cbNode->presence->timeOut = NULL;
1235 cbNode->presence->timeOut = (uint32_t *)
1236 OICMalloc(PresenceTimeOutSize * sizeof(uint32_t));
1237 if(!(cbNode->presence->timeOut)){
1239 "Could not allocate memory for cbNode->presence->timeOut");
1240 OICFree(cbNode->presence);
1241 result = OC_STACK_NO_MEMORY;
1246 ResetPresenceTTL(cbNode, maxAge);
1248 cbNode->sequenceNumber = response.sequenceNumber;
1253 // This is the multicast case
1254 OIC_LOG(INFO, TAG, "this is the multicast presence");
1257 OIC_LOG(INFO, TAG, "Stopping presence");
1258 response.result = OC_STACK_PRESENCE_STOPPED;
1262 // Ensure that a filter is actually applied.
1263 if (resourceTypeName && cbNode->filterResourceType)
1265 OIC_LOG_V(INFO, TAG, "find resource type : %s", resourceTypeName);
1266 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1272 OIC_LOG(INFO, TAG, "Callback for presence");
1274 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
1276 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1278 FindAndDeleteClientCB(cbNode);
1282 OCPayloadDestroy(response.payload);
1285 #endif // WITH_PRESENCE
1287 OCStackResult HandleBatchResponse(char *requestUri, OCRepPayload **payload)
1289 if (requestUri && *payload)
1291 char *interfaceName = NULL;
1292 char *rtTypeName = NULL;
1293 char *uriQuery = NULL;
1294 char *uriWithoutQuery = NULL;
1295 if (OC_STACK_OK == getQueryFromUri(requestUri, &uriQuery, &uriWithoutQuery))
1297 if (OC_STACK_OK == ExtractFiltersFromQuery(uriQuery, &interfaceName, &rtTypeName))
1299 if (interfaceName && (0 == strcmp(OC_RSRVD_INTERFACE_BATCH, interfaceName)))
1301 char *uri = (*payload)->uri;
1302 if (uri && 0 != strcmp(uriWithoutQuery, uri))
1304 OCRepPayload *newPayload = OCRepPayloadCreate();
1307 OCRepPayloadSetUri(newPayload, uri);
1308 newPayload->next = *payload;
1309 *payload = newPayload;
1316 OICFree(interfaceName);
1317 OICFree(rtTypeName);
1319 OICFree(uriWithoutQuery);
1322 return OC_STACK_INVALID_PARAM;
1325 void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
1327 OIC_TRACE_MARK(%s:OCHandleResponse:%s, TAG, responseInfo->info.resourceUri);
1328 OIC_LOG(DEBUG, TAG, "Enter OCHandleResponse");
1330 #ifdef WITH_PRESENCE
1331 if(responseInfo->info.resourceUri &&
1332 strcmp(responseInfo->info.resourceUri, OC_RSRVD_PRESENCE_URI) == 0)
1334 HandlePresenceResponse(endPoint, responseInfo);
1339 ClientCB *cbNode = GetClientCB(responseInfo->info.token,
1340 responseInfo->info.tokenLength, NULL, NULL);
1342 ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token,
1343 responseInfo->info.tokenLength);
1347 OIC_LOG(INFO, TAG, "There is a cbNode associated with the response token");
1349 // check obs header option
1350 bool obsHeaderOpt = false;
1351 CAHeaderOption_t *options = responseInfo->info.options;
1352 for (uint8_t i = 0; i< responseInfo->info.numOptions; i++)
1354 if (options && options[i].protocolID == CA_COAP_ID &&
1355 options[i].optionID == COAP_OPTION_OBSERVE)
1357 obsHeaderOpt = true;
1362 if(responseInfo->result == CA_EMPTY)
1364 OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1365 // We do not have a case for the client to receive a RESET
1366 if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1368 //This is the case of receiving an ACK on a request to a slow resource!
1369 OIC_LOG(INFO, TAG, "This is a pure ACK");
1370 //TODO: should we inform the client
1371 // app that at least the request was received at the server?
1374 else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1376 OIC_LOG(INFO, TAG, "Receiving A Timeout for this token");
1377 OIC_LOG(INFO, TAG, "Calling into application address space");
1379 OCClientResponse response =
1380 {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
1381 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1382 FixUpClientResponse(&response);
1383 response.resourceUri = OICStrdup(responseInfo->info.resourceUri);
1384 memcpy(response.identity.id, responseInfo->info.identity.id,
1385 sizeof (response.identity.id));
1386 response.identity.id_length = responseInfo->info.identity.id_length;
1388 response.result = CAResponseToOCStackResult(responseInfo->result);
1389 cbNode->callBack(cbNode->context,
1390 cbNode->handle, &response);
1391 FindAndDeleteClientCB(cbNode);
1392 OICFree(response.resourceUri);
1395 else if ((cbNode->method == OC_REST_OBSERVE || cbNode->method == OC_REST_OBSERVE_ALL)
1396 && (responseInfo->result == CA_CONTENT) && !obsHeaderOpt)
1398 OCClientResponse response =
1399 {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
1400 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1401 FixUpClientResponse(&response);
1402 response.resourceUri = OICStrdup(responseInfo->info.resourceUri);
1403 memcpy(response.identity.id, responseInfo->info.identity.id,
1404 sizeof (response.identity.id));
1405 response.identity.id_length = responseInfo->info.identity.id_length;
1406 response.result = OC_STACK_UNAUTHORIZED_REQ;
1408 cbNode->callBack(cbNode->context,
1411 FindAndDeleteClientCB(cbNode);
1412 OICFree(response.resourceUri);
1417 OIC_LOG(INFO, TAG, "This is a regular response, A client call back is found");
1418 OIC_LOG(INFO, TAG, "Calling into application address space");
1420 OCClientResponse response;
1421 memset(&response, 0, sizeof(OCClientResponse));
1422 response.devAddr.adapter = OC_DEFAULT_ADAPTER;
1424 response.sequenceNumber = MAX_SEQUENCE_NUMBER + 1;
1425 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1426 FixUpClientResponse(&response);
1427 response.resourceUri = OICStrdup(responseInfo->info.resourceUri);
1428 memcpy(response.identity.id, responseInfo->info.identity.id,
1429 sizeof (response.identity.id));
1430 response.identity.id_length = responseInfo->info.identity.id_length;
1432 response.result = CAResponseToOCStackResult(responseInfo->result);
1434 if(responseInfo->info.payload &&
1435 responseInfo->info.payloadSize)
1437 OCPayloadType type = PAYLOAD_TYPE_INVALID;
1438 // check the security resource
1439 if (SRMIsSecurityResourceURI(cbNode->requestUri))
1441 type = PAYLOAD_TYPE_SECURITY;
1443 else if (cbNode->method == OC_REST_DISCOVER)
1445 if (strncmp(OC_RSRVD_WELL_KNOWN_URI,cbNode->requestUri,
1446 sizeof(OC_RSRVD_WELL_KNOWN_URI) - 1) == 0)
1448 type = PAYLOAD_TYPE_DISCOVERY;
1451 else if (strcmp(cbNode->requestUri, OC_RSRVD_WELL_KNOWN_MQ_URI) == 0)
1453 type = PAYLOAD_TYPE_DISCOVERY;
1456 else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
1458 type = PAYLOAD_TYPE_REPRESENTATION;
1460 else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
1462 type = PAYLOAD_TYPE_REPRESENTATION;
1465 #ifdef ROUTING_GATEWAY
1466 else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0)
1468 type = PAYLOAD_TYPE_REPRESENTATION;
1471 else if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0)
1473 type = PAYLOAD_TYPE_REPRESENTATION;
1476 else if (strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0)
1478 type = PAYLOAD_TYPE_REPRESENTATION;
1483 OIC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
1484 cbNode->method, cbNode->requestUri);
1485 OICFree(response.resourceUri);
1489 else if (cbNode->method == OC_REST_GET ||
1490 cbNode->method == OC_REST_PUT ||
1491 cbNode->method == OC_REST_POST ||
1492 cbNode->method == OC_REST_OBSERVE ||
1493 cbNode->method == OC_REST_OBSERVE_ALL ||
1494 cbNode->method == OC_REST_DELETE)
1496 if (cbNode->requestUri)
1498 if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri))
1500 type = PAYLOAD_TYPE_REPRESENTATION;
1502 else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri))
1504 type = PAYLOAD_TYPE_REPRESENTATION;
1506 if (type == PAYLOAD_TYPE_INVALID)
1508 OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
1509 cbNode->method, cbNode->requestUri);
1510 type = PAYLOAD_TYPE_REPRESENTATION;
1515 OIC_LOG(INFO, TAG, "No Request URI, PROXY URI");
1516 type = PAYLOAD_TYPE_REPRESENTATION;
1521 OIC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
1522 cbNode->method, cbNode->requestUri);
1523 OICFree(response.resourceUri);
1527 // In case of error, still want application to receive the error message.
1528 if (OCResultToSuccess(response.result) || PAYLOAD_TYPE_REPRESENTATION == type)
1530 if(OC_STACK_OK != OCParsePayload(&response.payload,
1532 responseInfo->info.payload,
1533 responseInfo->info.payloadSize))
1535 OIC_LOG(ERROR, TAG, "Error converting payload");
1536 OCPayloadDestroy(response.payload);
1537 OICFree(response.resourceUri);
1543 response.resourceUri = OICStrdup(cbNode->requestUri);
1547 response.numRcvdVendorSpecificHeaderOptions = 0;
1548 if(responseInfo->info.numOptions > 0)
1551 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
1552 if(responseInfo->info.options
1553 && responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
1556 uint32_t observationOption;
1557 uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
1558 for (observationOption=0, i=0;
1559 i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
1563 (observationOption << 8) | optionData[i];
1565 response.sequenceNumber = observationOption;
1566 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
1571 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
1574 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
1576 OIC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
1577 OCPayloadDestroy(response.payload);
1578 OICFree(response.resourceUri);
1582 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
1584 if(&(responseInfo->info.options[i]))
1586 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
1587 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
1592 if (cbNode->method == OC_REST_OBSERVE &&
1593 response.sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
1594 cbNode->sequenceNumber <= MAX_SEQUENCE_NUMBER &&
1595 response.sequenceNumber <= cbNode->sequenceNumber)
1597 OIC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
1598 response.sequenceNumber);
1603 if (cbNode->requestUri)
1605 // if request uri is '/oic/rd', update ins value of resource.
1606 char *targetUri = strstr(cbNode->requestUri, OC_RSRVD_RD_URI);
1609 OCUpdateResourceInsWithResponse(cbNode->requestUri, &response);
1613 // set remoteID(device ID) into OCClientResponse callback parameter
1614 if (OC_REST_DISCOVER == cbNode->method)
1616 OIC_LOG(INFO, TAG, "cbNode method is OC_REST_DISCOVER");
1617 OCDiscoveryPayload *payload = (OCDiscoveryPayload*) response.payload;
1618 // Payload can be empty in case of error message.
1619 if (payload && payload->sid)
1621 OICStrcpy(response.devAddr.remoteId, sizeof(response.devAddr.remoteId),
1623 OIC_LOG_V(INFO_PRIVATE, TAG, "Device ID of response : %s",
1624 response.devAddr.remoteId);
1627 if(NULL == response.resourceUri)
1629 response.resourceUri = OICStrdup(cbNode->requestUri);
1633 if (cbNode->requestUri)
1635 OIC_LOG_V(INFO, TAG, "cbNode requestUri is %s", cbNode->requestUri);
1636 if (cbNode->method == OC_REST_POST &&
1637 strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0)
1639 OCHandleKeepAliveResponse(endPoint, response.payload);
1643 if (response.payload && response.payload->type == PAYLOAD_TYPE_REPRESENTATION)
1645 OIC_LOG(INFO, TAG, "Handle batch response");
1646 HandleBatchResponse(cbNode->requestUri, (OCRepPayload **)&response.payload);
1649 OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
1652 cbNode->sequenceNumber = response.sequenceNumber;
1654 if (appFeedback == OC_STACK_DELETE_TRANSACTION)
1656 FindAndDeleteClientCB(cbNode);
1660 // To keep discovery callbacks active.
1661 cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
1662 MILLISECONDS_PER_SECOND);
1666 //Need to send ACK when the response is CON
1667 if(responseInfo->info.type == CA_MSG_CONFIRM)
1669 if (!(endPoint->adapter & CA_ADAPTER_TCP))
1671 OIC_LOG(INFO, TAG, "Received a confirmable message. Sending EMPTY");
1672 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1673 CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1677 OICFree(response.resourceUri);
1678 OCPayloadDestroy(response.payload);
1685 OIC_LOG(INFO, TAG, "There is an observer associated with the response token");
1686 if(responseInfo->result == CA_EMPTY)
1688 OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1689 if(responseInfo->info.type == CA_MSG_RESET)
1691 OIC_LOG(INFO, TAG, "This is a RESET");
1692 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1693 OC_OBSERVER_NOT_INTERESTED);
1695 else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1697 OIC_LOG(INFO, TAG, "This is a pure ACK");
1698 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1699 OC_OBSERVER_STILL_INTERESTED);
1702 else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1704 OIC_LOG(INFO, TAG, "Receiving Time Out for an observer");
1705 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1706 OC_OBSERVER_FAILED_COMM);
1711 if(!cbNode && !observer)
1713 if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER
1714 || myStackMode == OC_GATEWAY)
1716 OIC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
1717 if(responseInfo->result == CA_EMPTY)
1719 OIC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
1723 if (!(endPoint->adapter & CA_ADAPTER_TCP))
1725 OIC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
1726 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1727 CA_MSG_RESET, 0, NULL, NULL, 0, NULL,
1728 CA_RESPONSE_FOR_RES);
1733 if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER
1734 || myStackMode == OC_GATEWAY)
1736 OIC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
1737 if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1739 OIC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
1740 responseInfo->info.messageId);
1742 if (responseInfo->info.type == CA_MSG_RESET)
1744 OIC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
1745 responseInfo->info.messageId);
1753 void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
1755 VERIFY_NON_NULL_NR(endPoint, FATAL);
1756 VERIFY_NON_NULL_NR(responseInfo, FATAL);
1758 OIC_LOG(INFO, TAG, "Enter HandleCAResponses");
1759 OIC_TRACE_BEGIN(%s:HandleCAResponses, TAG);
1761 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
1762 #ifdef ROUTING_GATEWAY
1763 bool needRIHandling = false;
1765 * Routing manager is going to update either of endpoint or response or both.
1766 * This typecasting is done to avoid unnecessary duplication of Endpoint and responseInfo
1767 * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
1770 OCStackResult ret = RMHandleResponse((CAResponseInfo_t *)responseInfo, (CAEndpoint_t *)endPoint,
1772 if(ret != OC_STACK_OK || !needRIHandling)
1774 OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
1781 * Put source in sender endpoint so that the next packet from application can be routed to
1782 * proper destination and remove "RM" coap header option before passing request / response to
1783 * RI as this option will make no sense to either RI or application.
1785 RMUpdateInfo((CAHeaderOption_t **) &(responseInfo->info.options),
1786 (uint8_t *) &(responseInfo->info.numOptions),
1787 (CAEndpoint_t *) endPoint);
1790 OCHandleResponse(endPoint, responseInfo);
1792 OIC_LOG(INFO, TAG, "Exit HandleCAResponses");
1796 * This function handles error response from CA
1797 * code shall be added to handle the errors
1799 void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
1801 VERIFY_NON_NULL_NR(endPoint, FATAL);
1802 VERIFY_NON_NULL_NR(errorInfo, FATAL);
1804 OIC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
1805 OIC_TRACE_BEGIN(%s:HandleCAErrorResponse, TAG);
1807 ClientCB *cbNode = GetClientCB(errorInfo->info.token,
1808 errorInfo->info.tokenLength, NULL, NULL);
1811 OCClientResponse response = { .devAddr = { .adapter = OC_DEFAULT_ADAPTER } };
1812 CopyEndpointToDevAddr(endPoint, &response.devAddr);
1813 FixUpClientResponse(&response);
1814 response.resourceUri = errorInfo->info.resourceUri;
1815 memcpy(response.identity.id, errorInfo->info.identity.id,
1816 sizeof (response.identity.id));
1817 response.identity.id_length = errorInfo->info.identity.id_length;
1818 response.result = CAResultToOCResult(errorInfo->result);
1820 cbNode->callBack(cbNode->context, cbNode->handle, &response);
1823 ResourceObserver *observer = GetObserverUsingToken(errorInfo->info.token,
1824 errorInfo->info.tokenLength);
1827 OIC_LOG(INFO, TAG, "Receiving communication error for an observer");
1828 OCStackResult result = CAResultToOCResult(errorInfo->result);
1829 if (OC_STACK_COMM_ERROR == result)
1831 OCStackFeedBack(errorInfo->info.token, errorInfo->info.tokenLength,
1832 OC_OBSERVER_FAILED_COMM);
1836 OIC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
1841 * This function sends out Direct Stack Responses. These are responses that are not coming
1842 * from the application entity handler. These responses have no payload and are usually ACKs,
1843 * RESETs or some error conditions that were caught by the stack.
1845 OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
1846 const CAResponseResult_t responseResult, const CAMessageType_t type,
1847 const uint8_t numOptions, const CAHeaderOption_t *options,
1848 CAToken_t token, uint8_t tokenLength, const char *resourceUri,
1849 CADataType_t dataType)
1851 OIC_LOG(DEBUG, TAG, "Entering SendDirectStackResponse");
1853 if (endPoint->flags & CA_MULTICAST)
1855 OIC_LOG(ERROR, TAG, "It is unnecessary to respond to a multicast request");
1859 CAResponseInfo_t respInfo = { .result = responseResult };
1860 respInfo.info.messageId = coapID;
1861 respInfo.info.numOptions = numOptions;
1863 if (respInfo.info.numOptions)
1865 respInfo.info.options =
1866 (CAHeaderOption_t *)OICCalloc(respInfo.info.numOptions, sizeof(CAHeaderOption_t));
1867 memcpy (respInfo.info.options, options,
1868 sizeof(CAHeaderOption_t) * respInfo.info.numOptions);
1872 respInfo.info.payload = NULL;
1873 respInfo.info.token = token;
1874 respInfo.info.tokenLength = tokenLength;
1875 respInfo.info.type = type;
1876 respInfo.info.resourceUri = OICStrdup (resourceUri);
1877 respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED;
1878 respInfo.info.dataType = dataType;
1880 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
1881 // Add the destination to route option from the endpoint->routeData.
1882 bool doPost = false;
1883 OCStackResult result = RMAddInfo(endPoint->routeData, &respInfo, false, &doPost);
1884 if(OC_STACK_OK != result)
1886 OIC_LOG_V(ERROR, TAG, "Add routing option failed [%d]", result);
1887 OICFree (respInfo.info.resourceUri);
1888 OICFree (respInfo.info.options);
1893 OIC_LOG(DEBUG, TAG, "Sending a POST message for EMPTY ACK in Client Mode");
1894 CARequestInfo_t reqInfo = {.method = CA_POST };
1895 /* The following initialization is not done in a single initializer block as in
1896 * arduino, .c file is compiled as .cpp and moves it from C99 to C++11. The latter
1897 * does not have designated initalizers. This is a work-around for now.
1899 reqInfo.info.type = CA_MSG_NONCONFIRM;
1900 reqInfo.info.messageId = coapID;
1901 reqInfo.info.tokenLength = tokenLength;
1902 reqInfo.info.token = token;
1903 reqInfo.info.numOptions = respInfo.info.numOptions;
1904 reqInfo.info.payload = NULL;
1905 reqInfo.info.resourceUri = OICStrdup (OC_RSRVD_GATEWAY_URI);
1906 if (reqInfo.info.numOptions)
1908 reqInfo.info.options =
1909 (CAHeaderOption_t *)OICCalloc(reqInfo.info.numOptions, sizeof(CAHeaderOption_t));
1910 if (NULL == reqInfo.info.options)
1912 OIC_LOG(ERROR, TAG, "Calloc failed");
1913 OICFree (reqInfo.info.resourceUri);
1914 OICFree (respInfo.info.resourceUri);
1915 OICFree (respInfo.info.options);
1916 return OC_STACK_NO_MEMORY;
1918 memcpy (reqInfo.info.options, respInfo.info.options,
1919 sizeof(CAHeaderOption_t) * reqInfo.info.numOptions);
1922 CAResult_t caResult = CASendRequest(endPoint, &reqInfo);
1923 OICFree (reqInfo.info.resourceUri);
1924 OICFree (reqInfo.info.options);
1925 OICFree (respInfo.info.resourceUri);
1926 OICFree (respInfo.info.options);
1927 if (CA_STATUS_OK != caResult)
1929 OIC_LOG(ERROR, TAG, "CASendRequest error");
1930 return CAResultToOCResult(caResult);
1936 CAResult_t caResult = CASendResponse(endPoint, &respInfo);
1938 // resourceUri in the info field is cloned in the CA layer and
1939 // thus ownership is still here.
1940 OICFree (respInfo.info.resourceUri);
1941 OICFree (respInfo.info.options);
1942 if(CA_STATUS_OK != caResult)
1944 OIC_LOG(ERROR, TAG, "CASendResponse error");
1945 return CAResultToOCResult(caResult);
1948 OIC_LOG(DEBUG, TAG, "Exit SendDirectStackResponse");
1952 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
1954 OIC_LOG(INFO, TAG, "Entering HandleStackRequests (OCStack Layer)");
1955 OCStackResult result = OC_STACK_ERROR;
1956 if(!protocolRequest)
1958 OIC_LOG(ERROR, TAG, "protocolRequest is NULL");
1959 return OC_STACK_INVALID_PARAM;
1962 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken,
1963 protocolRequest->tokenLength);
1966 OIC_LOG(INFO, TAG, "This is a new Server Request");
1967 result = AddServerRequest(&request, protocolRequest->coapID,
1968 protocolRequest->delayedResNeeded, 0, protocolRequest->method,
1969 protocolRequest->numRcvdVendorSpecificHeaderOptions,
1970 protocolRequest->observationOption, protocolRequest->qos,
1971 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
1972 protocolRequest->payload, protocolRequest->requestToken,
1973 protocolRequest->tokenLength, protocolRequest->resourceUrl,
1974 protocolRequest->reqTotalSize, protocolRequest->acceptFormat,
1975 &protocolRequest->devAddr);
1976 if (OC_STACK_OK != result)
1978 OIC_LOG(ERROR, TAG, "Error adding server request");
1984 OIC_LOG(ERROR, TAG, "Out of Memory");
1985 return OC_STACK_NO_MEMORY;
1988 if(!protocolRequest->reqMorePacket)
1990 request->requestComplete = 1;
1995 OIC_LOG(INFO, TAG, "This is either a repeated or blocked Server Request");
1998 if(request->requestComplete)
2000 OIC_LOG(INFO, TAG, "This Server Request is complete");
2001 ResourceHandling resHandling = OC_RESOURCE_VIRTUAL;
2002 OCResource *resource = NULL;
2003 result = DetermineResourceHandling (request, &resHandling, &resource);
2004 if (result == OC_STACK_OK)
2006 result = ProcessRequest(resHandling, resource, request);
2011 OIC_LOG(INFO, TAG, "This Server Request is incomplete");
2012 result = OC_STACK_CONTINUE;
2017 void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
2019 OIC_TRACE_MARK(%s:OCHandleRequests:%s, TAG, requestInfo->info.resourceUri);
2020 OIC_LOG(DEBUG, TAG, "Enter OCHandleRequests");
2022 OCStackResult requestResult = OC_STACK_ERROR;
2024 if(myStackMode == OC_CLIENT)
2026 //TODO: should the client be responding to requests?
2030 OCServerProtocolRequest serverRequest = {0};
2032 OIC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
2034 char * uriWithoutQuery = NULL;
2035 char * query = NULL;
2037 requestResult = getQueryFromUri(requestInfo->info.resourceUri, &query, &uriWithoutQuery);
2039 if (requestResult != OC_STACK_OK || !uriWithoutQuery)
2041 OIC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
2044 OIC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
2045 OIC_LOG_V(INFO, TAG, "Query : %s", query);
2047 if(strlen(uriWithoutQuery) < MAX_URI_LENGTH)
2049 OICStrcpy(serverRequest.resourceUrl, sizeof(serverRequest.resourceUrl), uriWithoutQuery);
2050 OICFree(uriWithoutQuery);
2054 OIC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
2055 OICFree(uriWithoutQuery);
2062 if(strlen(query) < MAX_QUERY_LENGTH)
2064 OICStrcpy(serverRequest.query, sizeof(serverRequest.query), query);
2069 OIC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
2075 if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
2077 serverRequest.reqTotalSize = requestInfo->info.payloadSize;
2078 serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
2079 if (!serverRequest.payload)
2081 OIC_LOG(ERROR, TAG, "Allocation for payload failed.");
2084 memcpy (serverRequest.payload, requestInfo->info.payload,
2085 requestInfo->info.payloadSize);
2089 serverRequest.reqTotalSize = 0;
2092 switch (requestInfo->method)
2095 serverRequest.method = OC_REST_GET;
2098 serverRequest.method = OC_REST_PUT;
2101 serverRequest.method = OC_REST_POST;
2104 serverRequest.method = OC_REST_DELETE;
2107 OIC_LOG_V(ERROR, TAG, "Received CA method %d not supported", requestInfo->method);
2108 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
2109 requestInfo->info.type, requestInfo->info.numOptions,
2110 requestInfo->info.options, requestInfo->info.token,
2111 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2113 OICFree(serverRequest.payload);
2117 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token,
2118 requestInfo->info.tokenLength);
2120 serverRequest.tokenLength = requestInfo->info.tokenLength;
2121 if (serverRequest.tokenLength) {
2123 serverRequest.requestToken = (CAToken_t)OICMalloc(requestInfo->info.tokenLength);
2125 if (!serverRequest.requestToken)
2127 OIC_LOG(FATAL, TAG, "Allocation for token failed.");
2128 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
2129 requestInfo->info.type, requestInfo->info.numOptions,
2130 requestInfo->info.options, requestInfo->info.token,
2131 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2133 OICFree(serverRequest.payload);
2136 memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
2139 switch (requestInfo->info.acceptFormat)
2141 case CA_FORMAT_APPLICATION_CBOR:
2142 serverRequest.acceptFormat = OC_FORMAT_CBOR;
2144 case CA_FORMAT_UNDEFINED:
2145 serverRequest.acceptFormat = OC_FORMAT_UNDEFINED;
2148 serverRequest.acceptFormat = OC_FORMAT_UNSUPPORTED;
2151 if (requestInfo->info.type == CA_MSG_CONFIRM)
2153 serverRequest.qos = OC_HIGH_QOS;
2157 serverRequest.qos = OC_LOW_QOS;
2159 // CA does not need the following field
2160 // Are we sure CA does not need them? how is it responding to multicast
2161 serverRequest.delayedResNeeded = 0;
2163 serverRequest.coapID = requestInfo->info.messageId;
2165 CopyEndpointToDevAddr(endPoint, &serverRequest.devAddr);
2167 // copy vendor specific header options
2168 uint8_t tempNum = (requestInfo->info.numOptions);
2170 // Assume no observation requested and it is a pure GET.
2171 // If obs registration/de-registration requested it'll be fetched from the
2172 // options in GetObserveHeaderOption()
2173 serverRequest.observationOption = OC_OBSERVE_NO_OPTION;
2175 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
2176 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
2179 "The request info numOptions is greater than MAX_HEADER_OPTIONS");
2180 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
2181 requestInfo->info.type, requestInfo->info.numOptions,
2182 requestInfo->info.options, requestInfo->info.token,
2183 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2185 OICFree(serverRequest.payload);
2186 OICFree(serverRequest.requestToken);
2189 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
2190 if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options)
2192 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
2193 sizeof(CAHeaderOption_t)*tempNum);
2196 requestResult = HandleStackRequests (&serverRequest);
2198 // Send ACK to client as precursor to slow response
2199 if (requestResult == OC_STACK_SLOW_RESOURCE)
2201 if (requestInfo->info.type == CA_MSG_CONFIRM)
2203 SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
2204 CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL,
2209 if (requestResult == OC_STACK_RESOURCE_ERROR
2210 && serverRequest.observationOption == OC_OBSERVE_REGISTER)
2212 OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error");
2215 if (serverRequest.observationOption == OC_OBSERVE_REGISTER)
2217 if (requestResult == OC_STACK_RESOURCE_ERROR)
2219 OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error");
2221 else if (!OCResultToSuccess(requestResult))
2223 DeleteObserverUsingToken(requestInfo->info.token, requestInfo->info.tokenLength);
2227 else if(!OCResultToSuccess(requestResult))
2229 OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
2231 CAResponseResult_t stackResponse =
2232 OCToCAStackResult(requestResult, serverRequest.method);
2234 SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
2235 requestInfo->info.type, requestInfo->info.numOptions,
2236 requestInfo->info.options, requestInfo->info.token,
2237 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2240 // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
2241 // The token is copied in there, and is thus still owned by this function.
2242 OICFree(serverRequest.payload);
2243 OICFree(serverRequest.requestToken);
2244 OIC_LOG(INFO, TAG, "Exit OCHandleRequests");
2247 //This function will be called back by CA layer when a request is received
2248 void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
2250 OIC_LOG(INFO, TAG, "Enter HandleCARequests");
2251 OIC_TRACE_BEGIN(%s:HandleCARequests, TAG);
2254 OIC_LOG(ERROR, TAG, "endPoint is NULL");
2261 OIC_LOG(ERROR, TAG, "requestInfo is NULL");
2266 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2267 #ifdef ROUTING_GATEWAY
2268 bool needRIHandling = false;
2269 bool isEmptyMsg = false;
2271 * Routing manager is going to update either of endpoint or request or both.
2272 * This typecasting is done to avoid unnecessary duplication of Endpoint and requestInfo
2273 * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
2274 * destination. It can also remove "RM" coap header option before passing request / response to
2275 * RI as this option will make no sense to either RI or application.
2277 OCStackResult ret = RMHandleRequest((CARequestInfo_t *)requestInfo, (CAEndpoint_t *)endPoint,
2278 &needRIHandling, &isEmptyMsg);
2279 if(OC_STACK_OK != ret || !needRIHandling)
2281 OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
2288 * Put source in sender endpoint so that the next packet from application can be routed to
2289 * proper destination and remove RM header option.
2291 RMUpdateInfo((CAHeaderOption_t **) &(requestInfo->info.options),
2292 (uint8_t *) &(requestInfo->info.numOptions),
2293 (CAEndpoint_t *) endPoint);
2295 #ifdef ROUTING_GATEWAY
2299 * In Gateways, the MSGType in route option is used to check if the actual
2300 * response is EMPTY message(4 bytes CoAP Header). In case of Client, the
2301 * EMPTY response is sent in the form of POST request which need to be changed
2302 * to a EMPTY response by RM. This translation is done in this part of the code.
2304 OIC_LOG(INFO, TAG, "This is a Empty response from the Client");
2305 CAResponseInfo_t respInfo = {.result = CA_EMPTY,
2306 .info.messageId = requestInfo->info.messageId,
2307 .info.type = CA_MSG_ACKNOWLEDGE};
2308 OCHandleResponse(endPoint, &respInfo);
2314 // Normal handling of the packet
2315 OCHandleRequests(endPoint, requestInfo);
2317 OIC_LOG(INFO, TAG, "Exit HandleCARequests");
2321 //-----------------------------------------------------------------------------
2323 //-----------------------------------------------------------------------------
2325 OCStackResult OCSetRAInfo(const OCRAInfo_t *raInfo)
2328 !raInfo->username ||
2329 !raInfo->hostname ||
2330 !raInfo->xmpp_domain)
2333 return OC_STACK_INVALID_PARAM;
2335 OCStackResult result = CAResultToOCResult(CASetRAInfo((const CARAInfo_t *) raInfo));
2336 gRASetInfo = (result == OC_STACK_OK)? true : false;
2342 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
2346 return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
2349 OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags)
2351 OIC_LOG(DEBUG, TAG, "call OCInit1");
2352 return OCInit2(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS, OC_DEFAULT_ADAPTER);
2355 OCStackResult OCInit2(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags,
2356 OCTransportAdapter transportType)
2358 if(stackState == OC_STACK_INITIALIZED)
2360 OIC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
2361 OCStop() between them are ignored.");
2365 #ifndef ROUTING_GATEWAY
2366 if (OC_GATEWAY == mode)
2368 OIC_LOG(ERROR, TAG, "Routing Manager not supported");
2369 return OC_STACK_INVALID_PARAM;
2376 OIC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
2377 return OC_STACK_ERROR;
2381 OCStackResult result = OC_STACK_ERROR;
2382 OIC_LOG(INFO, TAG, "Entering OCInit");
2385 if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)
2386 || (mode == OC_GATEWAY)))
2388 OIC_LOG(ERROR, TAG, "Invalid mode");
2389 return OC_STACK_ERROR;
2393 if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2395 caglobals.client = true;
2397 if (mode == OC_SERVER || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2399 caglobals.server = true;
2402 caglobals.serverFlags = (CATransportFlags_t)serverFlags;
2403 if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
2405 caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
2407 caglobals.clientFlags = (CATransportFlags_t)clientFlags;
2408 if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
2410 caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
2413 defaultDeviceHandler = NULL;
2414 defaultDeviceHandlerCallbackParameter = NULL;
2416 result = InitializeScheduleResourceList();
2417 VERIFY_SUCCESS(result, OC_STACK_OK);
2419 result = CAResultToOCResult(CAInitialize((CATransportAdapter_t)transportType));
2420 VERIFY_SUCCESS(result, OC_STACK_OK);
2422 result = CAResultToOCResult(OCSelectNetwork(transportType));
2423 VERIFY_SUCCESS(result, OC_STACK_OK);
2425 result = CAResultToOCResult(CARegisterNetworkMonitorHandler(
2426 OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler));
2427 VERIFY_SUCCESS(result, OC_STACK_OK);
2429 switch (myStackMode)
2432 CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2433 result = CAResultToOCResult(CAStartDiscoveryServer());
2434 OIC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
2437 SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2438 result = CAResultToOCResult(CAStartListeningServer());
2439 OIC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
2441 case OC_CLIENT_SERVER:
2443 SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2444 result = CAResultToOCResult(CAStartListeningServer());
2445 if(result == OC_STACK_OK)
2447 result = CAResultToOCResult(CAStartDiscoveryServer());
2451 VERIFY_SUCCESS(result, OC_STACK_OK);
2454 CARegisterKeepAliveHandler(OCHandleKeepAliveConnCB);
2457 #ifdef WITH_PRESENCE
2458 PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
2459 #endif // WITH_PRESENCE
2461 //Update Stack state to initialized
2462 stackState = OC_STACK_INITIALIZED;
2464 // Initialize resource
2465 if(myStackMode != OC_CLIENT)
2467 result = initResources();
2470 // Initialize the SRM Policy Engine
2471 if(result == OC_STACK_OK)
2473 result = SRMInitPolicyEngine();
2474 // TODO after BeachHead delivery: consolidate into single SRMInit()
2476 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2477 RMSetStackMode(mode);
2478 #ifdef ROUTING_GATEWAY
2479 if (OC_GATEWAY == myStackMode)
2481 result = RMInitialize();
2487 if (result == OC_STACK_OK)
2489 result = OCInitializeKeepAlive(myStackMode);
2494 if(result != OC_STACK_OK)
2496 OIC_LOG(ERROR, TAG, "Stack initialization error");
2497 TerminateScheduleResourceList();
2498 deleteAllResources();
2500 stackState = OC_STACK_UNINITIALIZED;
2505 OCStackResult OCStop()
2507 OIC_LOG(INFO, TAG, "Entering OCStop");
2509 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
2511 OIC_LOG(DEBUG, TAG, "Stack already stopping, exiting");
2514 else if (stackState != OC_STACK_INITIALIZED)
2516 OIC_LOG(INFO, TAG, "Stack not initialized");
2517 return OC_STACK_ERROR;
2520 // unset cautil config
2521 CAUtilConfig_t configs = {(CATransportBTFlags_t)CA_DEFAULT_BT_FLAGS};
2522 CAUtilSetBTConfigure(configs);
2524 stackState = OC_STACK_UNINIT_IN_PROGRESS;
2526 CAUnregisterNetworkMonitorHandler(OCDefaultAdapterStateChangedHandler,
2527 OCDefaultConnectionStateChangedHandler);
2529 #ifdef WITH_PRESENCE
2530 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
2531 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
2532 presenceResource.presenceTTL = 0;
2533 presenceState = OC_PRESENCE_UNINITIALIZED;
2534 #endif // WITH_PRESENCE
2536 #ifdef ROUTING_GATEWAY
2537 if (OC_GATEWAY == myStackMode)
2544 OCTerminateKeepAlive(myStackMode);
2547 TerminateScheduleResourceList();
2548 // Remove all observers
2549 DeleteObserverList();
2550 // Free memory dynamically allocated for resources
2551 deleteAllResources();
2552 // Remove all the client callbacks
2553 DeleteClientCBList();
2554 // Terminate connectivity-abstraction layer.
2557 // De-init the SRM Policy Engine
2558 // TODO after BeachHead delivery: consolidate into single SRMDeInit()
2559 SRMDeInitPolicyEngine();
2561 stackState = OC_STACK_UNINITIALIZED;
2565 OCStackResult OCStartMulticastServer()
2567 if(stackState != OC_STACK_INITIALIZED)
2569 OIC_LOG(ERROR, TAG, "OCStack is not initalized. Cannot start multicast server.");
2570 return OC_STACK_ERROR;
2572 CAResult_t ret = CAStartListeningServer();
2573 if (CA_STATUS_OK != ret)
2575 OIC_LOG_V(ERROR, TAG, "Failed starting listening server: %d", ret);
2576 return OC_STACK_ERROR;
2581 OCStackResult OCStopMulticastServer()
2583 CAResult_t ret = CAStopListeningServer();
2584 if (CA_STATUS_OK != ret)
2586 OIC_LOG_V(ERROR, TAG, "Failed stopping listening server: %d", ret);
2587 return OC_STACK_ERROR;
2592 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
2597 return CA_MSG_CONFIRM;
2602 return CA_MSG_NONCONFIRM;
2606 OCStackResult ParseRequestUri(const char *fullUri,
2607 OCTransportAdapter adapter,
2608 OCTransportFlags flags,
2609 OCDevAddr **devAddr,
2611 char **resourceType)
2613 VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
2615 OCStackResult result = OC_STACK_OK;
2616 OCDevAddr *da = NULL;
2620 // provide defaults for all returned values
2627 *resourceUri = NULL;
2631 *resourceType = NULL;
2634 // delimit url prefix, if any
2635 const char *start = fullUri;
2636 char *slash2 = strstr(start, "//");
2641 char *slash = strchr(start, '/');
2644 return OC_STACK_INVALID_URI;
2647 // process url scheme
2648 size_t prefixLen = slash2 - fullUri;
2652 if (((prefixLen == sizeof(COAP_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAP_TCP_SCHEME, prefixLen)))
2653 || ((prefixLen == sizeof(COAPS_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAPS_TCP_SCHEME, prefixLen))))
2659 // TODO: this logic should come in with unit tests exercising the various strings
2660 // processs url prefix, if any
2661 size_t urlLen = slash - start;
2665 if (urlLen && devAddr)
2666 { // construct OCDevAddr
2667 if (start[0] == '[')
2669 char *close = strchr(++start, ']');
2670 if (!close || close > slash)
2672 return OC_STACK_INVALID_URI;
2675 if (close[1] == ':')
2682 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2686 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2688 flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
2692 char *dot = strchr(start, '.');
2693 if (dot && dot < slash)
2695 colon = strchr(start, ':');
2696 end = (colon && colon < slash) ? colon : slash;
2701 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2705 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2707 flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
2715 if (len >= sizeof(da->addr))
2717 return OC_STACK_INVALID_URI;
2719 // collect port, if any
2720 if (colon && colon < slash)
2722 for (colon++; colon < slash; colon++)
2725 if (c < '0' || c > '9')
2727 return OC_STACK_INVALID_URI;
2729 port = 10 * port + c - '0';
2734 if (len >= sizeof(da->addr))
2736 return OC_STACK_INVALID_URI;
2739 da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
2742 return OC_STACK_NO_MEMORY;
2745 // Decode address per RFC 6874.
2746 result = OCDecodeAddressForRFC6874(da->addr, sizeof(da->addr), start, end);
2747 if (result != OC_STACK_OK)
2754 da->adapter = adapter;
2756 if (!strncmp(fullUri, "coaps", 5))
2758 da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
2763 // process resource uri, if any
2765 { // request uri and query
2766 size_t ulen = strlen(slash); // resource uri length
2767 size_t tlen = 0; // resource type length
2770 static const char strPresence[] = "/oic/ad?rt=";
2771 static const size_t lenPresence = sizeof(strPresence) - 1;
2772 if (!strncmp(slash, strPresence, lenPresence))
2774 type = slash + lenPresence;
2775 tlen = ulen - lenPresence;
2780 *resourceUri = (char *)OICMalloc(ulen + 1);
2783 result = OC_STACK_NO_MEMORY;
2786 OICStrcpy(*resourceUri, (ulen + 1), slash);
2789 if (type && resourceType)
2791 *resourceType = (char *)OICMalloc(tlen + 1);
2794 result = OC_STACK_NO_MEMORY;
2798 OICStrcpy(*resourceType, (tlen+1), type);
2805 // free all returned values
2812 OICFree(*resourceUri);
2816 OICFree(*resourceType);
2821 #ifdef WITH_PRESENCE
2822 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
2826 char uri[CA_MAX_URI_LENGTH];
2828 FormCanonicalPresenceUri(endpoint, uri, isMulticast);
2830 *requestUri = OICStrdup(uri);
2833 return OC_STACK_NO_MEMORY;
2838 #endif // WITH_PRESENCE
2841 * Discover or Perform requests on a specified resource
2843 OCStackResult OCDoResource(OCDoHandle *handle,
2845 const char *requestUri,
2846 const OCDevAddr *destination,
2848 OCConnectivityType connectivityType,
2849 OCQualityOfService qos,
2850 OCCallbackData *cbData,
2851 OCHeaderOption *options,
2854 OCStackResult ret = OCDoRequest(handle, method, requestUri,destination, payload,
2855 connectivityType, qos, cbData, options, numOptions);
2857 // This is the owner of the payload object, so we free it
2858 OCPayloadDestroy(payload);
2863 * Discover or Perform requests on a specified resource
2865 OCStackResult OCDoRequest(OCDoHandle *handle,
2867 const char *requestUri,
2868 const OCDevAddr *destination,
2870 OCConnectivityType connectivityType,
2871 OCQualityOfService qos,
2872 OCCallbackData *cbData,
2873 OCHeaderOption *options,
2876 OIC_LOG(INFO, TAG, "Entering OCDoResource");
2877 OIC_TRACE_BEGIN(%s:OCDoRequest, TAG);
2879 // Validate input parameters
2880 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
2881 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
2883 OCStackResult result = OC_STACK_ERROR;
2884 CAResult_t caResult;
2885 CAToken_t token = NULL;
2886 uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2887 ClientCB *clientCB = NULL;
2888 OCDoHandle resHandle = NULL;
2889 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2890 OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
2892 OCTransportAdapter adapter;
2893 OCTransportFlags flags;
2894 // the request contents are put here
2895 CARequestInfo_t requestInfo = {.method = CA_GET};
2896 // requestUri will be parsed into the following three variables
2897 OCDevAddr *devAddr = NULL;
2898 char *resourceUri = NULL;
2899 char *resourceType = NULL;
2902 * Support original behavior with address on resourceUri argument.
2904 adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2905 flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2909 result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2910 if (result != OC_STACK_OK)
2912 OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2916 else if (!checkProxyUri(options, numOptions))
2918 OIC_LOG(ERROR, TAG, "Request doesn't contain RequestURI/Proxy URI");
2925 case OC_REST_OBSERVE:
2926 case OC_REST_OBSERVE_ALL:
2927 requestInfo.method = CA_GET;
2930 requestInfo.method = CA_PUT;
2933 requestInfo.method = CA_POST;
2935 case OC_REST_DELETE:
2936 requestInfo.method = CA_DELETE;
2938 case OC_REST_DISCOVER:
2939 #ifdef WITH_PRESENCE
2940 case OC_REST_PRESENCE:
2942 if (destination || devAddr)
2944 requestInfo.isMulticast = false;
2948 tmpDevAddr.adapter = adapter;
2949 tmpDevAddr.flags = flags;
2950 destination = &tmpDevAddr;
2951 requestInfo.isMulticast = true;
2954 // OC_REST_DISCOVER: CA_DISCOVER will become GET and isMulticast.
2955 // OC_REST_PRESENCE: Since "presence" is a stack layer only implementation.
2956 // replacing method type with GET.
2957 requestInfo.method = CA_GET;
2960 result = OC_STACK_INVALID_METHOD;
2964 if (!devAddr && !destination)
2966 OIC_LOG(DEBUG, TAG, "no devAddr and no destination");
2967 result = OC_STACK_INVALID_PARAM;
2971 /* If not original behavior, use destination argument */
2972 if (destination && !devAddr)
2974 devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2977 result = OC_STACK_NO_MEMORY;
2980 OIC_LOG(DEBUG, TAG, "devAddr is set as destination");
2981 *devAddr = *destination;
2986 OIC_LOG_V(INFO_PRIVATE, TAG, "remoteId of devAddr : %s", devAddr->remoteId);
2987 if (!requestInfo.isMulticast)
2989 OIC_LOG_V(DEBUG, TAG, "remoteAddr of devAddr : [%s]:[%d]",
2990 devAddr->addr, devAddr->port);
2994 resHandle = GenerateInvocationHandle();
2997 result = OC_STACK_NO_MEMORY;
3001 caResult = CAGenerateToken(&token, tokenLength);
3002 if (caResult != CA_STATUS_OK)
3004 OIC_LOG(ERROR, TAG, "CAGenerateToken error");
3005 result= OC_STACK_ERROR;
3009 // fill in request data
3010 requestInfo.info.type = qualityOfServiceToMessageType(qos);
3011 requestInfo.info.token = token;
3012 requestInfo.info.tokenLength = tokenLength;
3014 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
3016 result = CreateObserveHeaderOption (&(requestInfo.info.options),
3017 options, numOptions, OC_OBSERVE_REGISTER);
3018 if (result != OC_STACK_OK)
3022 requestInfo.info.numOptions = numOptions + 1;
3026 requestInfo.info.numOptions = numOptions;
3027 requestInfo.info.options =
3028 (CAHeaderOption_t*) OICCalloc(numOptions, sizeof(CAHeaderOption_t));
3029 memcpy(requestInfo.info.options, (CAHeaderOption_t*)options,
3030 numOptions * sizeof(CAHeaderOption_t));
3033 CopyDevAddrToEndpoint(devAddr, &endpoint);
3038 OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
3041 OIC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
3044 requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
3048 requestInfo.info.payload = NULL;
3049 requestInfo.info.payloadSize = 0;
3050 requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
3053 // prepare for response
3054 #ifdef WITH_PRESENCE
3055 if (method == OC_REST_PRESENCE)
3057 char *presenceUri = NULL;
3058 result = OCPreparePresence(&endpoint, &presenceUri,
3059 requestInfo.isMulticast);
3060 if (OC_STACK_OK != result)
3065 // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
3066 // Presence notification will form a canonical uri to
3067 // look for callbacks into the application.
3070 OICFree(resourceUri);
3072 resourceUri = presenceUri;
3076 // update resourceUri onto requestInfo after check presence uri
3077 requestInfo.info.resourceUri = resourceUri;
3079 ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
3080 result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
3081 method, devAddr, resourceUri, resourceType, ttl);
3082 if (OC_STACK_OK != result)
3087 devAddr = NULL; // Client CB list entry now owns it
3088 resourceUri = NULL; // Client CB list entry now owns it
3089 resourceType = NULL; // Client CB list entry now owns it
3091 #ifdef WITH_PRESENCE
3092 if (method == OC_REST_PRESENCE)
3094 OIC_LOG(ERROR, TAG, "AddClientCB for presence done.");
3098 *handle = resHandle;
3106 result = OCSendRequest(&endpoint, &requestInfo);
3107 if (OC_STACK_OK != result)
3114 *handle = resHandle;
3118 if (result != OC_STACK_OK)
3120 OIC_LOG(ERROR, TAG, "OCDoResource error");
3121 FindAndDeleteClientCB(clientCB);
3122 CADestroyToken(token);
3130 OICFree(requestInfo.info.payload);
3132 OICFree(resourceUri);
3133 OICFree(resourceType);
3134 OICFree(requestInfo.info.options);
3139 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
3143 * This ftn is implemented one of two ways in the case of observation:
3145 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
3146 * Remove the callback associated on client side.
3147 * When the next notification comes in from server,
3148 * reply with RESET message to server.
3149 * Keep in mind that the server will react to RESET only
3150 * if the last notification was sent as CON
3152 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
3153 * and it is associated with an observe request
3154 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
3155 * Send CON Observe request to server with
3156 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
3157 * Remove the callback associated on client side.
3159 OCStackResult ret = OC_STACK_OK;
3160 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
3161 CARequestInfo_t requestInfo = {.method = CA_GET};
3165 return OC_STACK_INVALID_PARAM;
3168 ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
3171 OIC_LOG(ERROR, TAG, "Callback not found. Called OCCancel on same resource twice?");
3172 return OC_STACK_ERROR;
3175 switch (clientCB->method)
3177 case OC_REST_OBSERVE:
3178 case OC_REST_OBSERVE_ALL:
3180 OIC_LOG_V(INFO, TAG, "Canceling observation for resource %s", clientCB->requestUri);
3182 CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
3184 if ((endpoint.adapter & CA_ADAPTER_IP) && qos != OC_HIGH_QOS)
3186 FindAndDeleteClientCB(clientCB);
3190 OIC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
3192 requestInfo.info.type = qualityOfServiceToMessageType(qos);
3193 requestInfo.info.token = clientCB->token;
3194 requestInfo.info.tokenLength = clientCB->tokenLength;
3196 if (CreateObserveHeaderOption (&(requestInfo.info.options),
3197 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
3199 return OC_STACK_ERROR;
3201 requestInfo.info.numOptions = numOptions + 1;
3202 requestInfo.info.resourceUri = OICStrdup (clientCB->requestUri);
3205 ret = OCSendRequest(&endpoint, &requestInfo);
3207 if (requestInfo.info.options)
3209 OICFree (requestInfo.info.options);
3211 if (requestInfo.info.resourceUri)
3213 OICFree (requestInfo.info.resourceUri);
3218 case OC_REST_DISCOVER:
3219 OIC_LOG_V(INFO, TAG, "Cancelling discovery callback for resource %s",
3220 clientCB->requestUri);
3221 FindAndDeleteClientCB(clientCB);
3224 #ifdef WITH_PRESENCE
3225 case OC_REST_PRESENCE:
3226 FindAndDeleteClientCB(clientCB);
3232 case OC_REST_DELETE:
3233 OIC_LOG_V(INFO, TAG, "Cancelling request callback for resource %s",
3234 clientCB->requestUri);
3235 FindAndDeleteClientCB(clientCB);
3239 ret = OC_STACK_INVALID_METHOD;
3247 * @brief Register Persistent storage callback.
3248 * @param persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
3250 * OC_STACK_OK - No errors; Success
3251 * OC_STACK_INVALID_PARAM - Invalid parameter
3253 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
3255 OIC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
3256 if(!persistentStorageHandler)
3258 OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
3259 return OC_STACK_INVALID_PARAM;
3263 if( !persistentStorageHandler->open ||
3264 !persistentStorageHandler->close ||
3265 !persistentStorageHandler->read ||
3266 !persistentStorageHandler->unlink ||
3267 !persistentStorageHandler->write)
3269 OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
3270 return OC_STACK_INVALID_PARAM;
3273 return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
3276 #ifdef WITH_PRESENCE
3278 OCStackResult OCProcessPresence()
3280 OCStackResult result = OC_STACK_OK;
3282 // the following line floods the log with messages that are irrelevant
3283 // to most purposes. Uncomment as needed.
3284 //OIC_LOG(INFO, TAG, "Entering RequestPresence");
3285 ClientCB* cbNode = NULL;
3286 OCClientResponse clientResponse;
3287 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
3289 LL_FOREACH(cbList, cbNode)
3291 if (OC_REST_PRESENCE != cbNode->method || !cbNode->presence)
3296 uint32_t now = GetTicks(0);
3297 OIC_LOG_V(DEBUG, TAG, "this TTL level %d",
3298 cbNode->presence->TTLlevel);
3299 OIC_LOG_V(DEBUG, TAG, "current ticks %d", now);
3301 if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
3306 if (cbNode->presence->TTLlevel < PresenceTimeOutSize)
3308 OIC_LOG_V(DEBUG, TAG, "timeout ticks %d",
3309 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
3311 if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
3313 OIC_LOG(DEBUG, TAG, "No more timeout ticks");
3315 clientResponse.sequenceNumber = 0;
3316 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
3317 clientResponse.devAddr = *cbNode->devAddr;
3318 FixUpClientResponse(&clientResponse);
3319 clientResponse.payload = NULL;
3321 // Increment the TTLLevel (going to a next state), so we don't keep
3322 // sending presence notification to client.
3323 cbNode->presence->TTLlevel++;
3324 OIC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
3325 cbNode->presence->TTLlevel);
3327 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
3328 if (cbResult == OC_STACK_DELETE_TRANSACTION)
3330 FindAndDeleteClientCB(cbNode);
3334 if (now < cbNode->presence->timeOut[cbNode->presence->TTLlevel])
3339 CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
3340 CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
3341 CARequestInfo_t requestInfo = {.method = CA_GET};
3343 OIC_LOG(DEBUG, TAG, "time to test server presence");
3345 CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
3347 requestData.type = CA_MSG_NONCONFIRM;
3348 requestData.token = cbNode->token;
3349 requestData.tokenLength = cbNode->tokenLength;
3350 requestData.resourceUri = OC_RSRVD_PRESENCE_URI;
3351 requestInfo.method = CA_GET;
3352 requestInfo.info = requestData;
3354 result = OCSendRequest(&endpoint, &requestInfo);
3355 if (OC_STACK_OK != result)
3360 cbNode->presence->TTLlevel++;
3361 OIC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel);
3364 if (result != OC_STACK_OK)
3366 OIC_LOG(ERROR, TAG, "OCProcessPresence error");
3371 #endif // WITH_PRESENCE
3373 OCStackResult OCProcess()
3375 if (stackState == OC_STACK_UNINITIALIZED)
3377 OIC_LOG(ERROR, TAG, "OCProcess has failed. ocstack is not initialized");
3378 return OC_STACK_ERROR;
3380 #ifdef WITH_PRESENCE
3381 OCProcessPresence();
3383 CAHandleRequestResponse();
3385 #ifdef ROUTING_GATEWAY
3390 OCProcessKeepAlive();
3395 #ifdef WITH_PRESENCE
3396 OCStackResult OCStartPresence(const uint32_t ttl)
3398 OIC_LOG(INFO, TAG, "Entering OCStartPresence");
3399 uint8_t tokenLength = CA_MAX_TOKEN_LEN;
3400 OCChangeResourceProperty(
3401 &(((OCResource *)presenceResource.handle)->resourceProperties),
3404 if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
3406 presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
3407 OIC_LOG(INFO, TAG, "Setting Presence TTL to max value");
3411 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3412 OIC_LOG(INFO, TAG, "Setting Presence TTL to default value");
3416 presenceResource.presenceTTL = ttl;
3419 OIC_LOG_V(DEBUG, TAG, "Presence TTL is %" PRIu32 " seconds", presenceResource.presenceTTL);
3422 if (OC_PRESENCE_UNINITIALIZED == presenceState)
3424 presenceState = OC_PRESENCE_INITIALIZED;
3426 OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
3428 CAToken_t caToken = NULL;
3429 CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
3430 if (caResult != CA_STATUS_OK)
3432 OIC_LOG(ERROR, TAG, "CAGenerateToken error");
3433 CADestroyToken(caToken);
3434 return OC_STACK_ERROR;
3437 AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
3438 (OCResource *)presenceResource.handle, OC_LOW_QOS, OC_FORMAT_UNDEFINED, &devAddr);
3439 CADestroyToken(caToken);
3442 // Each time OCStartPresence is called
3443 // a different random 32-bit integer number is used
3444 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3446 return SendPresenceNotification(((OCResource *)presenceResource.handle)->rsrcType,
3447 OC_PRESENCE_TRIGGER_CREATE);
3450 OCStackResult OCStopPresence()
3452 OIC_LOG(INFO, TAG, "Entering OCStopPresence");
3453 OCStackResult result = OC_STACK_ERROR;
3455 if(presenceResource.handle)
3457 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3459 // make resource inactive
3460 result = OCChangeResourceProperty(
3461 &(((OCResource *) presenceResource.handle)->resourceProperties),
3465 if(result != OC_STACK_OK)
3468 "Changing the presence resource properties to ACTIVE not successful");
3472 return SendStopNotification();
3476 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler,
3477 void* callbackParameter)
3479 defaultDeviceHandler = entityHandler;
3480 defaultDeviceHandlerCallbackParameter = callbackParameter;
3485 OCStackResult OCCreateResource(OCResourceHandle *handle,
3486 const char *resourceTypeName,
3487 const char *resourceInterfaceName,
3488 const char *uri, OCEntityHandler entityHandler,
3489 void* callbackParam,
3490 uint8_t resourceProperties)
3493 OCResource *pointer = NULL;
3494 OCStackResult result = OC_STACK_ERROR;
3496 OIC_LOG(INFO, TAG, "Entering OCCreateResource");
3498 if(myStackMode == OC_CLIENT)
3500 return OC_STACK_INVALID_PARAM;
3502 // Validate parameters
3503 if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
3505 OIC_LOG(ERROR, TAG, "URI is empty or too long");
3506 return OC_STACK_INVALID_URI;
3508 // Is it presented during resource discovery?
3509 if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
3511 OIC_LOG(ERROR, TAG, "Input parameter is NULL");
3512 return OC_STACK_INVALID_PARAM;
3515 if (!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
3517 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
3521 resourceProperties = resourceProperties | OC_MQ_PUBLISHER;
3523 // Make sure resourceProperties bitmask has allowed properties specified
3524 if (resourceProperties
3525 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
3526 OC_EXPLICIT_DISCOVERABLE
3535 OIC_LOG(ERROR, TAG, "Invalid property");
3536 return OC_STACK_INVALID_PARAM;
3539 // If the headResource is NULL, then no resources have been created...
3540 pointer = headResource;
3543 // At least one resources is in the resource list, so we need to search for
3544 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
3547 if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
3549 OIC_LOG_V(ERROR, TAG, "Resource %s already exists", uri);
3550 return OC_STACK_INVALID_PARAM;
3552 pointer = pointer->next;
3555 // Create the pointer and insert it into the resource list
3556 pointer = (OCResource *) OICCalloc(1, sizeof(OCResource));
3559 result = OC_STACK_NO_MEMORY;
3562 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
3564 insertResource(pointer);
3567 pointer->uri = OICStrdup(uri);
3570 result = OC_STACK_NO_MEMORY;
3574 // Set properties. Set OC_ACTIVE
3575 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
3578 // Add the resourcetype to the resource
3579 result = BindResourceTypeToResource(pointer, resourceTypeName);
3580 if (result != OC_STACK_OK)
3582 OIC_LOG(ERROR, TAG, "Error adding resourcetype");
3586 // Add the resourceinterface to the resource
3587 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
3588 if (result != OC_STACK_OK)
3590 OIC_LOG(ERROR, TAG, "Error adding resourceinterface");
3594 // If an entity handler has been passed, attach it to the newly created
3595 // resource. Otherwise, set the default entity handler.
3598 pointer->entityHandler = entityHandler;
3599 pointer->entityHandlerCallbackParam = callbackParam;
3603 pointer->entityHandler = defaultResourceEHandler;
3604 pointer->entityHandlerCallbackParam = NULL;
3607 // Initialize a pointer indicating child resources in case of collection
3608 pointer->rsrcChildResourcesHead = NULL;
3611 result = OC_STACK_OK;
3613 #ifdef WITH_PRESENCE
3614 if (presenceResource.handle)
3616 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3617 SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
3621 if (result != OC_STACK_OK)
3623 // Deep delete of resource and other dynamic elements that it contains
3624 deleteResource(pointer);
3629 OCStackResult OCBindResource(
3630 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3632 OCResource *resource = NULL;
3633 OCChildResource *tempChildResource = NULL;
3634 OCChildResource *newChildResource = NULL;
3636 OIC_LOG(INFO, TAG, "Entering OCBindResource");
3638 // Validate parameters
3639 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3640 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3641 // Container cannot contain itself
3642 if (collectionHandle == resourceHandle)
3644 OIC_LOG(ERROR, TAG, "Added handle equals collection handle");
3645 return OC_STACK_INVALID_PARAM;
3648 // Use the handle to find the resource in the resource linked list
3649 resource = findResource((OCResource *) collectionHandle);
3652 OIC_LOG(ERROR, TAG, "Collection handle not found");
3653 return OC_STACK_INVALID_PARAM;
3656 // Look for an open slot to add add the child resource.
3657 // If found, add it and return success
3659 tempChildResource = resource->rsrcChildResourcesHead;
3661 while(resource->rsrcChildResourcesHead && tempChildResource->next)
3663 // TODO: what if one of child resource was deregistered without unbinding?
3664 tempChildResource = tempChildResource->next;
3667 // Do memory allocation for child resource
3668 newChildResource = (OCChildResource *) OICCalloc(1, sizeof(OCChildResource));
3669 if(!newChildResource)
3671 OIC_LOG(ERROR, TAG, "Adding new child resource is failed due to memory allocation failure");
3672 return OC_STACK_ERROR;
3675 newChildResource->rsrcResource = (OCResource *) resourceHandle;
3676 newChildResource->next = NULL;
3678 if(!resource->rsrcChildResourcesHead)
3680 resource->rsrcChildResourcesHead = newChildResource;
3683 tempChildResource->next = newChildResource;
3686 OIC_LOG(INFO, TAG, "resource bound");
3688 #ifdef WITH_PRESENCE
3689 if (presenceResource.handle)
3691 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3692 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3693 OC_PRESENCE_TRIGGER_CHANGE);
3700 OCStackResult OCUnBindResource(
3701 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3703 OCResource *resource = NULL;
3704 OCChildResource *tempChildResource = NULL;
3705 OCChildResource *tempLastChildResource = NULL;
3707 OIC_LOG(INFO, TAG, "Entering OCUnBindResource");
3709 // Validate parameters
3710 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3711 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3712 // Container cannot contain itself
3713 if (collectionHandle == resourceHandle)
3715 OIC_LOG(ERROR, TAG, "removing handle equals collection handle");
3716 return OC_STACK_INVALID_PARAM;
3719 // Use the handle to find the resource in the resource linked list
3720 resource = findResource((OCResource *) collectionHandle);
3723 OIC_LOG(ERROR, TAG, "Collection handle not found");
3724 return OC_STACK_INVALID_PARAM;
3727 // Look for an open slot to add add the child resource.
3728 // If found, add it and return success
3729 if(!resource->rsrcChildResourcesHead)
3731 OIC_LOG(INFO, TAG, "resource not found in collection");
3733 // Unable to add resourceHandle, so return error
3734 return OC_STACK_ERROR;
3738 tempChildResource = resource->rsrcChildResourcesHead;
3740 while (tempChildResource)
3742 if(tempChildResource->rsrcResource == resourceHandle)
3744 // if resource going to be unbinded is the head one.
3745 if( tempChildResource == resource->rsrcChildResourcesHead )
3747 OCChildResource *temp = resource->rsrcChildResourcesHead->next;
3748 OICFree(resource->rsrcChildResourcesHead);
3749 resource->rsrcChildResourcesHead = temp;
3754 OCChildResource *temp = tempChildResource->next;
3755 OICFree(tempChildResource);
3756 if (tempLastChildResource)
3758 tempLastChildResource->next = temp;
3763 OIC_LOG(INFO, TAG, "resource unbound");
3765 // Send notification when resource is unbounded successfully.
3766 #ifdef WITH_PRESENCE
3767 if (presenceResource.handle)
3769 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3770 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3771 OC_PRESENCE_TRIGGER_CHANGE);
3774 tempChildResource = NULL;
3775 tempLastChildResource = NULL;
3781 tempLastChildResource = tempChildResource;
3782 tempChildResource = tempChildResource->next;
3785 OIC_LOG(INFO, TAG, "resource not found in collection");
3787 tempChildResource = NULL;
3788 tempLastChildResource = NULL;
3790 // Unable to add resourceHandle, so return error
3791 return OC_STACK_ERROR;
3794 static bool ValidateResourceTypeInterface(const char *resourceItemName)
3796 if (!resourceItemName)
3800 // Per RFC 6690 only registered values must follow the first rule below.
3801 // At this point in time the only values registered begin with "core", and
3802 // all other values are specified as opaque strings where multiple values
3803 // are separated by a space.
3804 if (strncmp(resourceItemName, CORESPEC, sizeof(CORESPEC) - 1) == 0)
3806 for(size_t index = sizeof(CORESPEC) - 1; resourceItemName[index]; ++index)
3808 if (resourceItemName[index] != '.'
3809 && resourceItemName[index] != '-'
3810 && (resourceItemName[index] < 'a' || resourceItemName[index] > 'z')
3811 && (resourceItemName[index] < '0' || resourceItemName[index] > '9'))
3819 for (size_t index = 0; resourceItemName[index]; ++index)
3821 if (resourceItemName[index] == ' '
3822 || resourceItemName[index] == '\t'
3823 || resourceItemName[index] == '\r'
3824 || resourceItemName[index] == '\n')
3834 OCStackResult BindResourceTypeToResource(OCResource* resource,
3835 const char *resourceTypeName)
3837 OCResourceType *pointer = NULL;
3839 OCStackResult result = OC_STACK_ERROR;
3841 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
3843 if (!ValidateResourceTypeInterface(resourceTypeName))
3845 OIC_LOG(ERROR, TAG, "resource type illegal (see RFC 6690)");
3846 return OC_STACK_INVALID_PARAM;
3849 pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
3852 result = OC_STACK_NO_MEMORY;
3856 str = OICStrdup(resourceTypeName);
3859 result = OC_STACK_NO_MEMORY;
3862 pointer->resourcetypename = str;
3863 pointer->next = NULL;
3865 insertResourceType(resource, pointer);
3866 result = OC_STACK_OK;
3869 if (result != OC_STACK_OK)
3878 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
3879 const char *resourceInterfaceName)
3881 OCResourceInterface *pointer = NULL;
3883 OCStackResult result = OC_STACK_ERROR;
3885 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
3887 if (!ValidateResourceTypeInterface(resourceInterfaceName))
3889 OIC_LOG(ERROR, TAG, "resource /interface illegal (see RFC 6690)");
3890 return OC_STACK_INVALID_PARAM;
3893 OIC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
3895 pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
3898 result = OC_STACK_NO_MEMORY;
3902 str = OICStrdup(resourceInterfaceName);
3905 result = OC_STACK_NO_MEMORY;
3908 pointer->name = str;
3910 // Bind the resourceinterface to the resource
3911 insertResourceInterface(resource, pointer);
3913 result = OC_STACK_OK;
3916 if (result != OC_STACK_OK)
3925 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
3926 const char *resourceTypeName)
3929 OCStackResult result = OC_STACK_ERROR;
3930 OCResource *resource = NULL;
3932 resource = findResource((OCResource *) handle);
3935 OIC_LOG(ERROR, TAG, "Resource not found");
3936 return OC_STACK_ERROR;
3939 result = BindResourceTypeToResource(resource, resourceTypeName);
3941 #ifdef WITH_PRESENCE
3942 if(presenceResource.handle)
3944 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3945 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3952 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
3953 const char *resourceInterfaceName)
3956 OCStackResult result = OC_STACK_ERROR;
3957 OCResource *resource = NULL;
3959 resource = findResource((OCResource *) handle);
3962 OIC_LOG(ERROR, TAG, "Resource not found");
3963 return OC_STACK_ERROR;
3966 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
3968 #ifdef WITH_PRESENCE
3969 if (presenceResource.handle)
3971 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3972 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3979 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
3981 OCResource *pointer = headResource;
3983 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
3987 *numResources = *numResources + 1;
3988 pointer = pointer->next;
3993 OCResourceHandle OCGetResourceHandle(uint8_t index)
3995 OCResource *pointer = headResource;
3997 for( uint8_t i = 0; i < index && pointer; ++i)
3999 pointer = pointer->next;
4001 return (OCResourceHandle) pointer;
4004 OCStackResult OCDeleteResource(OCResourceHandle handle)
4008 OIC_LOG(ERROR, TAG, "Invalid handle for deletion");
4009 return OC_STACK_INVALID_PARAM;
4012 OCResource *resource = findResource((OCResource *) handle);
4013 if (resource == NULL)
4015 OIC_LOG(ERROR, TAG, "Resource not found");
4016 return OC_STACK_NO_RESOURCE;
4019 if (deleteResource((OCResource *) handle) != OC_STACK_OK)
4021 OIC_LOG(ERROR, TAG, "Error deleting resource");
4022 return OC_STACK_ERROR;
4028 const char *OCGetResourceUri(OCResourceHandle handle)
4030 OCResource *resource = NULL;
4032 resource = findResource((OCResource *) handle);
4035 return resource->uri;
4037 return (const char *) NULL;
4040 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
4042 OCResource *resource = NULL;
4044 resource = findResource((OCResource *) handle);
4047 return resource->resourceProperties;
4049 return (OCResourceProperty)-1;
4052 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
4053 uint8_t *numResourceTypes)
4055 OCResource *resource = NULL;
4056 OCResourceType *pointer = NULL;
4058 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
4059 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
4061 *numResourceTypes = 0;
4063 resource = findResource((OCResource *) handle);
4066 pointer = resource->rsrcType;
4069 *numResourceTypes = *numResourceTypes + 1;
4070 pointer = pointer->next;
4076 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
4078 OCResourceType *resourceType = NULL;
4080 resourceType = findResourceTypeAtIndex(handle, index);
4083 return resourceType->resourcetypename;
4085 return (const char *) NULL;
4088 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
4089 uint8_t *numResourceInterfaces)
4091 OCResourceInterface *pointer = NULL;
4092 OCResource *resource = NULL;
4094 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
4095 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
4097 *numResourceInterfaces = 0;
4098 resource = findResource((OCResource *) handle);
4101 pointer = resource->rsrcInterface;
4104 *numResourceInterfaces = *numResourceInterfaces + 1;
4105 pointer = pointer->next;
4111 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
4113 OCResourceInterface *resourceInterface = NULL;
4115 resourceInterface = findResourceInterfaceAtIndex(handle, index);
4116 if (resourceInterface)
4118 return resourceInterface->name;
4120 return (const char *) NULL;
4123 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
4126 OCResource *resource = NULL;
4127 OCChildResource *tempChildResource = NULL;
4130 resource = findResource((OCResource *) collectionHandle);
4136 tempChildResource = resource->rsrcChildResourcesHead;
4138 while(tempChildResource)
4142 return tempChildResource->rsrcResource;
4145 tempChildResource = tempChildResource->next;
4148 // In this case, the number of resource handles in the collection exceeds the index
4149 tempChildResource = NULL;
4153 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
4154 OCEntityHandler entityHandler,
4155 void* callbackParam)
4157 OCResource *resource = NULL;
4159 // Validate parameters
4160 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
4162 // Use the handle to find the resource in the resource linked list
4163 resource = findResource((OCResource *)handle);
4166 OIC_LOG(ERROR, TAG, "Resource not found");
4167 return OC_STACK_ERROR;
4171 resource->entityHandler = entityHandler;
4172 resource->entityHandlerCallbackParam = callbackParam;
4174 #ifdef WITH_PRESENCE
4175 if (presenceResource.handle)
4177 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
4178 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
4185 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
4187 OCResource *resource = NULL;
4189 resource = findResource((OCResource *)handle);
4192 OIC_LOG(ERROR, TAG, "Resource not found");
4197 return resource->entityHandler;
4200 void incrementSequenceNumber(OCResource * resPtr)
4202 // Increment the sequence number
4203 resPtr->sequenceNum += 1;
4204 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
4206 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
4211 #ifdef WITH_PRESENCE
4212 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
4213 OCPresenceTrigger trigger)
4215 OIC_LOG(INFO, TAG, "SendPresenceNotification");
4216 OCResource *resPtr = NULL;
4217 OCStackResult result = OC_STACK_ERROR;
4218 OCMethod method = OC_REST_PRESENCE;
4219 uint32_t maxAge = 0;
4220 resPtr = findResource((OCResource *) presenceResource.handle);
4223 return OC_STACK_NO_RESOURCE;
4226 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
4228 maxAge = presenceResource.presenceTTL;
4230 result = SendAllObserverNotification(method, resPtr, maxAge,
4231 trigger, resourceType, OC_LOW_QOS);
4237 OCStackResult SendStopNotification()
4239 OIC_LOG(INFO, TAG, "SendStopNotification");
4240 OCResource *resPtr = NULL;
4241 OCStackResult result = OC_STACK_ERROR;
4242 OCMethod method = OC_REST_PRESENCE;
4243 resPtr = findResource((OCResource *) presenceResource.handle);
4246 return OC_STACK_NO_RESOURCE;
4249 // maxAge is 0. ResourceType is NULL.
4250 result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
4256 #endif // WITH_PRESENCE
4257 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
4259 OCResource *resPtr = NULL;
4260 OCStackResult result = OC_STACK_ERROR;
4261 OCMethod method = OC_REST_NOMETHOD;
4262 uint32_t maxAge = 0;
4264 OIC_LOG(INFO, TAG, "Notifying all observers");
4265 #ifdef WITH_PRESENCE
4266 if(handle == presenceResource.handle)
4270 #endif // WITH_PRESENCE
4271 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
4273 // Verify that the resource exists
4274 resPtr = findResource ((OCResource *) handle);
4277 return OC_STACK_NO_RESOURCE;
4281 //only increment in the case of regular observing (not presence)
4282 incrementSequenceNumber(resPtr);
4283 method = OC_REST_OBSERVE;
4284 maxAge = MAX_OBSERVE_AGE;
4285 #ifdef WITH_PRESENCE
4286 result = SendAllObserverNotification (method, resPtr, maxAge,
4287 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
4289 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
4296 OCNotifyListOfObservers (OCResourceHandle handle,
4297 OCObservationId *obsIdList,
4298 uint8_t numberOfIds,
4299 const OCRepPayload *payload,
4300 OCQualityOfService qos)
4302 OIC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
4304 OCResource *resPtr = NULL;
4305 //TODO: we should allow the server to define this
4306 uint32_t maxAge = MAX_OBSERVE_AGE;
4308 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
4309 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
4310 VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
4312 resPtr = findResource ((OCResource *) handle);
4313 if (NULL == resPtr || myStackMode == OC_CLIENT)
4315 return OC_STACK_NO_RESOURCE;
4319 incrementSequenceNumber(resPtr);
4321 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
4322 payload, maxAge, qos));
4325 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
4327 OIC_TRACE_BEGIN(%s:OCDoResponse, TAG);
4328 OCStackResult result = OC_STACK_ERROR;
4329 OCServerRequest *serverRequest = NULL;
4331 OIC_LOG(INFO, TAG, "Entering OCDoResponse");
4333 // Validate input parameters
4334 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
4335 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
4338 // Get pointer to request info
4339 serverRequest = GetServerRequestUsingHandle(ehResponse->requestHandle);
4342 // response handler in ocserverrequest.c. Usually HandleSingleResponse.
4343 result = serverRequest->ehResponseHandler(ehResponse);
4350 //#ifdef DIRECT_PAIRING
4351 const OCDPDev_t* OCDiscoverDirectPairingDevices(unsigned short waittime)
4353 OIC_LOG(INFO, TAG, "Start OCDiscoverDirectPairingDevices");
4354 if(OC_STACK_OK != DPDeviceDiscovery(waittime))
4356 OIC_LOG(ERROR, TAG, "Fail to discover Direct-Pairing device");
4360 return (const OCDPDev_t*)DPGetDiscoveredDevices();
4363 const OCDPDev_t* OCGetDirectPairedDevices()
4365 return (const OCDPDev_t*)DPGetPairedDevices();
4368 OCStackResult OCDoDirectPairing(void *ctx, OCDPDev_t* peer, OCPrm_t pmSel, char *pinNumber,
4369 OCDirectPairingCB resultCallback)
4371 OIC_LOG(INFO, TAG, "Start OCDoDirectPairing");
4372 if(NULL == peer || NULL == pinNumber)
4374 OIC_LOG(ERROR, TAG, "Invalid parameters");
4375 return OC_STACK_INVALID_PARAM;
4377 if (NULL == resultCallback)
4379 OIC_LOG(ERROR, TAG, "Invalid callback");
4380 return OC_STACK_INVALID_CALLBACK;
4383 return DPDirectPairing(ctx, (OCDirectPairingDev_t*)peer, (OicSecPrm_t)pmSel,
4384 pinNumber, (OCDirectPairingResultCB)resultCallback);
4386 //#endif // DIRECT_PAIRING
4388 //-----------------------------------------------------------------------------
4389 // Private internal function definitions
4390 //-----------------------------------------------------------------------------
4391 static OCDoHandle GenerateInvocationHandle()
4393 OCDoHandle handle = NULL;
4394 // Generate token here, it will be deleted when the transaction is deleted
4395 handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
4398 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
4404 #ifdef WITH_PRESENCE
4405 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
4406 OCResourceProperty resourceProperties, uint8_t enable)
4410 return OC_STACK_INVALID_PARAM;
4412 if (resourceProperties
4413 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
4415 OIC_LOG(ERROR, TAG, "Invalid property");
4416 return OC_STACK_INVALID_PARAM;
4420 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
4424 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
4430 OCStackResult initResources()
4432 OCStackResult result = OC_STACK_OK;
4434 headResource = NULL;
4435 tailResource = NULL;
4436 // Init Virtual Resources
4437 #ifdef WITH_PRESENCE
4438 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
4440 result = OCCreateResource(&presenceResource.handle,
4441 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
4443 OC_RSRVD_PRESENCE_URI,
4447 //make resource inactive
4448 result = OCChangeResourceProperty(
4449 &(((OCResource *) presenceResource.handle)->resourceProperties),
4452 #ifndef WITH_ARDUINO
4453 if (result == OC_STACK_OK)
4455 result = SRMInitSecureResources();
4459 if(result == OC_STACK_OK)
4461 CreateResetProfile();
4462 result = OCCreateResource(&deviceResource,
4463 OC_RSRVD_RESOURCE_TYPE_DEVICE,
4464 OC_RSRVD_INTERFACE_DEFAULT,
4465 OC_RSRVD_DEVICE_URI,
4469 if(result == OC_STACK_OK)
4471 result = BindResourceInterfaceToResource((OCResource *)deviceResource,
4472 OC_RSRVD_INTERFACE_READ);
4476 if(result == OC_STACK_OK)
4478 result = OCCreateResource(&platformResource,
4479 OC_RSRVD_RESOURCE_TYPE_PLATFORM,
4480 OC_RSRVD_INTERFACE_DEFAULT,
4481 OC_RSRVD_PLATFORM_URI,
4485 if(result == OC_STACK_OK)
4487 result = BindResourceInterfaceToResource((OCResource *)platformResource,
4488 OC_RSRVD_INTERFACE_READ);
4495 void insertResource(OCResource *resource)
4499 headResource = resource;
4500 tailResource = resource;
4504 tailResource->next = resource;
4505 tailResource = resource;
4507 resource->next = NULL;
4510 OCResource *findResource(OCResource *resource)
4512 OCResource *pointer = headResource;
4516 if (pointer == resource)
4520 pointer = pointer->next;
4525 void deleteAllResources()
4527 OCResource *pointer = headResource;
4528 OCResource *temp = NULL;
4532 temp = pointer->next;
4533 #ifdef WITH_PRESENCE
4534 if (pointer != (OCResource *) presenceResource.handle)
4536 #endif // WITH_PRESENCE
4537 deleteResource(pointer);
4538 #ifdef WITH_PRESENCE
4540 #endif // WITH_PRESENCE
4543 memset(&platformResource, 0, sizeof(platformResource));
4544 memset(&deviceResource, 0, sizeof(deviceResource));
4546 memset(&brokerResource, 0, sizeof(brokerResource));
4549 SRMDeInitSecureResources();
4551 #ifdef WITH_PRESENCE
4552 // Ensure that the last resource to be deleted is the presence resource. This allows for all
4553 // presence notification attributed to their deletion to be processed.
4554 deleteResource((OCResource *) presenceResource.handle);
4555 memset(&presenceResource, 0, sizeof(presenceResource));
4556 #endif // WITH_PRESENCE
4559 OCStackResult deleteResource(OCResource *resource)
4561 OCResource *prev = NULL;
4562 OCResource *temp = NULL;
4565 OIC_LOG(DEBUG,TAG,"resource is NULL");
4566 return OC_STACK_INVALID_PARAM;
4569 OIC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
4571 temp = headResource;
4574 if (temp == resource)
4576 // Invalidate all Resource Properties.
4577 resource->resourceProperties = (OCResourceProperty) 0;
4578 #ifdef WITH_PRESENCE
4579 if(resource != (OCResource *) presenceResource.handle)
4581 #endif // WITH_PRESENCE
4582 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
4583 #ifdef WITH_PRESENCE
4586 if(presenceResource.handle)
4588 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
4589 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
4592 // Only resource in list.
4593 if (temp == headResource && temp == tailResource)
4595 headResource = NULL;
4596 tailResource = NULL;
4599 else if (temp == headResource)
4601 headResource = temp->next;
4604 else if (temp == tailResource && prev)
4606 tailResource = prev;
4607 tailResource->next = NULL;
4611 prev->next = temp->next;
4614 deleteResourceElements(temp);
4625 return OC_STACK_ERROR;
4628 void deleteResourceElements(OCResource *resource)
4637 OICFree(resource->uri);
4638 resource->uri = NULL;
4640 if (resource->rsrcType)
4642 deleteResourceType(resource->rsrcType);
4643 resource->rsrcType = NULL;
4645 if (resource->rsrcInterface)
4647 deleteResourceInterface(resource->rsrcInterface);
4648 resource->rsrcInterface = NULL;
4650 if (resource->rsrcChildResourcesHead)
4652 deleteResourceChild(resource->rsrcChildResourcesHead);
4653 resource->rsrcChildResourcesHead = NULL;
4655 if (resource->rsrcAttributes)
4657 OCDeleteResourceAttributes(resource->rsrcAttributes);
4658 resource->rsrcAttributes = NULL;
4663 void deleteResourceType(OCResourceType *resourceType)
4665 OCResourceType *next = NULL;
4667 for (OCResourceType *pointer = resourceType; pointer; pointer = next)
4669 next = pointer->next ? pointer->next : NULL;
4670 if (pointer->resourcetypename)
4672 OICFree(pointer->resourcetypename);
4673 pointer->resourcetypename = NULL;
4679 void deleteResourceInterface(OCResourceInterface *resourceInterface)
4681 OCResourceInterface *next = NULL;
4682 for (OCResourceInterface *pointer = resourceInterface; pointer; pointer = next)
4684 next = pointer->next ? pointer->next : NULL;
4687 OICFree(pointer->name);
4688 pointer->name = NULL;
4694 void deleteResourceChild(OCChildResource *resourceChild)
4696 OCChildResource *next = NULL;
4697 for (OCChildResource *pointer = resourceChild; pointer; pointer = next)
4699 next = pointer->next ? pointer->next : NULL;
4700 if (pointer->rsrcResource)
4702 deleteResourceElements(pointer->rsrcResource);
4703 pointer->rsrcResource = NULL;
4709 void OCDeleteResourceAttributes(OCAttribute *rsrcAttributes)
4711 OCAttribute *next = NULL;
4712 for (OCAttribute *pointer = rsrcAttributes; pointer; pointer = next)
4714 next = pointer->next ? pointer->next : NULL;
4715 if (pointer->attrName && 0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, pointer->attrName))
4717 OCFreeOCStringLL((OCStringLL *)pointer->attrValue);
4718 pointer->attrValue = NULL;
4720 else if (pointer->attrValue)
4722 OICFree(pointer->attrValue);
4723 pointer->attrValue = NULL;
4725 if (pointer->attrName)
4727 OICFree(pointer->attrName);
4728 pointer->attrName = NULL;
4734 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
4736 OCResourceType *pointer = NULL;
4737 OCResourceType *previous = NULL;
4738 if (!resource || !resourceType)
4742 // resource type list is empty.
4743 else if (!resource->rsrcType)
4745 resource->rsrcType = resourceType;
4749 pointer = resource->rsrcType;
4753 if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
4755 OIC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
4756 OICFree(resourceType->resourcetypename);
4757 OICFree(resourceType);
4761 pointer = pointer->next;
4766 previous->next = resourceType;
4769 resourceType->next = NULL;
4771 OIC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
4774 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
4776 OCResource *resource = NULL;
4777 OCResourceType *pointer = NULL;
4779 // Find the specified resource
4780 resource = findResource((OCResource *) handle);
4786 // Make sure a resource has a resourcetype
4787 if (!resource->rsrcType)
4792 // Iterate through the list
4793 pointer = resource->rsrcType;
4794 for(uint8_t i = 0; i< index && pointer; ++i)
4796 pointer = pointer->next;
4801 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
4803 if(resourceTypeList && resourceTypeName)
4805 OCResourceType * rtPointer = resourceTypeList;
4806 while(resourceTypeName && rtPointer)
4808 OIC_LOG_V(DEBUG, TAG, "current resourceType : %s", rtPointer->resourcetypename);
4809 if(rtPointer->resourcetypename &&
4810 strcmp(resourceTypeName, (const char *)
4811 (rtPointer->resourcetypename)) == 0)
4815 rtPointer = rtPointer->next;
4823 * Insert a new interface into interface linked list only if not already present.
4824 * If alredy present, 2nd arg is free'd.
4825 * Default interface will always be first if present.
4827 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
4829 OCResourceInterface *pointer = NULL;
4830 OCResourceInterface *previous = NULL;
4832 newInterface->next = NULL;
4834 OCResourceInterface **firstInterface = &(resource->rsrcInterface);
4836 if (!*firstInterface)
4838 // If first interface is not oic.if.baseline, by default add it as first interface type.
4839 if (0 == strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT))
4841 *firstInterface = newInterface;
4845 OCStackResult result = BindResourceInterfaceToResource(resource,
4846 OC_RSRVD_INTERFACE_DEFAULT);
4847 if (result != OC_STACK_OK)
4849 OICFree(newInterface->name);
4850 OICFree(newInterface);
4853 if (*firstInterface)
4855 (*firstInterface)->next = newInterface;
4859 // If once add oic.if.baseline, later too below code take care of freeing memory.
4860 else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
4862 if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
4864 OICFree(newInterface->name);
4865 OICFree(newInterface);
4868 // This code will not hit anymore, keeping
4871 newInterface->next = *firstInterface;
4872 *firstInterface = newInterface;
4877 pointer = *firstInterface;
4880 if (strcmp(newInterface->name, pointer->name) == 0)
4882 OICFree(newInterface->name);
4883 OICFree(newInterface);
4887 pointer = pointer->next;
4892 previous->next = newInterface;
4897 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
4900 OCResource *resource = NULL;
4901 OCResourceInterface *pointer = NULL;
4903 // Find the specified resource
4904 resource = findResource((OCResource *) handle);
4910 // Make sure a resource has a resourceinterface
4911 if (!resource->rsrcInterface)
4916 // Iterate through the list
4917 pointer = resource->rsrcInterface;
4919 for (uint8_t i = 0; i < index && pointer; ++i)
4921 pointer = pointer->next;
4927 * This function splits the uri using the '?' delimiter.
4928 * "uriWithoutQuery" is the block of characters between the beginning
4929 * till the delimiter or '\0' which ever comes first.
4930 * "query" is whatever is to the right of the delimiter if present.
4931 * No delimiter sets the query to NULL.
4932 * If either are present, they will be malloc'ed into the params 2, 3.
4933 * The first param, *uri is left untouched.
4935 * NOTE: This function does not account for whitespace at the end of the uri NOR
4936 * malformed uri's with '??'. Whitespace at the end will be assumed to be
4937 * part of the query.
4939 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
4943 return OC_STACK_INVALID_URI;
4945 if(!query || !uriWithoutQuery)
4947 return OC_STACK_INVALID_PARAM;
4951 *uriWithoutQuery = NULL;
4953 size_t uriWithoutQueryLen = 0;
4954 size_t queryLen = 0;
4955 size_t uriLen = strlen(uri);
4957 char *pointerToDelimiter = strstr(uri, "?");
4959 uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
4960 queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
4962 if (uriWithoutQueryLen)
4964 *uriWithoutQuery = (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
4965 if (!*uriWithoutQuery)
4969 OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
4973 *query = (char *) OICCalloc(queryLen + 1, 1);
4976 OICFree(*uriWithoutQuery);
4977 *uriWithoutQuery = NULL;
4980 OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
4986 return OC_STACK_NO_MEMORY;
4989 const char* OCGetServerInstanceIDString(void)
4991 static char sidStr[UUID_STRING_SIZE];
4993 if (OC_STACK_OK != GetDoxmDeviceID(&sid))
4995 OIC_LOG(FATAL, TAG, "GetDoxmDeviceID failed!");
4999 if (OCConvertUuidToString(sid.id, sidStr) != RAND_UUID_OK)
5001 OIC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
5008 CAResult_t OCSelectNetwork(OCTransportAdapter transportType)
5010 OIC_LOG_V(DEBUG, TAG, "OCSelectNetwork [%d]", transportType);
5011 CAResult_t retResult = CA_STATUS_FAILED;
5012 CAResult_t caResult = CA_STATUS_OK;
5014 CATransportAdapter_t connTypes[] = {
5016 CA_ADAPTER_RFCOMM_BTEDR,
5017 CA_ADAPTER_GATT_BTLE,
5020 ,CA_ADAPTER_REMOTE_ACCESS
5027 int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
5029 for(int i = 0; i < numConnTypes; i++)
5031 // If CA status is not initialized, CASelectNetwork() will not be called.
5032 if (caResult != CA_STATUS_NOT_INITIALIZED)
5034 if ((connTypes[i] & transportType) || (OC_DEFAULT_ADAPTER == transportType))
5036 OIC_LOG_V(DEBUG, TAG, "call CASelectNetwork [%d]", connTypes[i]);
5037 caResult = CASelectNetwork(connTypes[i]);
5038 if (caResult == CA_STATUS_OK)
5040 retResult = CA_STATUS_OK;
5045 OIC_LOG_V(DEBUG, TAG, "there is no transport type [%d]", connTypes[i]);
5050 if (retResult != CA_STATUS_OK)
5052 return caResult; // Returns error of appropriate transport that failed fatally.
5058 OCStackResult CAResultToOCResult(CAResult_t caResult)
5064 case CA_STATUS_INVALID_PARAM:
5065 return OC_STACK_INVALID_PARAM;
5066 case CA_ADAPTER_NOT_ENABLED:
5067 return OC_STACK_ADAPTER_NOT_ENABLED;
5068 case CA_SERVER_STARTED_ALREADY:
5070 case CA_SERVER_NOT_STARTED:
5071 return OC_STACK_ERROR;
5072 case CA_DESTINATION_NOT_REACHABLE:
5073 return OC_STACK_COMM_ERROR;
5074 case CA_SOCKET_OPERATION_FAILED:
5075 return OC_STACK_COMM_ERROR;
5076 case CA_SEND_FAILED:
5077 return OC_STACK_COMM_ERROR;
5078 case CA_RECEIVE_FAILED:
5079 return OC_STACK_COMM_ERROR;
5080 case CA_MEMORY_ALLOC_FAILED:
5081 return OC_STACK_NO_MEMORY;
5082 case CA_REQUEST_TIMEOUT:
5083 return OC_STACK_TIMEOUT;
5084 case CA_DESTINATION_DISCONNECTED:
5085 return OC_STACK_COMM_ERROR;
5086 case CA_STATUS_FAILED:
5087 return OC_STACK_ERROR;
5088 case CA_NOT_SUPPORTED:
5089 return OC_STACK_NOTIMPL;
5091 return OC_STACK_ERROR;
5095 bool OCResultToSuccess(OCStackResult ocResult)
5100 case OC_STACK_RESOURCE_CREATED:
5101 case OC_STACK_RESOURCE_DELETED:
5102 case OC_STACK_CONTINUE:
5103 case OC_STACK_RESOURCE_CHANGED:
5104 case OC_STACK_SLOW_RESOURCE:
5112 OCStackResult OCSetProxyURI(const char *uri)
5114 return CAResultToOCResult(CASetProxyUri(uri));
5118 #if defined(RD_CLIENT) || defined(RD_SERVER)
5119 OCStackResult OCBindResourceInsToResource(OCResourceHandle handle, int64_t ins)
5121 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
5123 OCResource *resource = NULL;
5125 resource = findResource((OCResource *) handle);
5128 OIC_LOG(ERROR, TAG, "Resource not found");
5129 return OC_STACK_ERROR;
5132 resource->ins = ins;
5138 OCStackResult OCUpdateResourceInsWithResponse(const char *requestUri,
5139 const OCClientResponse *response)
5141 // Validate input parameters
5142 VERIFY_NON_NULL(requestUri, ERROR, OC_STACK_INVALID_PARAM);
5143 VERIFY_NON_NULL(response, ERROR, OC_STACK_INVALID_PARAM);
5145 char *targetUri = (char *) OICMalloc(strlen(requestUri) + 1);
5148 return OC_STACK_NO_MEMORY;
5150 strncpy(targetUri, requestUri, strlen(requestUri) + 1);
5152 if (response->result == OC_STACK_RESOURCE_CHANGED) // publish message
5154 OIC_LOG(DEBUG, TAG, "update the ins of published resource");
5156 char rdPubUri[MAX_URI_LENGTH] = { 0 };
5157 snprintf(rdPubUri, MAX_URI_LENGTH, "%s?rt=%s", OC_RSRVD_RD_URI,
5158 OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
5160 if (strcmp(rdPubUri, targetUri) == 0)
5162 // Update resource unique id in stack.
5165 if (response->payload)
5167 OCRepPayload *rdPayload = (OCRepPayload *) response->payload;
5168 OCRepPayload **links = NULL;
5169 size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
5170 if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS,
5171 &links, dimensions))
5174 for (; i < dimensions[0]; i++)
5177 if (OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri))
5179 OCResourceHandle handle = OCGetResourceHandleAtUri(uri);
5181 if (OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins))
5183 OCBindResourceInsToResource(handle, ins);
5192 else if (response->result == OC_STACK_RESOURCE_DELETED) // delete message
5194 OIC_LOG(DEBUG, TAG, "update the ins of deleted resource with 0");
5196 uint8_t numResources = 0;
5197 OCGetNumberOfResources(&numResources);
5199 char *ins = strstr(targetUri, OC_RSRVD_INS);
5202 for (uint8_t i = 0; i < numResources; i++)
5204 OCResourceHandle resHandle = OCGetResourceHandle(i);
5207 OCBindResourceInsToResource(resHandle, 0);
5213 const char *token = "&";
5214 char *iterTokenPtr = NULL;
5215 char *start = strtok_r(targetUri, token, &iterTokenPtr);
5217 while (start != NULL)
5219 char *query = start;
5220 query = strstr(query, OC_RSRVD_INS);
5223 int64_t queryIns = atoi(query + 4);
5224 for (uint8_t i = 0; i < numResources; i++)
5226 OCResourceHandle resHandle = OCGetResourceHandle(i);
5230 OCGetResourceIns(resHandle, &resIns);
5231 if (queryIns && queryIns == resIns)
5233 OCBindResourceInsToResource(resHandle, 0);
5239 start = strtok_r(NULL, token, &iterTokenPtr);
5248 OCResourceHandle OCGetResourceHandleAtUri(const char *uri)
5252 OIC_LOG(ERROR, TAG, "Resource uri is NULL");
5256 OCResource *pointer = headResource;
5260 if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
5262 OIC_LOG_V(DEBUG, TAG, "Found Resource %s", uri);
5265 pointer = pointer->next;
5270 OCStackResult OCGetResourceIns(OCResourceHandle handle, int64_t *ins)
5272 OCResource *resource = NULL;
5274 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
5275 VERIFY_NON_NULL(ins, ERROR, OC_STACK_INVALID_PARAM);
5277 resource = findResource((OCResource *) handle);
5280 *ins = resource->ins;
5283 return OC_STACK_ERROR;
5287 OCStackResult OCSetHeaderOption(OCHeaderOption* ocHdrOpt, size_t* numOptions, uint16_t optionID,
5288 void* optionData, size_t optionDataLength)
5292 OIC_LOG (INFO, TAG, "Header options are NULL");
5293 return OC_STACK_INVALID_PARAM;
5298 OIC_LOG (INFO, TAG, "optionData are NULL");
5299 return OC_STACK_INVALID_PARAM;
5304 OIC_LOG (INFO, TAG, "numOptions is NULL");
5305 return OC_STACK_INVALID_PARAM;
5308 if (*numOptions >= MAX_HEADER_OPTIONS)
5310 OIC_LOG (INFO, TAG, "Exceeding MAX_HEADER_OPTIONS");
5311 return OC_STACK_NO_MEMORY;
5314 ocHdrOpt += *numOptions;
5315 ocHdrOpt->protocolID = OC_COAP_ID;
5316 ocHdrOpt->optionID = optionID;
5317 ocHdrOpt->optionLength =
5318 optionDataLength < MAX_HEADER_OPTION_DATA_LENGTH ?
5319 optionDataLength : MAX_HEADER_OPTION_DATA_LENGTH;
5320 memcpy(ocHdrOpt->optionData, (const void*) optionData, ocHdrOpt->optionLength);
5326 OCStackResult OCGetHeaderOption(OCHeaderOption* ocHdrOpt, size_t numOptions, uint16_t optionID,
5327 void* optionData, size_t optionDataLength, uint16_t* receivedDataLength)
5329 if (!ocHdrOpt || !numOptions)
5331 OIC_LOG (INFO, TAG, "No options present");
5337 OIC_LOG (INFO, TAG, "optionData are NULL");
5338 return OC_STACK_INVALID_PARAM;
5341 if (!receivedDataLength)
5343 OIC_LOG (INFO, TAG, "receivedDataLength is NULL");
5344 return OC_STACK_INVALID_PARAM;
5347 for (uint8_t i = 0; i < numOptions; i++)
5349 if (ocHdrOpt[i].optionID == optionID)
5351 if (optionDataLength >= ocHdrOpt->optionLength)
5353 memcpy(optionData, ocHdrOpt->optionData, ocHdrOpt->optionLength);
5354 *receivedDataLength = ocHdrOpt->optionLength;
5359 OIC_LOG (ERROR, TAG, "optionDataLength is less than the length of received data");
5360 return OC_STACK_ERROR;
5367 void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled)
5369 OIC_LOG(DEBUG, TAG, "OCDefaultAdapterStateChangedHandler");
5370 if (g_adapterHandler)
5372 g_adapterHandler(adapter, enabled);
5376 void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected)
5378 OIC_LOG(DEBUG, TAG, "OCDefaultConnectionStateChangedHandler");
5379 if (g_connectionHandler)
5381 g_connectionHandler(info, isConnected);
5385 * If the client observes one or more resources over a reliable connection,
5386 * then the CoAP server (or intermediary in the role of the CoAP server)
5387 * MUST remove all entries associated with the client endpoint from the lists
5388 * of observers when the connection is either closed or times out.
5392 OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
5393 CopyEndpointToDevAddr(info, &devAddr);
5395 // remove observer list with remote device address.
5396 DeleteObserverUsingDevAddr(&devAddr);
5400 void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler,
5401 CAConnectionStateChangedCB connectionHandler)
5403 OIC_LOG(DEBUG, TAG, "OCSetNetworkMonitorHandler");
5404 g_adapterHandler = adapterHandler;
5405 g_connectionHandler = connectionHandler;
5408 OCStackResult OCGetDeviceId(OCUUIdentity *deviceId)
5411 OCStackResult ret = OC_STACK_ERROR;
5413 ret = GetDoxmDeviceID(&oicUuid);
5414 if (OC_STACK_OK == ret)
5416 memcpy(deviceId, &oicUuid, UUID_IDENTITY_SIZE);
5420 OIC_LOG(ERROR, TAG, "Device ID Get error");
5425 OCStackResult OCSetDeviceId(const OCUUIdentity *deviceId)
5428 OCStackResult ret = OC_STACK_ERROR;
5430 memcpy(&oicUuid, deviceId, UUID_LENGTH);
5431 for (int i = 0; i < UUID_LENGTH; i++)
5433 OIC_LOG_V(INFO, TAG, "Set Device Id %x", oicUuid.id[i]);
5435 ret = SetDoxmDeviceID(&oicUuid);
5439 OCStackResult OCGetDeviceOwnedState(bool *isOwned)
5441 bool isDeviceOwned = true;
5442 OCStackResult ret = OC_STACK_ERROR;
5444 ret = GetDoxmIsOwned(&isDeviceOwned);
5445 if (OC_STACK_OK == ret)
5447 *isOwned = isDeviceOwned;
5451 OIC_LOG(ERROR, TAG, "Device Owned State Get error");
5456 void OCClearCallBackList()
5458 DeleteClientCBList();
5461 void OCClearObserverlist()
5463 DeleteObserverList();
5466 int OCEncrypt(const unsigned char *pt, size_t pt_len,
5467 unsigned char **ct, size_t *ct_len)
5469 #ifndef __SECURE_PSI__
5470 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);
5473 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5475 return psiEncrypt(pt, pt_len, ct, ct_len);
5476 #endif // __SECURE_PSI__
5479 int OCDecrypt(const unsigned char *ct, size_t ct_len,
5480 unsigned char **pt, size_t *pt_len)
5482 #ifndef __SECURE_PSI__
5483 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);
5486 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5488 return psiDecrypt(ct, ct_len, pt, pt_len);
5489 #endif // __SECURE_PSI__
5492 OCStackResult OCSetKey(const unsigned char* key)
5494 #ifndef __SECURE_PSI__
5495 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);
5498 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5500 return psiSetKey(key);
5501 #endif // __SECURE_PSI__
5504 OCStackResult OCGetKey(unsigned char* key)
5506 #ifndef __SECURE_PSI__
5507 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);
5510 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5512 return psiGetKey(key);
5513 #endif // __SECURE_PSI__
5516 OCStackResult OCSetSecurePSI(const unsigned char *key, const OCPersistentStorage *psPlain,
5517 const OCPersistentStorage *psEnc, const OCPersistentStorage *psRescue)
5519 #ifndef __SECURE_PSI__
5520 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);
5523 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5525 return setSecurePSI(key, psPlain, psEnc, psRescue);
5526 #endif // __SECURE_PSI__
5529 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
5530 static void OtmEventHandler(const char *addr, uint16_t port, const char *uuid, int event)
5532 if (g_otmEventHandler.cb)
5534 g_otmEventHandler.cb(g_otmEventHandler.ctx, addr, port, uuid, event);
5539 * It is already declared in srmutility.h.
5540 * We can't include the header file, because of "redefined VERIFY_NON_NULL"
5542 typedef void (*OicSecOtmEventHandler_t)(const char* addr, uint16_t port,
5543 const char* uuid, int event);
5544 void SetOtmEventHandler(OicSecOtmEventHandler_t otmEventHandler);
5547 OCStackResult OCSetOtmEventHandler(void *ctx, OCOtmEventHandler cb)
5549 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
5550 OIC_LOG_V(DEBUG, TAG, "%s", __func__);
5552 g_otmEventHandler.cb = cb;
5553 g_otmEventHandler.ctx = ctx;
5555 if (g_otmEventHandler.cb)
5557 OIC_LOG(DEBUG, TAG, "SET OCOtmEventHandler");
5558 SetOtmEventHandler(OtmEventHandler);
5562 OIC_LOG(DEBUG, TAG, "UNSET OCOtmEventHandler");
5563 SetOtmEventHandler(NULL);
5566 OIC_LOG_V(DEBUG, TAG, "Not Supported : %s", __func__);