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 //-----------------------------------------------------------------------------
25 #define _POSIX_C_SOURCE 200112L
30 #include "ocstackinternal.h"
31 #include "ocresourcehandler.h"
32 #include "occlientcb.h"
33 #include "ocobserve.h"
36 #include "ocserverrequest.h"
37 #include "ocsecurityinternal.h"
40 #include "cainterface.h"
47 #include "coap_time.h"
52 #include <arpa/inet.h>
55 //-----------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------
59 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
63 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
67 //-----------------------------------------------------------------------------
69 //-----------------------------------------------------------------------------
70 static OCStackState stackState = OC_STACK_UNINITIALIZED;
72 OCResource *headResource = NULL;
73 static OCResource *tailResource = NULL;
75 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
76 static PresenceResource presenceResource;
77 static uint8_t PresenceTimeOutSize = 0;
78 static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
81 static OCMode myStackMode;
82 OCDeviceEntityHandler defaultDeviceHandler;
83 OCStackResult getQueryFromUri(const char * uri, char** resourceType, char ** newURI);
85 //-----------------------------------------------------------------------------
87 //-----------------------------------------------------------------------------
88 #define TAG PCF("OCStack")
89 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
90 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
91 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
92 TAG, PCF(#arg " is NULL")); return (retVal); } }
93 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
96 //TODO: we should allow the server to define this
97 #define MAX_OBSERVE_AGE (0x2FFFFUL)
99 //=============================================================================
101 //=============================================================================
102 static uint32_t GetTime(float afterSeconds)
106 return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
109 static OCStackResult FormOCResponse(OCResponse * * responseLoc,
114 CAToken_t * rcvdToken,
115 OCClientResponse * clientResponse,
118 OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
121 return OC_STACK_NO_MEMORY;
123 response->cbNode = cbNode;
124 response->maxAge = maxAge;
125 response->fullUri = fullUri;
126 response->rcvdUri = rcvdUri;
127 response->rcvdToken = rcvdToken;
128 response->clientResponse = clientResponse;
129 response->bufRes = bufRes;
131 *responseLoc = response;
135 /// This method is used to create the IPv4 dev_addr structure.
136 /// TODO: Remove in future. Temporary helper function.
137 /// Builds a socket interface address using IP address and port number
138 static OCStackResult OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
139 uint16_t port, OCDevAddr *ipAddr)
142 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
143 return OC_STACK_INVALID_PARAM;
150 *((uint16_t*)&(ipAddr->addr[4])) = port;
155 //-----------------------------------------------------------------------------
156 // Internal API function
157 //-----------------------------------------------------------------------------
159 // This internal function is called to update the stack with the status of
160 // observers and communication failures
161 OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
163 OCStackResult result = OC_STACK_ERROR;
164 ResourceObserver * observer = NULL;
165 OCEntityHandlerRequest ehRequest = {};
169 case OC_OBSERVER_NOT_INTERESTED:
170 OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
171 observer = GetObserverUsingToken (token);
174 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
175 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
176 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
177 if(result != OC_STACK_OK)
181 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
183 //observer is not observing anymore
184 result = DeleteObserverUsingToken (token);
185 if(result == OC_STACK_OK)
187 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
191 result = OC_STACK_OK;
192 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
195 case OC_OBSERVER_STILL_INTERESTED:
196 //observer is still interested
197 OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
198 notifications, reset the failedCount"));
199 observer = GetObserverUsingToken (token);
202 observer->forceHighQos = 0;
203 observer->failedCommCount = 0;
204 result = OC_STACK_OK;
208 result = OC_STACK_OBSERVER_NOT_FOUND;
211 case OC_OBSERVER_FAILED_COMM:
212 //observer is not reachable
213 OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
214 observer = GetObserverUsingToken (token);
217 if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
219 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
220 OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
221 NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
222 if(result != OC_STACK_OK)
224 return OC_STACK_ERROR;
226 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
227 //observer is unreachable
228 result = DeleteObserverUsingToken (token);
229 if(result == OC_STACK_OK)
231 OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
235 result = OC_STACK_OK;
236 OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
241 observer->failedCommCount++;
242 result = OC_STACK_CONTINUE;
244 observer->forceHighQos = 1;
245 OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
249 OC_LOG(ERROR, TAG, PCF("Unknown status"));
250 result = OC_STACK_ERROR;
256 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
258 OCStackResult ret = OC_STACK_ERROR;
266 ret = OC_STACK_RESOURCE_CREATED;
269 ret = OC_STACK_RESOURCE_DELETED;
272 ret = OC_STACK_INVALID_QUERY;
275 ret = OC_STACK_INVALID_OPTION;
278 ret = OC_STACK_NO_RESOURCE;
286 OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
288 OCStackResult ret = OC_STACK_OK;
293 *caConType = CA_ETHERNET;
296 *caConType = CA_WIFI;
305 // Currently OC_ALL represents WIFI and ETHERNET
306 // Add other connectivity types as they are enabled in future
307 *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
310 ret = OC_STACK_INVALID_PARAM;
316 OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
318 OCStackResult ret = OC_STACK_OK;
323 *ocConType = OC_ETHERNET;
326 *ocConType = OC_WIFI;
335 ret = OC_STACK_INVALID_PARAM;
341 // update response.addr appropriately from endPoint.addressInfo
342 OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
344 OCStackResult ret = OC_STACK_ERROR;
345 static OCDevAddr address = {};
347 char * savePtr = NULL;
348 char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
351 ret = OC_STACK_NO_MEMORY;
354 memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
355 strlen(endPoint->addressInfo.IP.ipAddress) + 1);
357 // Grabs the first three numbers from the IPv4 address and replaces dots
358 for(int i=0; i<4; i++)
360 tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
364 ret = OC_STACK_ERROR;
367 address.addr[i] = atoi(tok);
370 memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
374 response->addr = &address;
375 ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
379 OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
386 void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
389 char * savePtr = NULL;
390 // The format of the payload is {"oc":[%u:%u:%s]}
391 // %u : sequence number,
393 // %s : Resource Type (Optional)
394 tok = strtok_r(payload, "[:]}", &savePtr);
395 payload[strlen(payload)] = ':';
396 tok = strtok_r(NULL, "[:]}", &savePtr);
397 payload[strlen((char *)payload)] = ':';
398 *seqNum = (uint32_t) atoi(tok);
400 tok = strtok_r(NULL, "[:]}", &savePtr);
401 *maxAge = (uint32_t) atoi(tok);
402 tok = strtok_r(NULL, "[:]}",&savePtr);
406 *resType = (char *)OCMalloc(strlen(tok));
411 payload[strlen((char *)payload)] = ':';
412 strcpy(*resType, tok);
413 OC_LOG_V(DEBUG, TAG, "resourceTypeName %s", *resType);
415 payload[strlen((char *)payload)] = ']';
418 OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
419 const CAResponseInfo_t* responseInfo)
421 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
422 ClientCB * cbNode = NULL;
423 char *resourceTypeName = NULL;
424 OCClientResponse response;
425 OCStackResult result = OC_STACK_ERROR;
426 uint32_t lowerBound = 0;
427 uint32_t higherBound = 0;
430 char *fullUri = NULL;
431 char *ipAddress = NULL;
432 int presenceSubscribe = 0;
433 int multicastPresenceSubscribe = 0;
435 if (responseInfo->result != CA_SUCCESS)
437 OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
438 return OC_STACK_ERROR;
441 fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
445 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
446 result = OC_STACK_NO_MEMORY;
450 size_t addressLen = strlen(endPoint->addressInfo.IP.ipAddress);
451 ipAddress = (char *) OCMalloc(addressLen + 1);
453 if(NULL == ipAddress)
455 OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
456 result = OC_STACK_NO_MEMORY;
460 strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress, addressLen);
461 ipAddress[addressLen] = '\0';
463 snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
466 cbNode = GetClientCB(NULL, NULL, fullUri);
470 presenceSubscribe = 1;
474 snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
475 cbNode = GetClientCB(NULL, NULL, fullUri);
478 multicastPresenceSubscribe = 1;
482 if(!presenceSubscribe && !multicastPresenceSubscribe)
484 OC_LOG(ERROR, TAG, PCF("Received a presence notification, but no callback, ignoring"));
488 // No payload to the application in case of presence
489 response.resJSONPayload = NULL;
490 response.result = OC_STACK_OK;
492 result = UpdateResponseAddr(&response, endPoint);
493 if(result != OC_STACK_OK)
498 if(responseInfo->info.payload)
500 parsePresencePayload(responseInfo->info.payload,
501 &(response.sequenceNumber),
506 if(presenceSubscribe)
508 if(cbNode->sequenceNumber == response.sequenceNumber)
510 OC_LOG(INFO, TAG, PCF("===============No presence change"));
515 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
516 response.result = OC_STACK_PRESENCE_STOPPED;
519 OCFree(cbNode->presence->timeOut);
520 OCFree(cbNode->presence);
521 cbNode->presence = NULL;
526 if(!cbNode->presence)
528 cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
529 if(!(cbNode->presence))
531 OC_LOG(ERROR, TAG, PCF("Could not allocate memory for cbNode->presence"));
532 result = OC_STACK_NO_MEMORY;
536 VERIFY_NON_NULL_V(cbNode->presence);
537 cbNode->presence->timeOut = NULL;
538 cbNode->presence->timeOut = (uint32_t *)
539 OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
540 if(!(cbNode->presence->timeOut)){
542 PCF("Could not allocate memory for cbNode->presence->timeOut"));
543 OCFree(cbNode->presence);
544 result = OC_STACK_NO_MEMORY;
549 OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
550 cbNode->presence->TTL = maxAge;
551 for(int index = 0; index < PresenceTimeOutSize; index++)
553 lowerBound = GetTime(PresenceTimeOut[index]/ 100.0f*cbNode->presence->TTL);
554 higherBound = GetTime(PresenceTimeOut[index + 1]/100.0f*cbNode->presence->TTL);
555 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
556 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout %d", lowerBound);
557 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
558 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry %d",
559 cbNode->presence->timeOut[index]);
561 cbNode->presence->TTLlevel = 0;
562 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
565 OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
566 cbNode->sequenceNumber = response.sequenceNumber;
568 // Ensure that a filter is actually applied.
569 if(resourceTypeName && cbNode->filterResourceType)
571 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
580 // This is the multicast case
582 OCMulticastNode* mcNode = NULL;
583 mcNode = GetMCPresenceNode(fullUri);
587 if(mcNode->nonce == response.sequenceNumber)
589 OC_LOG(INFO, TAG, PCF("No presence change (Multicast)"));
592 mcNode->nonce = response.sequenceNumber;
596 OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
597 response.result = OC_STACK_PRESENCE_STOPPED;
602 uint32_t uriLen = strlen(fullUri);
603 char* uri = (char *) OCMalloc(uriLen + 1);
606 memcpy(uri, fullUri, (uriLen + 1));
611 PCF("No Memory for URI to store in the presence node"));
612 result = OC_STACK_NO_MEMORY;
615 result = AddMCPresenceNode(&mcNode, uri, response.sequenceNumber);
616 if(result == OC_STACK_NO_MEMORY)
619 PCF("No Memory for Multicast Presence Node"));
620 result = OC_STACK_NO_MEMORY;
626 // Ensure that a filter is actually applied.
627 if(resourceTypeName && cbNode->filterResourceType)
629 if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
636 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
638 if (cbResult == OC_STACK_DELETE_TRANSACTION)
640 FindAndDeleteClientCB(cbNode);
646 OCFree(resourceTypeName);
651 //This function will be called back by CA layer when a response is received
652 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
654 OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
658 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
662 if(NULL == responseInfo)
664 OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
668 if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
670 HandlePresenceResponse(endPoint, responseInfo);
674 ClientCB *cbNode = GetClientCB(&(responseInfo->info.token), NULL, NULL);
678 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
679 OCClientResponse response;
681 OCStackResult result = UpdateResponseAddr(&response, endPoint);
682 if(result != OC_STACK_OK)
684 OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
688 response.result = CAToOCStackResult(responseInfo->result);
689 response.resJSONPayload = responseInfo->info.payload;
690 response.numRcvdVendorSpecificHeaderOptions = 0;
691 if(responseInfo->info.options && responseInfo->info.numOptions > 0)
694 //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
695 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
697 memcpy (&(response.sequenceNumber),
698 &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
699 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
704 response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
707 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
709 OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
713 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
715 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
716 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
719 if (cbNode->callBack(cbNode->context,cbNode->handle, &response)
720 == OC_STACK_DELETE_TRANSACTION)
722 FindAndDeleteClientCB(cbNode);
725 OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
726 OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
729 //This function will be called back by CA layer when a request is received
730 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
732 OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
735 OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
741 OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
745 OCStackResult requestResult = OC_STACK_ERROR;
747 if(myStackMode == OC_CLIENT)
749 //TODO: should the client be responding to requests?
753 OCServerProtocolRequest serverRequest = {};
755 OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
757 char * newUri = NULL;
759 getQueryFromUri(endPoint->resourceUri, &query, &newUri);
760 OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
761 OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
762 if(strlen(newUri) < MAX_URI_LENGTH)
765 memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
769 OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
775 if(strlen((char*)query) < MAX_QUERY_LENGTH)
777 memcpy (&(serverRequest.query), query, strlen((char*)query));
781 OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
785 //copy request payload
786 if (requestInfo->info.payload)
788 size_t payloadLen = strlen(requestInfo->info.payload);
789 serverRequest.reqTotalSize = payloadLen + 1;
790 memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
795 serverRequest.reqTotalSize = 1;
796 serverRequest.reqJSONPayload[0] = '\0';
799 switch (requestInfo->method)
803 serverRequest.method = OC_REST_GET;
808 serverRequest.method = OC_REST_PUT;
813 serverRequest.method = OC_REST_POST;
818 serverRequest.method = OC_REST_DELETE;
823 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
828 OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
829 OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
831 serverRequest.requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
833 if (!serverRequest.requestToken)
835 OC_LOG(FATAL, TAG, "Server Request Token is NULL");
838 memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
840 if (requestInfo->info.type == CA_MSG_CONFIRM)
842 serverRequest.qos = OC_HIGH_QOS;
844 else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
846 serverRequest.qos = OC_LOW_QOS;
848 else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
850 // TODO-CA: Need to handle this
852 else if (requestInfo->info.type == CA_MSG_RESET)
854 // TODO-CA: Need to handle this
856 // CA does not need the following 3 fields
857 serverRequest.coapID = 0;
858 serverRequest.delayedResNeeded = 0;
859 serverRequest.secured = endPoint->isSecured;
862 serverRequest.addressInfo = endPoint->addressInfo;
863 serverRequest.connectivityType = endPoint->connectivityType;
865 // copy vendor specific header options
866 // TODO-CA: CA is including non-vendor header options as well, like observe.
867 // Need to filter those out
868 uint8_t tempNum = (requestInfo->info.numOptions);
869 GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
870 if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
873 PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
874 OCFree(serverRequest.requestToken);
877 serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
878 if (serverRequest.numRcvdVendorSpecificHeaderOptions)
880 memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
881 sizeof(CAHeaderOption_t)*tempNum);
884 requestResult = HandleStackRequests (&serverRequest);
885 if(requestResult != OC_STACK_OK)
887 OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
889 OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
892 //This function will be called back by occoap layer when a request is received
893 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
895 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
896 OCStackResult result = OC_STACK_ERROR;
897 ResourceHandling resHandling;
898 OCResource *resource;
901 OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
902 return OC_STACK_INVALID_PARAM;
905 OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
908 OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
909 result = AddServerRequest(&request, protocolRequest->coapID,
910 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
911 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
912 protocolRequest->observationOption, protocolRequest->qos,
913 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
914 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
915 protocolRequest->resourceUrl,protocolRequest->reqTotalSize,
916 &protocolRequest->addressInfo, protocolRequest->connectivityType);
917 if (OC_STACK_OK != result)
919 OC_LOG(ERROR, TAG, PCF("Error adding server request"));
925 OC_LOG(ERROR, TAG, PCF("Out of Memory"));
926 return OC_STACK_NO_MEMORY;
929 if(!protocolRequest->reqMorePacket)
931 request->requestComplete = 1;
937 PCF("This is either a repeated Server Request or blocked Server Request"));
940 if(request->requestComplete)
942 OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
943 result = DetermineResourceHandling (request, &resHandling, &resource);
944 if (result == OC_STACK_OK)
946 result = ProcessRequest(resHandling, resource, request);
950 result = OC_STACK_ERROR;
955 OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
956 result = OC_STACK_CONTINUE;
961 int ParseIPv4Address(char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
965 uint8_t dotCount = 0;
969 /* search for scheme */
971 if (!isdigit((char) *ipAddrStr))
973 coap = OC_COAP_SCHEME;
974 while (*coap && tolower(*itr) == *coap)
983 if (isdigit(*ipAddrStr))
986 ipAddr[index] += *ipAddrStr - '0';
988 else if (*ipAddrStr == '.')
1000 if(*ipAddrStr == ':')
1004 if (isdigit(*ipAddrStr))
1007 *port += *ipAddrStr - '0';
1028 //-----------------------------------------------------------------------------
1029 // Private internal function prototypes
1030 //-----------------------------------------------------------------------------
1032 static OCDoHandle GenerateInvocationHandle();
1033 static OCStackResult initResources();
1034 static void insertResource(OCResource *resource);
1035 static OCResource *findResource(OCResource *resource);
1036 static void insertResourceType(OCResource *resource,
1037 OCResourceType *resourceType);
1038 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
1040 static void insertResourceInterface(OCResource *resource,
1041 OCResourceInterface *resourceInterface);
1042 static OCResourceInterface *findResourceInterfaceAtIndex(
1043 OCResourceHandle handle, uint8_t index);
1044 static void deleteResourceType(OCResourceType *resourceType);
1045 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
1046 static void deleteResourceElements(OCResource *resource);
1047 static OCStackResult deleteResource(OCResource *resource);
1048 static void deleteAllResources();
1049 static void incrementSequenceNumber(OCResource * resPtr);
1050 static OCStackResult verifyUriQueryLength(const char * inputUri,
1052 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
1053 OCStackResult getResourceType(const char * query, char** resourceType);
1054 static CAResult_t OCSelectNetwork();
1056 //-----------------------------------------------------------------------------
1058 //-----------------------------------------------------------------------------
1061 * Initialize the OC Stack. Must be called prior to starting the stack.
1064 * IP Address of host device
1066 * Port of host device
1068 * Host device is client, server, or client-server
1071 * OC_STACK_OK - no errors
1072 * OC_STACK_ERROR - stack init error
1074 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1076 OCStackResult result = OC_STACK_ERROR;
1077 CAResult_t caResult = CA_STATUS_OK;
1078 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
1081 if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
1083 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1084 return OC_STACK_ERROR;
1089 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
1093 caResult = CAInitialize();
1094 if(caResult == CA_STATUS_OK)
1096 caResult = OCSelectNetwork();
1100 OC_LOG(ERROR, TAG, PCF("Failed to initialize the CA Layer."));
1101 return CAResultToOCResult(caResult);
1104 if(caResult == CA_STATUS_OK)
1106 CARegisterHandler(HandleCARequests, HandleCAResponses);
1108 OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
1109 stackState = OC_STACK_INITIALIZED;
1110 result = OC_STACK_OK;
1114 caResult = CAStartDiscoveryServer();
1115 OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
1118 caResult = CAStartListeningServer();
1119 OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
1121 case OC_CLIENT_SERVER:
1122 caResult = CAStartListeningServer();
1123 if(caResult == CA_STATUS_OK)
1125 caResult = CAStartDiscoveryServer();
1127 OC_LOG(INFO, TAG, PCF("Client-server mode"));
1130 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
1131 return OC_STACK_ERROR;
1137 result = CAResultToOCResult(caResult);
1141 OC_LOG(ERROR, TAG, PCF("Failed to initialize any transports."));
1142 return CAResultToOCResult(caResult);
1146 defaultDeviceHandler = NULL;
1148 #if defined(__WITH_DTLS__)
1149 caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
1150 result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
1151 #endif // (__WITH_DTLS__)
1153 #ifdef WITH_PRESENCE
1154 PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
1155 #endif // WITH_PRESENCE
1157 if (result == OC_STACK_OK)
1159 stackState = OC_STACK_INITIALIZED;
1161 // Initialize resource
1162 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
1164 result = initResources();
1166 if(result != OC_STACK_OK)
1168 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
1174 * Stop the OC stack. Use for a controlled shutdown.
1176 * OC_STACK_OK - no errors
1177 * OC_STACK_ERROR - stack not initialized
1179 OCStackResult OCStop()
1181 OCStackResult result = OC_STACK_ERROR;
1183 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
1185 if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1187 OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
1190 else if (stackState != OC_STACK_INITIALIZED)
1192 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
1193 return OC_STACK_ERROR;
1196 stackState = OC_STACK_UNINIT_IN_PROGRESS;
1198 #ifdef WITH_PRESENCE
1199 // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1200 // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1201 presenceResource.presenceTTL = 0;
1202 #endif // WITH_PRESENCE
1204 // Free memory dynamically allocated for resources
1205 deleteAllResources();
1208 //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
1209 result = OC_STACK_OK;
1211 if (result == OC_STACK_OK)
1213 // Remove all observers
1214 DeleteObserverList();
1215 // Remove all the client callbacks
1216 DeleteClientCBList();
1217 stackState = OC_STACK_UNINITIALIZED;
1218 result = OC_STACK_OK;
1220 stackState = OC_STACK_INITIALIZED;
1221 result = OC_STACK_ERROR;
1224 // Deinit security blob
1225 DeinitOCSecurityInfo();
1227 if (result != OC_STACK_OK) {
1228 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1235 * Map OCQualityOfService to CAMessageType
1237 * @param OCQualityOfService - Input qos.
1239 * Returns CA message type for a given qos.
1241 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1246 return CA_MSG_CONFIRM;
1251 return CA_MSG_NONCONFIRM;
1256 * Verify the lengths of the URI and the query separately
1258 * @param inputUri - Input URI and query.
1259 * @param uriLen - The length of the initial URI with query.
1261 * Note: The '?' that appears after the URI is not considered as
1262 * a part of the query.
1264 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1268 query = strchr (inputUri, '?');
1272 if((query - inputUri) > MAX_URI_LENGTH)
1274 return OC_STACK_INVALID_URI;
1277 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1279 return OC_STACK_INVALID_QUERY;
1282 else if(uriLen > MAX_URI_LENGTH)
1284 return OC_STACK_INVALID_URI;
1290 * Discover or Perform requests on a specified resource
1291 * (specified by that Resource's respective URI).
1293 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
1295 * @param method - @ref OCMethod to perform on the resource
1296 * @param requiredUri - URI of the resource to interact with
1297 * @param referenceUri - URI of the reference resource
1298 * @param request - JSON encoded request
1299 * @param qos - quality of service
1300 * @param cbData - struct that contains asynchronous callback function that is invoked
1301 * by the stack when discovery or resource interaction is complete
1302 * @param options - The address of an array containing the vendor specific header
1303 * header options to be sent with the request
1304 * @param numOptions - Number of vendor specific header options to be included
1307 * OC_STACK_OK - no errors
1308 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1309 * OC_STACK_INVALID_METHOD - invalid resource method
1310 * OC_STACK_INVALID_URI - invalid required or reference URI
1312 * Note: when using multicast, the required URI should not contain IP address.
1313 * Instead, it just contains the URI to the resource such as "/oc/core".
1315 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1316 const char *referenceUri, const char *request, OCConnectivityType conType,
1317 OCQualityOfService qos, OCCallbackData *cbData,
1318 OCHeaderOption * options, uint8_t numOptions)
1320 OCStackResult result = OC_STACK_ERROR;
1321 ClientCB *clientCB = NULL;
1322 char * requestUri = NULL;
1323 char * resourceType = NULL;
1324 char * query = NULL;
1325 char * newUri = (char *)requiredUri;
1326 (void) referenceUri;
1327 CARemoteEndpoint_t* endpoint = NULL;
1328 CAResult_t caResult;
1329 CAToken_t token = NULL;
1330 OCDoHandle resHandle = NULL;
1331 CAInfo_t requestData ={};
1332 CARequestInfo_t requestInfo ={};
1333 CAGroupEndpoint_t grpEnd = {};
1335 // To track if memory is allocated for additional header options
1337 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1339 // Validate input parameters
1340 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1341 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1343 //TODO ("Need to form the final query by concatenating require and reference URI's");
1344 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1346 uint16_t uriLen = strlen(requiredUri);
1348 // ToDo: We should also check if the requiredUri has a mutlicast address,
1349 // then qos has to be OC_Low_QOS
1355 case OC_REST_DELETE:
1356 case OC_REST_OBSERVE:
1357 case OC_REST_OBSERVE_ALL:
1358 case OC_REST_CANCEL_OBSERVE:
1360 #ifdef WITH_PRESENCE
1361 case OC_REST_PRESENCE:
1365 result = OC_STACK_INVALID_METHOD;
1369 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1374 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1376 result = OC_STACK_INVALID_PARAM;
1380 #ifdef WITH_PRESENCE
1381 if(method == OC_REST_PRESENCE)
1383 result = getQueryFromUri(requiredUri, &query, &newUri);
1386 result = getResourceType((char *) query, &resourceType);
1389 OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1393 OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
1398 OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
1400 if(result != OC_STACK_OK)
1405 #endif // WITH_PRESENCE
1407 requestUri = (char *) OCMalloc(uriLen + 1);
1410 memcpy(requestUri, newUri, (uriLen + 1));
1414 result = OC_STACK_NO_MEMORY;
1418 resHandle = GenerateInvocationHandle();
1421 result = OC_STACK_NO_MEMORY;
1428 case OC_REST_OBSERVE:
1429 case OC_REST_OBSERVE_ALL:
1430 case OC_REST_CANCEL_OBSERVE:
1432 requestInfo.method = CA_GET;
1437 requestInfo.method = CA_PUT;
1442 requestInfo.method = CA_POST;
1445 case OC_REST_DELETE:
1447 requestInfo.method = CA_DELETE;
1450 #ifdef WITH_PRESENCE
1451 case OC_REST_PRESENCE:
1453 // Replacing method type with GET because "presence"
1454 // is a stack layer only implementation.
1455 requestInfo.method = CA_GET;
1460 result = OC_STACK_INVALID_METHOD;
1464 //High QoS is not supported
1465 if(qos == OC_HIGH_QOS)
1467 result = OC_STACK_INVALID_PARAM;
1472 caResult = CAGenerateToken(&token);
1473 if (caResult != CA_STATUS_OK)
1475 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1476 CADestroyToken(token);
1480 requestData.type = qualityOfServiceToMessageType(qos);
1481 requestData.token = token;
1482 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1484 result = CreateObserveHeaderOption (&(requestData.options), options,
1485 numOptions, OC_OBSERVE_REGISTER);
1486 if (result != OC_STACK_OK)
1490 requestData.numOptions = numOptions + 1;
1494 requestData.options = (CAHeaderOption_t*)options;
1495 requestData.numOptions = numOptions;
1497 requestData.payload = (char *)request;
1499 requestInfo.info = requestData;
1501 CAConnectivityType_t caConType;
1503 result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
1504 if (result != OC_STACK_OK)
1506 OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
1511 if(conType == OC_ALL)
1513 grpEnd.connectivityType = caConType;
1515 grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
1516 if(!grpEnd.resourceUri)
1518 result = OC_STACK_NO_MEMORY;
1521 strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
1523 caResult = CASendRequestToAll(&grpEnd, &requestInfo);
1527 caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
1529 if (caResult != CA_STATUS_OK)
1531 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1535 caResult = CASendRequest(endpoint, &requestInfo);
1538 if (caResult != CA_STATUS_OK)
1540 OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1544 if((result = AddClientCB(&clientCB, cbData, &token, &resHandle, method,
1545 requestUri, resourceType)) != OC_STACK_OK)
1547 result = OC_STACK_NO_MEMORY;
1553 *handle = resHandle;
1557 if(newUri != requiredUri)
1561 if (result != OC_STACK_OK)
1563 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1564 FindAndDeleteClientCB(clientCB);
1567 CADestroyRemoteEndpoint(endpoint);
1568 OCFree(grpEnd.resourceUri);
1569 if (requestData.options && requestData.numOptions > 0)
1571 if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
1573 OCFree(requestData.options);
1580 * Cancel a request associated with a specific @ref OCDoResource invocation.
1582 * @param handle - Used to identify a specific OCDoResource invocation.
1583 * @param qos - used to specify Quality of Service (read below for more info)
1584 * @param options- used to specify vendor specific header options when sending
1585 * explicit observe cancellation
1586 * @param numOptions- Number of header options to be included
1589 * OC_STACK_OK - No errors; Success
1590 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
1592 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1596 * This ftn is implemented one of two ways in the case of observation:
1598 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1599 * Remove the callback associated on client side.
1600 * When the next notification comes in from server,
1601 * reply with RESET message to server.
1602 * Keep in mind that the server will react to RESET only
1603 * if the last notification was sent ans CON
1605 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1606 * and it is associated with an observe request
1607 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1608 * Send CON Observe request to server with
1609 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1610 * Remove the callback associated on client side.
1612 OCStackResult ret = OC_STACK_OK;
1613 CARemoteEndpoint_t* endpoint = NULL;
1614 CAResult_t caResult= CA_STATUS_OK;
1615 CAInfo_t requestData = {};
1616 CARequestInfo_t requestInfo = {};
1620 return OC_STACK_INVALID_PARAM;
1623 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1625 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1629 switch (clientCB->method)
1631 case OC_REST_OBSERVE:
1632 case OC_REST_OBSERVE_ALL:
1633 //TODO-CA : Why CA_WIFI alone?
1634 caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
1636 if (caResult != CA_STATUS_OK)
1638 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1639 return OC_STACK_ERROR;
1642 memset(&requestData, 0, sizeof(CAInfo_t));
1643 requestData.type = qualityOfServiceToMessageType(qos);
1644 requestData.token = clientCB->token;
1645 if (CreateObserveHeaderOption (&(requestData.options),
1646 options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
1648 return OC_STACK_ERROR;
1650 requestData.numOptions = numOptions + 1;
1651 requestInfo.method = CA_GET;
1652 requestInfo.info = requestData;
1654 caResult = CASendRequest(endpoint, &requestInfo);
1655 if (caResult != CA_STATUS_OK)
1657 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1659 if(caResult == CA_STATUS_OK)
1663 #ifdef WITH_PRESENCE
1664 case OC_REST_PRESENCE:
1665 FindAndDeleteClientCB(clientCB);
1669 return OC_STACK_INVALID_METHOD;
1672 CADestroyRemoteEndpoint(endpoint);
1673 if (requestData.numOptions > 0)
1675 OCFree(requestData.options);
1681 #ifdef WITH_PRESENCE
1682 OCStackResult OCProcessPresence()
1684 OCStackResult result = OC_STACK_OK;
1685 uint8_t ipAddr[4] = { 0 };
1688 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1689 ClientCB* cbNode = NULL;
1691 OCClientResponse clientResponse ={};
1692 OCResponse * response = NULL;
1693 OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1695 LL_FOREACH(cbList, cbNode)
1697 if(OC_REST_PRESENCE == cbNode->method)
1699 if(cbNode->presence)
1701 uint32_t now = GetTime(0);
1702 OC_LOG_V(DEBUG, TAG, "this TTL level %d",
1703 cbNode->presence->TTLlevel);
1704 OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
1707 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1712 if(cbNode->presence->TTLlevel < PresenceTimeOutSize)
1714 OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
1715 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1718 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1720 OC_LOG(DEBUG, TAG, PCF("No more timeout ticks"));
1721 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1723 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1726 clientResponse.sequenceNumber = 0;
1727 clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
1728 clientResponse.addr = (OCDevAddr *) &dst;
1729 clientResponse.resJSONPayload = NULL;
1731 result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1732 &cbNode->token, &clientResponse, NULL);
1733 if(result != OC_STACK_OK)
1738 // Increment the TTLLevel (going to a next state), so we don't keep
1739 // sending presence notification to client.
1740 cbNode->presence->TTLlevel++;
1741 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
1742 cbNode->presence->TTLlevel);
1746 result = OC_STACK_INVALID_IP;
1750 cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
1751 if (cbResult == OC_STACK_DELETE_TRANSACTION)
1753 FindAndDeleteClientCB(cbNode);
1757 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1759 CAResult_t caResult = CA_STATUS_OK;
1760 CARemoteEndpoint_t* endpoint = NULL;
1761 CAInfo_t requestData ={};
1762 CARequestInfo_t requestInfo = {};
1764 OC_LOG(DEBUG, TAG, PCF("time to test server presence"));
1766 //TODO-CA : Why CA_WIFI alone?
1767 caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
1770 if (caResult != CA_STATUS_OK)
1772 OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1776 requestData.type = CA_MSG_NONCONFIRM;
1777 requestData.token = cbNode->token;
1779 requestInfo.method = CA_GET;
1780 requestInfo.info = requestData;
1782 caResult = CASendRequest(endpoint, &requestInfo);
1784 if (caResult != CA_STATUS_OK)
1786 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
1790 cbNode->presence->TTLlevel++;
1791 OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
1792 cbNode->presence->TTLlevel);
1798 if (result != OC_STACK_OK)
1800 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1804 #endif // WITH_PRESENCE
1807 * Called in main loop of OC client or server. Allows low-level processing of
1811 * OC_STACK_OK - no errors
1812 * OC_STACK_ERROR - stack process error
1814 OCStackResult OCProcess()
1816 #ifdef WITH_PRESENCE
1817 OCProcessPresence();
1819 CAHandleRequestResponse();
1824 #ifdef WITH_PRESENCE
1826 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
1827 * presence notifications to clients via multicast. Once this API has been called with a success,
1828 * clients may query for this server's presence and this server's stack will respond via multicast.
1830 * Server can call this function when it comes online for the first time, or when it comes back
1831 * online from offline mode, or when it re enters network.
1833 * @param ttl - Time To Live in seconds
1834 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
1837 * OC_STACK_OK - No errors; Success
1839 OCStackResult OCStartPresence(const uint32_t ttl)
1841 OCChangeResourceProperty(
1842 &(((OCResource *)presenceResource.handle)->resourceProperties),
1847 presenceResource.presenceTTL = ttl;
1850 if(OC_PRESENCE_UNINITIALIZED == presenceState)
1852 presenceState = OC_PRESENCE_INITIALIZED;
1854 CAAddress_t addressInfo;
1855 strncpy(addressInfo.IP.ipAddress, OC_MULTICAST_IP, CA_IPADDR_SIZE);
1856 addressInfo.IP.port = 5683;
1858 //TODO make sure there is no memory leak here since another copy
1859 //of token is being created inside AddObserver
1860 CAToken_t caToken = NULL;
1861 CAResult_t caResult = CAGenerateToken(&caToken);
1862 if (caResult != CA_STATUS_OK)
1864 OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1865 CADestroyToken(caToken);
1866 return OC_STACK_ERROR;
1869 CAConnectivityType_t connType;
1870 OCToCAConnectivityType(OC_ALL, &connType );
1871 AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
1872 (OCResource *)presenceResource.handle, OC_LOW_QOS,
1873 &addressInfo, connType);
1876 // Each time OCStartPresence is called
1877 // a different random 32-bit integer number is used
1878 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1880 return SendPresenceNotification(NULL);
1884 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
1885 * presence notifications to clients via multicast. Once this API has been called with a success,
1886 * this server's stack will not respond to clients querying for this server's presence.
1888 * Server can call this function when it is terminating, going offline, or when going
1889 * away from network.
1892 * OC_STACK_OK - No errors; Success
1894 OCStackResult OCStopPresence()
1896 OCStackResult result = OC_STACK_ERROR;
1898 if(presenceResource.handle)
1900 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1903 // make resource inactive
1904 result = OCChangeResourceProperty(
1905 &(((OCResource *) presenceResource.handle)->resourceProperties),
1908 if(result != OC_STACK_OK)
1911 PCF("Changing the presence resource properties to ACTIVE not successful"));
1915 return SendStopNotification();
1920 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
1922 defaultDeviceHandler = entityHandler;
1927 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
1929 OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
1931 if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
1933 return SaveDeviceInfo(deviceInfo);
1937 return OC_STACK_ERROR;
1944 * @param handle - pointer to handle to newly created resource. Set by ocstack.
1945 * Used to refer to resource
1946 * @param resourceTypeName - name of resource type. Example: "core.led"
1947 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
1948 * @param uri - URI of the resource. Example: "/a/led"
1949 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1950 * NULL for default entity handler
1951 * @param resourceProperties - properties supported by resource.
1952 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
1955 * OC_STACK_OK - no errors
1956 * OC_STACK_ERROR - stack process error
1958 OCStackResult OCCreateResource(OCResourceHandle *handle,
1959 const char *resourceTypeName,
1960 const char *resourceInterfaceName,
1961 const char *uri, OCEntityHandler entityHandler,
1962 uint8_t resourceProperties)
1965 OCResource *pointer = NULL;
1968 OCStackResult result = OC_STACK_ERROR;
1970 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
1972 if(myStackMode == OC_CLIENT)
1974 return OC_STACK_INVALID_PARAM;
1976 // Validate parameters
1977 if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
1979 OC_LOG(ERROR, TAG, PCF("URI is invalid"));
1980 return OC_STACK_INVALID_URI;
1982 // Is it presented during resource discovery?
1983 if (!handle || !resourceTypeName)
1985 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
1986 return OC_STACK_INVALID_PARAM;
1989 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
1991 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
1994 // Make sure resourceProperties bitmask has allowed properties specified
1995 if (resourceProperties
1996 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
1997 OC_LOG(ERROR, TAG, PCF("Invalid property"));
1998 return OC_STACK_INVALID_PARAM;
2001 // If the headResource is NULL, then no resources have been created...
2002 pointer = headResource;
2005 // At least one resources is in the resource list, so we need to search for
2006 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
2009 if (strcmp(uri, pointer->uri) == 0)
2011 OC_LOG(ERROR, TAG, PCF("URI already in use"));
2012 return OC_STACK_INVALID_PARAM;
2014 pointer = pointer->next;
2017 // Create the pointer and insert it into the resource list
2018 pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
2021 result = OC_STACK_NO_MEMORY;
2024 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2026 insertResource(pointer);
2029 size = strlen(uri) + 1;
2030 str = (char *) OCMalloc(size);
2033 result = OC_STACK_NO_MEMORY;
2036 strncpy(str, uri, size);
2039 // Set properties. Set OC_ACTIVE
2040 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2043 // Add the resourcetype to the resource
2044 result = BindResourceTypeToResource(pointer, resourceTypeName);
2045 if (result != OC_STACK_OK)
2047 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2051 // Add the resourceinterface to the resource
2052 result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2053 if (result != OC_STACK_OK)
2055 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2059 // If an entity handler has been passed, attach it to the newly created
2060 // resource. Otherwise, set the default entity handler.
2063 pointer->entityHandler = entityHandler;
2067 pointer->entityHandler = defaultResourceEHandler;
2071 result = OC_STACK_OK;
2073 #ifdef WITH_PRESENCE
2074 if(presenceResource.handle)
2076 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2077 SendPresenceNotification(pointer->rsrcType);
2081 if (result != OC_STACK_OK)
2083 // Deep delete of resource and other dynamic elements that it contains
2084 deleteResource(pointer);
2093 * Create a resource. with host ip address for remote resource
2095 * @param handle - pointer to handle to newly created resource. Set by ocstack.
2096 * Used to refer to resource
2097 * @param resourceTypeName - name of resource type. Example: "core.led"
2098 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
2099 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
2100 * @param uri - URI of the resource. Example: "/a/led"
2101 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2102 * NULL for default entity handler
2103 * @param resourceProperties - properties supported by resource.
2104 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
2107 * OC_STACK_OK - no errors
2108 * OC_STACK_ERROR - stack process error
2111 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
2112 const char *resourceTypeName,
2113 const char *resourceInterfaceName,
2116 OCEntityHandler entityHandler,
2117 uint8_t resourceProperties)
2124 return OC_STACK_INVALID_PARAM;
2127 OCStackResult result = OC_STACK_ERROR;
2129 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
2130 uri, entityHandler, resourceProperties);
2132 if (result != OC_STACK_ERROR)
2135 size = strlen(host) + 1;
2136 str = (char *) OCMalloc(size);
2139 return OC_STACK_NO_MEMORY;
2141 strncpy(str, host, size);
2142 ((OCResource *) *handle)->host = str;
2149 * Add a resource to a collection resource.
2151 * @param collectionHandle - handle to the collection resource
2152 * @param resourceHandle - handle to resource to be added to the collection resource
2155 * OC_STACK_OK - no errors
2156 * OC_STACK_ERROR - stack process error
2157 * OC_STACK_INVALID_PARAM - invalid collectionhandle
2159 OCStackResult OCBindResource(
2160 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2162 OCResource *resource = NULL;
2165 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2167 // Validate parameters
2168 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2169 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2170 // Container cannot contain itself
2171 if (collectionHandle == resourceHandle)
2173 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2174 return OC_STACK_INVALID_PARAM;
2177 // Use the handle to find the resource in the resource linked list
2178 resource = findResource((OCResource *) collectionHandle);
2181 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2182 return OC_STACK_INVALID_PARAM;
2185 // Look for an open slot to add add the child resource.
2186 // If found, add it and return success
2187 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2189 if (!resource->rsrcResources[i])
2191 resource->rsrcResources[i] = (OCResource *) resourceHandle;
2192 OC_LOG(INFO, TAG, PCF("resource bound"));
2194 #ifdef WITH_PRESENCE
2195 if(presenceResource.handle)
2197 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2198 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2206 // Unable to add resourceHandle, so return error
2207 return OC_STACK_ERROR;
2211 * Remove a resource from a collection resource.
2213 * @param collectionHandle - handle to the collection resource
2214 * @param resourceHandle - handle to resource to be added to the collection resource
2217 * OC_STACK_OK - no errors
2218 * OC_STACK_ERROR - stack process error
2219 * OC_STACK_INVALID_PARAM - invalid collectionHandle
2221 OCStackResult OCUnBindResource(
2222 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2224 OCResource *resource = NULL;
2227 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2229 // Validate parameters
2230 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2231 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2232 // Container cannot contain itself
2233 if (collectionHandle == resourceHandle)
2235 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2236 return OC_STACK_INVALID_PARAM;
2239 // Use the handle to find the resource in the resource linked list
2240 resource = findResource((OCResource *) collectionHandle);
2243 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2244 return OC_STACK_INVALID_PARAM;
2247 // Look for an open slot to add add the child resource.
2248 // If found, add it and return success
2249 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2251 if (resourceHandle == resource->rsrcResources[i])
2253 resource->rsrcResources[i] = (OCResource *) NULL;
2254 OC_LOG(INFO, TAG, PCF("resource unbound"));
2256 // Send notification when resource is unbounded successfully.
2257 #ifdef WITH_PRESENCE
2258 if(presenceResource.handle)
2260 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2261 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
2268 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2270 // Unable to add resourceHandle, so return error
2271 return OC_STACK_ERROR;
2274 OCStackResult BindResourceTypeToResource(OCResource* resource,
2275 const char *resourceTypeName)
2277 OCResourceType *pointer = NULL;
2280 OCStackResult result = OC_STACK_ERROR;
2282 OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
2284 // Validate parameters
2285 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2286 // TODO: Does resource attribute resentation really have to be maintained in stack?
2287 // Is it presented during resource discovery?
2289 //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
2291 // Create the resourcetype and insert it into the resource list
2292 pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
2295 result = OC_STACK_NO_MEMORY;
2299 // Set the resourceTypeName
2300 size = strlen(resourceTypeName) + 1;
2301 str = (char *) OCMalloc(size);
2304 result = OC_STACK_NO_MEMORY;
2307 strncpy(str, resourceTypeName, size);
2308 pointer->resourcetypename = str;
2310 insertResourceType(resource, pointer);
2311 result = OC_STACK_OK;
2314 if (result != OC_STACK_OK)
2323 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2324 const char *resourceInterfaceName)
2326 OCResourceInterface *pointer = NULL;
2329 OCStackResult result = OC_STACK_ERROR;
2331 OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
2333 // Validate parameters
2334 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2336 //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
2338 // Create the resourceinterface and insert it into the resource list
2339 pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
2342 result = OC_STACK_NO_MEMORY;
2346 // Set the resourceinterface name
2347 size = strlen(resourceInterfaceName) + 1;
2348 str = (char *) OCMalloc(size);
2351 result = OC_STACK_NO_MEMORY;
2354 strncpy(str, resourceInterfaceName, size);
2355 pointer->name = str;
2357 // Bind the resourceinterface to the resource
2358 insertResourceInterface(resource, pointer);
2360 result = OC_STACK_OK;
2363 if (result != OC_STACK_OK)
2373 * Bind a resourcetype to a resource.
2375 * @param handle - handle to the resource
2376 * @param resourceTypeName - name of resource type. Example: "core.led"
2379 * OC_STACK_OK - no errors
2380 * OC_STACK_ERROR - stack process error
2382 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2383 const char *resourceTypeName)
2386 OCStackResult result = OC_STACK_ERROR;
2387 OCResource *resource = NULL;
2389 // Make sure resource exists
2390 resource = findResource((OCResource *) handle);
2393 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2394 return OC_STACK_ERROR;
2397 // call internal function
2398 result = BindResourceTypeToResource(resource, resourceTypeName);
2400 #ifdef WITH_PRESENCE
2401 if(presenceResource.handle)
2403 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2404 SendPresenceNotification(resource->rsrcType);
2412 * Bind a resourceinterface to a resource.
2414 * @param handle - handle to the resource
2415 * @param resourceInterfaceName - name of resource interface. Example: "oc.mi.b"
2418 * OC_STACK_OK - no errors
2419 * OC_STACK_ERROR - stack process error
2422 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2423 const char *resourceInterfaceName)
2426 OCStackResult result = OC_STACK_ERROR;
2427 OCResource *resource = NULL;
2429 // Make sure resource exists
2430 resource = findResource((OCResource *) handle);
2433 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2434 return OC_STACK_ERROR;
2437 // call internal function
2438 result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2440 #ifdef WITH_PRESENCE
2441 if(presenceResource.handle)
2443 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2444 SendPresenceNotification(resource->rsrcType);
2452 * Get the number of resources that have been created in the stack.
2454 * @param numResources - pointer to count variable
2457 * OC_STACK_OK - no errors
2458 * OC_STACK_ERROR - stack process error
2461 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
2463 OCResource *pointer = headResource;
2465 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2466 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2470 *numResources = *numResources + 1;
2471 pointer = pointer->next;
2477 * Get a resource handle by index.
2479 * @param index - index of resource, 0 to Count - 1
2482 * Resource handle - if found
2483 * NULL - if not found
2485 OCResourceHandle OCGetResourceHandle(uint8_t index)
2487 OCResource *pointer = headResource;
2489 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2491 // Iterate through the list
2492 for( uint8_t i = 0; i < index && pointer; ++i)
2494 pointer = pointer->next;
2496 return (OCResourceHandle) pointer;
2500 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
2503 * @param handle - handle of resource to be deleted
2506 * OC_STACK_OK - no errors
2507 * OC_STACK_ERROR - stack process error
2508 * OC_STACK_NO_RESOURCE - resource not found
2509 * OC_STACK_INVALID_PARAM - invalid param
2511 OCStackResult OCDeleteResource(OCResourceHandle handle)
2513 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2517 OC_LOG(ERROR, TAG, PCF("Invalid param"));
2518 return OC_STACK_INVALID_PARAM;
2521 OCResource *resource = findResource((OCResource *) handle);
2522 if (resource == NULL)
2524 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2525 return OC_STACK_NO_RESOURCE;
2528 if (deleteResource((OCResource *) handle) != OC_STACK_OK)
2530 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2531 return OC_STACK_ERROR;
2538 * Get the URI of the resource specified by handle.
2540 * @param handle - handle of resource
2542 * URI string - if resource found
2543 * NULL - resource not found
2545 const char *OCGetResourceUri(OCResourceHandle handle)
2547 OCResource *resource = NULL;
2548 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2550 resource = findResource((OCResource *) handle);
2553 return resource->uri;
2555 return (const char *) NULL;
2559 * Get the properties of the resource specified by handle.
2560 * NOTE: that after a resource is created, the OC_ACTIVE property is set
2561 * for the resource by the stack.
2563 * @param handle - handle of resource
2565 * OCResourceProperty Bitmask
2566 * -1 if resource is not found
2568 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
2570 OCResource *resource = NULL;
2571 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2573 resource = findResource((OCResource *) handle);
2576 return resource->resourceProperties;
2578 return (OCResourceProperty)-1;
2582 * Get the number of resource types of the resource.
2584 * @param handle - handle of resource
2585 * @param numResourceTypes - pointer to count variable
2588 * OC_STACK_OK - no errors
2589 * OC_STACK_ERROR - stack process error
2591 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2592 uint8_t *numResourceTypes)
2594 OCResource *resource = NULL;
2595 OCResourceType *pointer = NULL;
2597 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2598 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2599 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2601 *numResourceTypes = 0;
2603 resource = findResource((OCResource *) handle);
2606 pointer = resource->rsrcType;
2609 *numResourceTypes = *numResourceTypes + 1;
2610 pointer = pointer->next;
2617 * Get name of resource type of the resource.
2619 * @param handle - handle of resource
2620 * @param index - index of resource, 0 to Count - 1
2623 * resource type name - if resource found
2624 * NULL - resource not found
2626 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
2628 OCResourceType *resourceType = NULL;
2630 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2632 resourceType = findResourceTypeAtIndex(handle, index);
2635 return resourceType->resourcetypename;
2637 return (const char *) NULL;
2643 * Get the number of resource interfaces of the resource.
2645 * @param handle - handle of resource
2646 * @param numResources - pointer to count variable
2649 * OC_STACK_OK - no errors
2650 * OC_STACK_ERROR - stack process error
2652 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2653 uint8_t *numResourceInterfaces)
2655 OCResourceInterface *pointer = NULL;
2656 OCResource *resource = NULL;
2658 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2660 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2661 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2663 *numResourceInterfaces = 0;
2664 resource = findResource((OCResource *) handle);
2667 pointer = resource->rsrcInterface;
2670 *numResourceInterfaces = *numResourceInterfaces + 1;
2671 pointer = pointer->next;
2678 * Get name of resource interface of the resource.
2680 * @param handle - handle of resource
2681 * @param index - index of resource, 0 to Count - 1
2684 * resource interface name - if resource found
2685 * NULL - resource not found
2687 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
2689 OCResourceInterface *resourceInterface = NULL;
2691 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2693 resourceInterface = findResourceInterfaceAtIndex(handle, index);
2694 if (resourceInterface)
2696 return resourceInterface->name;
2698 return (const char *) NULL;
2702 * Get resource handle from the collection resource by index.
2704 * @param collectionHandle - handle of collection resource
2705 * @param index - index of contained resource, 0 to Count - 1
2708 * handle to resource - if resource found
2709 * NULL - resource not found
2711 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2714 OCResource *resource = NULL;
2716 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2718 if (index >= MAX_CONTAINED_RESOURCES)
2723 resource = findResource((OCResource *) collectionHandle);
2729 return resource->rsrcResources[index];
2733 * Bind an entity handler to the resource.
2735 * @param handle - handle to the resource that the contained resource is to be bound
2736 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2738 * OC_STACK_OK - no errors
2739 * OC_STACK_ERROR - stack process error
2741 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2742 OCEntityHandler entityHandler)
2744 OCResource *resource = NULL;
2746 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2748 // Validate parameters
2749 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2751 // Use the handle to find the resource in the resource linked list
2752 resource = findResource((OCResource *)handle);
2755 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2756 return OC_STACK_ERROR;
2760 resource->entityHandler = entityHandler;
2762 #ifdef WITH_PRESENCE
2763 if(presenceResource.handle)
2765 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2766 SendPresenceNotification(resource->rsrcType);
2774 * Get the entity handler for a resource.
2776 * @param handle - handle of resource
2779 * entity handler - if resource found
2780 * NULL - resource not found
2782 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
2784 OCResource *resource = NULL;
2786 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2788 // Use the handle to find the resource in the resource linked list
2789 resource = findResource((OCResource *)handle);
2792 OC_LOG(ERROR, TAG, PCF("Resource not found"));
2797 return resource->entityHandler;
2800 void incrementSequenceNumber(OCResource * resPtr)
2802 // Increment the sequence number
2803 resPtr->sequenceNum += 1;
2804 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2806 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2812 * Notify Presence subscribers that a resource has been modified
2814 * @param resourceType - Handle to the resourceType linked list of resource
2815 * that was modified.
2816 * @param qos - Quality Of Service
2819 * OC_STACK_OK - no errors
2820 * OC_STACK_ERROR - stack process error
2822 #ifdef WITH_PRESENCE
2825 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2827 OCResource *resPtr = NULL;
2828 OCStackResult result = OC_STACK_ERROR;
2829 OCMethod method = OC_REST_PRESENCE;
2830 uint32_t maxAge = 0;
2831 resPtr = findResource((OCResource *) presenceResource.handle);
2834 return OC_STACK_NO_RESOURCE;
2837 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2839 maxAge = presenceResource.presenceTTL;
2841 result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2848 * Send Stop Notification to Presence subscribers
2851 * OC_STACK_OK - no errors
2852 * OC_STACK_ERROR - stack process error
2856 OCStackResult SendStopNotification()
2858 OCResource *resPtr = NULL;
2859 OCStackResult result = OC_STACK_ERROR;
2860 OCMethod method = OC_REST_PRESENCE;
2861 resPtr = findResource((OCResource *) presenceResource.handle);
2864 return OC_STACK_NO_RESOURCE;
2867 // maxAge is 0. ResourceType is NULL.
2868 result = SendAllObserverNotification(method, resPtr, 0, NULL, OC_LOW_QOS);
2873 #endif // WITH_PRESENCE
2875 * Notify observers that an observed value has changed.
2877 * @param handle - handle of resource
2880 * OC_STACK_OK - no errors
2881 * OC_STACK_NO_RESOURCE - invalid resource handle
2882 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2884 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
2887 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2889 OCResource *resPtr = NULL;
2890 OCStackResult result = OC_STACK_ERROR;
2891 OCMethod method = OC_REST_NOMETHOD;
2892 uint32_t maxAge = 0;
2894 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2895 #ifdef WITH_PRESENCE
2896 if(handle == presenceResource.handle)
2900 #endif // WITH_PRESENCE
2901 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2903 // Verify that the resource exists
2904 resPtr = findResource ((OCResource *) handle);
2907 return OC_STACK_NO_RESOURCE;
2911 //only increment in the case of regular observing (not presence)
2912 incrementSequenceNumber(resPtr);
2913 method = OC_REST_OBSERVE;
2914 maxAge = MAX_OBSERVE_AGE;
2915 #ifdef WITH_PRESENCE
2916 result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
2918 result = SendAllObserverNotification (method, resPtr, maxAge, qos);
2925 OCNotifyListOfObservers (OCResourceHandle handle,
2926 OCObservationId *obsIdList,
2927 uint8_t numberOfIds,
2928 const char *notificationJSONPayload,
2929 OCQualityOfService qos)
2931 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
2933 OCResource *resPtr = NULL;
2934 //TODO: we should allow the server to define this
2935 uint32_t maxAge = MAX_OBSERVE_AGE;
2937 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2938 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
2939 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
2941 // Verify that the resource exists
2942 resPtr = findResource ((OCResource *) handle);
2943 if (NULL == resPtr || myStackMode == OC_CLIENT)
2945 return OC_STACK_NO_RESOURCE;
2949 incrementSequenceNumber(resPtr);
2951 return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
2952 notificationJSONPayload, maxAge, qos));
2956 * Send a response to a request.
2957 * The response can be a regular, slow, or block (i.e. a response that
2958 * is too large to be sent in a single PDU and must span multiple transmissions)
2960 * @param response - pointer to structure that contains response parameters
2963 * OC_STACK_OK - No errors; Success
2964 * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
2965 * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
2966 * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
2967 * persistent response buffer is necessary
2969 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
2971 OCStackResult result = OC_STACK_ERROR;
2972 OCServerRequest *serverRequest = NULL;
2974 OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
2976 // Validate input parameters
2977 VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
2978 VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
2980 // TODO: Placeholder for creating a response entry when implementing
2981 // block transfer feature
2983 // If a response payload is present, check if block transfer is required
2984 if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
2985 (const char *)ehResponse->payload, ehResponse->payloadSize))
2987 OC_LOG(INFO, TAG, PCF("Block transfer required"));
2989 // Persistent response buffer is needed for block transfer
2990 if (!ehResponse->persistentBufferFlag)
2992 OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
2993 return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
2995 // TODO: Placeholder for block transfer handling
2996 // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
2997 // when implementing the block transfer feature
3002 // Get pointer to request info
3003 serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3006 result = serverRequest->ehResponseHandler(ehResponse);
3013 * Cancel a response. Applies to a block response
3015 * @param responseHandle - response handle set by stack in OCServerResponse after
3016 * OCDoResponse is called
3019 * OC_STACK_OK - No errors; Success
3020 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
3022 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
3024 OCStackResult result = OC_STACK_NOTIMPL;
3026 OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
3028 // TODO: validate response handle
3033 //-----------------------------------------------------------------------------
3034 // Private internal function definitions
3035 //-----------------------------------------------------------------------------
3037 * Generate handle of OCDoResource invocation for callback management.
3039 static OCDoHandle GenerateInvocationHandle()
3041 OCDoHandle handle = NULL;
3042 // Generate token here, it will be deleted when the transaction is deleted
3043 handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3046 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3051 #ifdef WITH_PRESENCE
3052 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3053 OCResourceProperty resourceProperties, uint8_t enable)
3055 if (resourceProperties
3056 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3058 OC_LOG(ERROR, TAG, PCF("Invalid property"));
3059 return OC_STACK_INVALID_PARAM;
3063 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3067 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3074 * Initialize resource data structures, variables, etc.
3076 OCStackResult initResources()
3078 OCStackResult result = OC_STACK_OK;
3079 // Init application resource vars
3080 headResource = NULL;
3081 tailResource = NULL;
3082 // Init Virtual Resources
3083 #ifdef WITH_PRESENCE
3084 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
3085 //presenceResource.token = OCGenerateCoAPToken();
3086 result = OCCreateResource(&presenceResource.handle,
3087 OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3092 //make resource inactive
3093 result = OCChangeResourceProperty(
3094 &(((OCResource *) presenceResource.handle)->resourceProperties),
3101 * Add a resource to the end of the linked list of resources.
3103 * @param resource - resource to be added
3105 void insertResource(OCResource *resource)
3107 OCResource *pointer = NULL;
3109 if (!headResource) {
3110 headResource = resource;
3111 tailResource = resource;
3115 tailResource->next = resource;
3116 tailResource = resource;
3118 resource->next = NULL;
3122 * Find a resource in the linked list of resources.
3124 * @param resource - resource to be found
3126 * NULL - resource not found
3127 * pointer to resource - pointer to resource that was found in the linked list
3129 OCResource *findResource(OCResource *resource)
3131 OCResource *pointer = headResource;
3135 if (pointer == resource)
3139 pointer = pointer->next;
3144 void deleteAllResources()
3146 OCResource *pointer = headResource;
3147 OCResource *temp = NULL;
3151 temp = pointer->next;
3152 #ifdef WITH_PRESENCE
3153 if(pointer != (OCResource *) presenceResource.handle)
3155 #endif // WITH_PRESENCE
3156 deleteResource(pointer);
3157 #ifdef WITH_PRESENCE
3159 #endif // WITH_PRESENCE
3163 #ifdef WITH_PRESENCE
3164 // Ensure that the last resource to be deleted is the presence resource. This allows for all
3165 // presence notification attributed to their deletion to be processed.
3166 deleteResource((OCResource *) presenceResource.handle);
3167 #endif // WITH_PRESENCE
3171 * Delete the resource from the linked list.
3173 * @param resource - resource to be deleted
3175 * OC_STACK_ERROR - error
3176 * OC_STACK_OK - success
3178 OCStackResult deleteResource(OCResource *resource)
3180 OCResource *prev = NULL;
3181 OCResource *temp = NULL;
3183 temp = headResource;
3186 if (temp == resource)
3188 // Invalidate all Resource Properties.
3189 resource->resourceProperties = (OCResourceProperty) 0;
3190 #ifdef WITH_PRESENCE
3191 if(resource != (OCResource *) presenceResource.handle)
3193 #endif // WITH_PRESENCE
3194 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3195 #ifdef WITH_PRESENCE
3198 if(presenceResource.handle)
3200 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3201 if(resource != (OCResource *) presenceResource.handle)
3203 SendPresenceNotification(resource->rsrcType);
3207 SendPresenceNotification(NULL);
3211 // Only resource in list.
3212 if (temp == headResource && temp == tailResource)
3214 headResource = NULL;
3215 tailResource = NULL;
3218 else if (temp == headResource)
3220 headResource = temp->next;
3223 else if (temp == tailResource)
3225 tailResource = prev;
3226 tailResource->next = NULL;
3230 prev->next = temp->next;
3233 deleteResourceElements(temp);
3244 return OC_STACK_ERROR;
3248 * Delete all of the dynamically allocated elements that were created for the resource.
3250 * @param resource - specified resource
3252 void deleteResourceElements(OCResource *resource)
3260 OCFree(resource->uri);
3262 // Delete resourcetype linked list
3263 deleteResourceType(resource->rsrcType);
3265 // Delete resourceinterface linked list
3266 deleteResourceInterface(resource->rsrcInterface);
3270 * Delete all of the dynamically allocated elements that were created for the resource type.
3272 * @param resourceType - specified resource type
3274 void deleteResourceType(OCResourceType *resourceType)
3276 OCResourceType *pointer = resourceType;
3277 OCResourceType *next = NULL;
3281 next = pointer->next;
3282 OCFree(pointer->resourcetypename);
3289 * Delete all of the dynamically allocated elements that were created for the resource interface.
3291 * @param resourceInterface - specified resource interface
3293 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3295 OCResourceInterface *pointer = resourceInterface;
3296 OCResourceInterface *next = NULL;
3300 next = pointer->next;
3301 OCFree(pointer->name);
3308 * Insert a resource type into a resource's resource type linked list.
3310 * @param resource - resource where resource type is to be inserted
3311 * @param resourceType - resource type to be inserted
3313 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3315 OCResourceType *pointer = NULL;
3317 if (resource && !resource->rsrcType)
3319 resource->rsrcType = resourceType;
3325 pointer = resource->rsrcType;
3329 pointer = resourceType;
3331 while (pointer->next)
3333 pointer = pointer->next;
3335 pointer->next = resourceType;
3337 resourceType->next = NULL;
3341 * Get a resource type at the specified index within a resource.
3343 * @param handle - handle of resource
3344 * @param index - index of resource type
3347 * resourcetype - if found
3350 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3352 OCResource *resource = NULL;
3353 OCResourceType *pointer = NULL;
3355 // Find the specified resource
3356 resource = findResource((OCResource *) handle);
3362 // Make sure a resource has a resourcetype
3363 if (!resource->rsrcType)
3368 // Iterate through the list
3369 pointer = resource->rsrcType;
3370 for(uint8_t i = 0; i< index && pointer; ++i)
3372 pointer = pointer->next;
3378 * Finds a resource type in an OCResourceType link-list.
3380 * @param resourceTypeList - the link-list to be searched through
3381 * @param resourceTypeName - the key to search for
3384 * resourceType that matches the key (ie. resourceTypeName)
3385 * NULL - either an invalid parameter or this function was unable to find the key.
3387 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3389 if(resourceTypeList && resourceTypeName)
3391 OCResourceType * rtPointer = resourceTypeList;
3392 while(resourceTypeName && rtPointer)
3394 if(rtPointer->resourcetypename &&
3395 strcmp(resourceTypeName, (const char *)
3396 (rtPointer->resourcetypename)) == 0)
3400 rtPointer = rtPointer->next;
3407 * Insert a resource interface into a resource's resource interface linked list.
3409 * @param resource - resource where resource interface is to be inserted
3410 * @param resourceInterface - resource interface to be inserted
3412 void insertResourceInterface(OCResource *resource,
3413 OCResourceInterface *resourceInterface)
3415 OCResourceInterface *pointer = NULL;
3416 if (!resource->rsrcInterface)
3418 resource->rsrcInterface = resourceInterface;
3422 pointer = resource->rsrcInterface;
3423 while (pointer->next)
3425 pointer = pointer->next;
3427 pointer->next = resourceInterface;
3429 resourceInterface->next = NULL;
3433 * Get a resource interface at the specified index within a resource.
3435 * @param handle - handle of resource
3436 * @param index - index of resource interface
3439 * resourceinterface - if found
3442 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3445 OCResource *resource = NULL;
3446 OCResourceInterface *pointer = NULL;
3448 // Find the specified resource
3449 resource = findResource((OCResource *) handle);
3455 // Make sure a resource has a resourceinterface
3456 if (!resource->rsrcInterface)
3461 // Iterate through the list
3462 pointer = resource->rsrcInterface;
3464 for (uint8_t i = 0; i < index && pointer; ++i)
3466 pointer = pointer->next;
3472 * Determine if a request/response must be sent in a block transfer because it is too large to be
3473 * sent in a single PDU. This function can be used for either a request or a response
3475 * @param request - NULL or pointer to request
3476 * @param response - NULL or pointer to response
3477 * @param size - 0 or size of the request/response. If 0, strlen is used for determining
3478 * the length of the request/response
3481 * 0 - packet transfer NOT required (i.e. normal request/response)
3482 * 1 - packet transfer required (i.e. block transfer needed)
3484 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
3488 // Determine if we are checking a request or a response
3491 // If size is greater than 0, use it for the request size value, otherwise
3492 // assume request is null terminated and use strlen for size value
3493 if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
3500 // If size is greater than 0, use it for the response size value, otherwise
3501 // assume response is null terminated and use strlen for size value
3502 if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
3511 * Retrieves a resource type based upon a query contains only just one
3512 * resource attribute (and that has to be of type "rt").
3514 * @remark This API malloc's memory for the resource type. Do not malloc resourceType
3515 * before passing in.
3517 * @param query - The query part of the URI
3518 * @param resourceType - The resource type to be populated; pass by reference.
3521 * OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3522 * OC_STACK_OK - Success
3524 OCStackResult getResourceType(const char * query, char** resourceType)
3528 return OC_STACK_INVALID_PARAM;
3531 OCStackResult result = OC_STACK_ERROR;
3533 if(strncmp(query, "rt=", 3) == 0)
3535 *resourceType = (char *) OCMalloc(strlen(query)-3 + 1);
3538 result = OC_STACK_NO_MEMORY;
3541 strcpy((char *)*resourceType, ((const char *)&query[3]));
3542 result = OC_STACK_OK;
3548 OCStackResult getQueryFromUri(const char * uri, char** query, char ** newURI)
3552 return OC_STACK_INVALID_URI;
3554 if(!query || !newURI)
3556 return OC_STACK_INVALID_PARAM;
3558 char * leftToken = NULL;
3559 char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3564 strcpy(tempURI, uri);
3565 char* strTokPtr = NULL;
3566 leftToken = strtok_r(tempURI, "?", &strTokPtr);
3568 //TODO-CA: This could be simplified. Clean up required.
3569 while(leftToken != NULL)
3571 if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
3573 *query = (char *) OCMalloc(strlen(leftToken) + 1);
3579 strcpy(*query, &leftToken[0]);
3582 leftToken = strtok_r(NULL, "?", &strTokPtr);
3590 return OC_STACK_NO_MEMORY;
3593 const ServerID OCGetServerInstanceID(void)
3595 static bool generated = false;
3596 static ServerID sid;
3602 sid = OCGetRandom();
3607 const char* OCGetServerInstanceIDString(void)
3609 // max printed length of a base 10
3610 // uint32 is 10 characters, so 11 includes null.
3611 // This will change as the representation gets switched
3613 static char buffer[11];
3615 if (snprintf(buffer, sizeof(buffer),"%u", OCGetServerInstanceID()) < 0)
3623 /// Retrieve the IPv4 address embedded inside OCDev address data structure
3624 int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
3625 uint8_t *c, uint8_t *d )
3627 if ( !ipAddr || !a || !b || !c || !d )
3629 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
3630 return OC_STACK_INVALID_PARAM;
3633 *a = ipAddr->addr[0];
3634 *b = ipAddr->addr[1];
3635 *c = ipAddr->addr[2];
3636 *d = ipAddr->addr[3];
3642 /// Retrieve the IPv4 address embedded inside OCDev address data structure
3643 int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
3645 if ( !ipAddr || !port )
3647 OC_LOG(FATAL, TAG, PCF("Invalid argument"));
3648 return OC_STACK_INVALID_PARAM;
3651 *port = *((uint16_t*)&ipAddr->addr[4]);
3657 * Attempts to initialize every network interface that the CA Layer might have compiled in.
3659 * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork
3660 * return something other than @ref CA_STATUS_OK, then this function fails.
3663 * CA_STATUS_OK - Success
3664 * CA_NOT_SUPPORTED or CA_STATUS_FAILED - None of the transports successfully initialized.
3666 CAResult_t OCSelectNetwork()
3668 CAResult_t retResult = CA_STATUS_FAILED;
3669 CAResult_t caResult = CA_STATUS_OK;
3671 CAConnectivityType_t connTypes[] = {
3676 int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
3678 for(int i = 0; i<numConnTypes; i++)
3680 // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
3681 if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
3683 caResult = CASelectNetwork(connTypes[i]);
3684 if(caResult == CA_STATUS_OK)
3686 retResult = CA_STATUS_OK;
3691 if(retResult != CA_STATUS_OK)
3693 return caResult; // Returns error of appropriate transport that failed fatally.
3700 * Takes a @ref CAResult_t and converts it to a similar or equivalent @ref OCStackResult value.
3702 * @return @ref OCStackResult - The equivalent or similar result code to the in-param caResult.
3704 OCStackResult CAResultToOCResult(CAResult_t caResult)
3710 case CA_STATUS_INVALID_PARAM:
3711 return OC_STACK_INVALID_PARAM;
3712 case CA_ADAPTER_NOT_ENABLED:
3713 return OC_STACK_ADAPTER_NOT_ENABLED;
3714 case CA_SERVER_STARTED_ALREADY:
3716 case CA_SERVER_NOT_STARTED:
3717 return OC_STACK_ERROR;
3718 case CA_DESTINATION_NOT_REACHABLE:
3719 return OC_STACK_COMM_ERROR;
3720 case CA_SOCKET_OPERATION_FAILED:
3721 return OC_STACK_COMM_ERROR;
3722 case CA_SEND_FAILED:
3723 return OC_STACK_COMM_ERROR;
3724 case CA_RECEVIE_FAILED:
3725 return OC_STACK_COMM_ERROR;
3726 case CA_MEMORY_ALLOC_FAILED:
3727 return OC_STACK_NO_MEMORY;
3728 case CA_REQUEST_TIMEOUT:
3729 return OC_STACK_TIMEOUT;
3730 case CA_DESTINATION_DISCONNECTED:
3731 return OC_STACK_COMM_ERROR;
3732 case CA_STATUS_FAILED:
3733 return OC_STACK_ERROR;
3734 case CA_NOT_SUPPORTED:
3735 return OC_STACK_NOTIMPL;
3737 return OC_STACK_ERROR;