Removed ocsocket
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocstack.c
index e6080c9..da84aa0 100644 (file)
 //-----------------------------------------------------------------------------
 // Includes
 //-----------------------------------------------------------------------------
+#define _POSIX_C_SOURCE 200112L
+#include <string.h>
+#include <ctype.h>
+
 #include "ocstack.h"
 #include "ocstackinternal.h"
 #include "ocresourcehandler.h"
 #include "occlientcb.h"
 #include "ocobserve.h"
 #include "ocrandom.h"
-#include "debug.h"
-#include "occoap.h"
 #include "ocmalloc.h"
 #include "ocserverrequest.h"
+#include "ocsecurityinternal.h"
+
+#include "cacommon.h"
+#include "cainterface.h"
+
+#ifdef WITH_ARDUINO
+#include "Time.h"
+#else
+#include <sys/time.h>
+#endif
+#include "coap_time.h"
+#include "utlist.h"
+#include "pdu.h"
+
+#ifndef ARDUINO
+#include <arpa/inet.h>
+#endif
+
 
 //-----------------------------------------------------------------------------
 // Typedefs
 //-----------------------------------------------------------------------------
 typedef enum {
-    OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
+    OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
 } OCStackState;
-
 #ifdef WITH_PRESENCE
 typedef enum {
     OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
@@ -61,20 +80,77 @@ uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
 
 OCMode myStackMode;
 OCDeviceEntityHandler defaultDeviceHandler;
+OCStackResult getQueryFromUri(const char * uri, unsigned char** resourceType, char ** newURI);
 
 //-----------------------------------------------------------------------------
 // Macros
 //-----------------------------------------------------------------------------
 #define TAG  PCF("OCStack")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+            {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
              TAG, PCF(#arg " is NULL")); return (retVal); } }
+#define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
+    goto exit;} }
 
 //TODO: we should allow the server to define this
 #define MAX_OBSERVE_AGE (0x2FFFFUL)
-//-----------------------------------------------------------------------------
-// Externs
-//-----------------------------------------------------------------------------
-extern void DeinitOCSecurityInfo();
+
+//=============================================================================
+// Helper Functions
+//=============================================================================
+static uint32_t GetTime(float afterSeconds)
+{
+    coap_tick_t now;
+    coap_ticks(&now);
+    return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
+}
+
+static OCStackResult FormOCResponse(OCResponse * * responseLoc,
+                                    ClientCB * cbNode,
+                                    uint32_t maxAge,
+                                    unsigned char * fullUri,
+                                    unsigned char * rcvdUri,
+                                    CAToken_t * rcvdToken,
+                                    OCClientResponse * clientResponse,
+                                    unsigned char * bufRes)
+{
+    OCResponse * response = (OCResponse *) OCMalloc(sizeof(OCResponse));
+    if (!response)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+    response->cbNode = cbNode;
+    response->maxAge = maxAge;
+    response->fullUri = fullUri;
+    response->rcvdUri = rcvdUri;
+    response->rcvdToken = rcvdToken;
+    response->clientResponse = clientResponse;
+    response->bufRes = bufRes;
+
+    *responseLoc = response;
+    return OC_STACK_OK;
+}
+
+/// This method is used to create the IPv4 dev_addr structure.
+/// TODO: Remove in future. Temporary helper function.
+/// Builds a socket interface address using IP address and port number
+static int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+        uint16_t port, OCDevAddr *ipAddr)
+{
+    if ( !ipAddr ) {
+        OC_LOG(FATAL, TAG, "Invalid argument");
+        return 1;
+    }
+
+    ipAddr->addr[0] = a;
+    ipAddr->addr[1] = b;
+    ipAddr->addr[2] = c;
+    ipAddr->addr[3] = d;
+    *((uint16_t*)&(ipAddr->addr[4])) = port;
+
+    return 0;
+}
 
 //-----------------------------------------------------------------------------
 // Internal API function
@@ -82,7 +158,7 @@ extern void DeinitOCSecurityInfo();
 
 // This internal function is called to update the stack with the status of
 // observers and communication failures
-OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
+OCStackResult OCStackFeedBack(CAToken_t * token, uint8_t status)
 {
     OCStackResult result = OC_STACK_ERROR;
     ResourceObserver * observer = NULL;
@@ -120,7 +196,7 @@ OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
         //observer is still interested
         OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
                 notifications, reset the failedCount"));
-        observer = GetObserverUsingToken(token);
+        observer = GetObserverUsingToken (token);
         if(observer)
         {
             observer->forceHighQos = 0;
@@ -135,7 +211,7 @@ OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
     case OC_OBSERVER_FAILED_COMM:
         //observer is not reachable
         OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
-        observer = GetObserverUsingToken(token);
+        observer = GetObserverUsingToken (token);
         if(observer)
         {
             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
@@ -177,14 +253,636 @@ OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
     return result;
 }
 
+OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    switch(caCode)
+    {
+        case CA_SUCCESS:
+            ret = OC_STACK_OK;
+            break;
+        case CA_CREATED:
+            ret = OC_STACK_RESOURCE_CREATED;
+            break;
+        case CA_DELETED:
+            ret = OC_STACK_RESOURCE_DELETED;
+            break;
+        case CA_BAD_REQ:
+            ret = OC_STACK_INVALID_QUERY;
+            break;
+        case CA_BAD_OPT:
+            ret = OC_STACK_INVALID_OPTION;
+            break;
+        case CA_NOT_FOUND:
+            ret = OC_STACK_NO_RESOURCE;
+            break;
+        default:
+            break;
+    }
+    return ret;
+}
+
+OCStackResult OCToCAConnectivityType(OCConnectivityType ocConType, CAConnectivityType_t* caConType)
+{
+    OCStackResult ret = OC_STACK_OK;
+
+    switch(ocConType)
+    {
+        case OC_ETHERNET:
+            *caConType = CA_ETHERNET;
+            break;
+        case OC_WIFI:
+            *caConType = CA_WIFI;
+            break;
+        case OC_EDR:
+            *caConType = CA_EDR;
+            break;
+        case OC_LE:
+            *caConType = CA_LE;
+            break;
+        case OC_ALL:
+            // Currently OC_ALL represents WIFI and ETHERNET
+            // Add other connectivity types as they are enabled in future
+            *caConType = (CAConnectivityType_t) (CA_WIFI|CA_ETHERNET);
+            break;
+        default:
+            ret = OC_STACK_INVALID_PARAM;
+            break;
+    }
+    return ret;
+}
+
+OCStackResult CAToOCConnectivityType(CAConnectivityType_t caConType, OCConnectivityType *ocConType)
+{
+    OCStackResult ret = OC_STACK_OK;
+
+    switch(caConType)
+    {
+        case CA_ETHERNET:
+            *ocConType = OC_ETHERNET;
+            break;
+        case CA_WIFI:
+            *ocConType = OC_WIFI;
+            break;
+        case CA_EDR:
+            *ocConType = OC_EDR;
+            break;
+        case CA_LE:
+            *ocConType = OC_LE;
+            break;
+        default:
+            ret = OC_STACK_INVALID_PARAM;
+            break;
+    }
+    return ret;
+}
+
+// update response.addr appropriately from endPoint.addressInfo
+OCStackResult UpdateResponseAddr(OCClientResponse *response, const CARemoteEndpoint_t* endPoint)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    static OCDevAddr address = {0};
+    char * tok = NULL;
+    char * savePtr = NULL;
+    char * cpAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
+    if(!cpAddress)
+    {
+        ret = OC_STACK_NO_MEMORY;
+        goto exit;
+    }
+    memcpy(cpAddress, endPoint->addressInfo.IP.ipAddress,
+            strlen(endPoint->addressInfo.IP.ipAddress) + 1);
+
+    // Grabs the first three numbers from the IPv4 address and replaces dots
+    for(int i=0; i<4; i++)
+    {
+        tok = strtok_r(i==0 ? cpAddress : NULL, ".", &savePtr);
+
+        if(!tok)
+        {
+            ret = OC_STACK_ERROR;
+            goto exit;
+        }
+        address.addr[i] = atoi(tok);
+    }
+
+    memcpy(&address.addr[4], &endPoint->addressInfo.IP.port, sizeof(uint32_t));
+
+    if(response)
+    {
+        response->addr = &address;
+        ret = CAToOCConnectivityType(endPoint->connectivityType, &(response->connType));
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, PCF("OCClientResponse is NULL!"));
+    }
+exit:
+    OCFree(cpAddress);
+    return ret;
+}
+
+void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, char** resType)
+{
+    char * tok = NULL;
+    char * savePtr;
+    // The format of the payload is {"oc":[%u:%u:%s]}
+    // %u : sequence number,
+    // %u : max age
+    // %s : Resource Type (Optional)
+    tok = strtok_r(payload, "[:]}", &savePtr);
+    payload[strlen(payload)] = ':';
+    tok = strtok_r(NULL, "[:]}", &savePtr);
+    payload[strlen((char *)payload)] = ':';
+    *seqNum = (uint32_t) atoi(tok);
+    tok = strtok_r(NULL, "[:]}", &savePtr);
+    *maxAge = (uint32_t) atoi(tok);
+    tok = strtok_r(NULL, "[:]}",&savePtr);
+
+    if(tok)
+    {
+        *resType = (char *)OCMalloc(strlen(tok));
+        if(!*resType)
+        {
+            return;
+        }
+        payload[strlen((char *)payload)] = ':';
+        strcpy(*resType, tok);
+        OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s", *resType);
+    }
+    payload[strlen((char *)payload)] = ']';
+}
+
+OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
+                            const CAResponseInfo_t* responseInfo)
+{
+    OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
+    ClientCB * cbNode = NULL;
+    char *resourceTypeName = NULL;
+    OCClientResponse response;
+    OCStackResult result = OC_STACK_ERROR;
+    uint32_t lowerBound = 0;
+    uint32_t higherBound = 0;
+    uint32_t maxAge = 0;
+
+    char *fullUri = NULL;
+    char *ipAddress = NULL;
+    int presenceSubscribe = 0;
+    int multicastPresenceSubscribe = 0;
+
+    if (responseInfo->result != CA_SUCCESS)
+    {
+        OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
+        return OC_STACK_ERROR;
+    }
+
+    fullUri = (char *) OCMalloc(MAX_URI_LENGTH );
+
+    if(NULL == fullUri)
+    {
+        OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for fullUri"));
+        result = OC_STACK_NO_MEMORY;
+        goto exit;
+    }
+
+    ipAddress = (char *) OCMalloc(strlen(endPoint->addressInfo.IP.ipAddress) + 1);
+
+    if(NULL == ipAddress)
+    {
+        OC_LOG(ERROR, TAG, PCF("Memory could not be allocated for ipAddress"));
+        result = OC_STACK_NO_MEMORY;
+        goto exit;
+    }
+
+    strncpy(ipAddress, endPoint->addressInfo.IP.ipAddress,
+                            strlen(endPoint->addressInfo.IP.ipAddress));
+    ipAddress[strlen(endPoint->addressInfo.IP.ipAddress)] = '\0';
+
+    snprintf(fullUri, MAX_URI_LENGTH, "coap://%s:%u%s", ipAddress, endPoint->addressInfo.IP.port,
+                OC_PRESENCE_URI);
+
+    cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
+
+    if(cbNode)
+    {
+        presenceSubscribe = 1;
+    }
+    else
+    {
+        snprintf(fullUri, MAX_URI_LENGTH, "%s%s", OC_MULTICAST_IP, endPoint->resourceUri);
+        cbNode = GetClientCB(NULL, NULL, (unsigned char *) fullUri);
+        if(cbNode)
+        {
+            multicastPresenceSubscribe = 1;
+        }
+    }
+
+    if(!presenceSubscribe && !multicastPresenceSubscribe)
+    {
+        OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
+                                                ------------ ignoring"));
+        goto exit;
+    }
+
+    // No payload to the application in case of presence
+    response.resJSONPayload = NULL;
+    response.result = OC_STACK_OK;
+
+    result = UpdateResponseAddr(&response, endPoint);
+    if(result != OC_STACK_OK)
+    {
+        goto exit;
+    }
+
+    if(responseInfo->info.payload)
+    {
+        parsePresencePayload(responseInfo->info.payload,
+                                &(response.sequenceNumber),
+                                &maxAge,
+                                &resourceTypeName);
+    }
+
+    if(maxAge == 0)
+    {
+        OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+        response.result = OC_STACK_PRESENCE_STOPPED;
+        if(cbNode->presence)
+        {
+            OCFree(cbNode->presence->timeOut);
+            OCFree(cbNode->presence);
+            cbNode->presence = NULL;
+        }
+    }
+    else if(presenceSubscribe)
+    {
+        if(!cbNode->presence)
+        {
+            cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
+            VERIFY_NON_NULL_V(cbNode->presence);
+            cbNode->presence->timeOut = NULL;
+            cbNode->presence->timeOut = (uint32_t *)
+                    OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
+            if(!(cbNode->presence->timeOut)){
+                OCFree(cbNode->presence);
+                result = OC_STACK_NO_MEMORY;
+            }
+        }
+
+        OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
+        cbNode->presence->TTL = maxAge;
+        for(int index = 0; index < PresenceTimeOutSize; index++)
+        {
+            lowerBound = GetTime(((float)(PresenceTimeOut[index])
+                    /(float)100)*(float)cbNode->presence->TTL);
+            higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
+                    /(float)100)*(float)cbNode->presence->TTL);
+            cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
+            OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
+            OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
+            OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
+                    cbNode->presence->timeOut[index]);
+        }
+        cbNode->presence->TTLlevel = 0;
+        OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+        if(cbNode->sequenceNumber == response.sequenceNumber)
+        {
+            OC_LOG(INFO, TAG, PCF("===============No presence change"));
+            goto exit;
+        }
+        OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
+        cbNode->sequenceNumber = response.sequenceNumber;
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+    else
+    {
+        // This is the multicast case
+
+        OCMulticastNode* mcNode = NULL;
+        mcNode = GetMCPresenceNode((const unsigned char *)fullUri);
+
+        if(mcNode != NULL)
+        {
+            if(mcNode->nonce == response.sequenceNumber)
+            {
+                OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
+                goto exit;
+            }
+            mcNode->nonce = response.sequenceNumber;
+        }
+        else
+        {
+            uint32_t uriLen = strlen((char*)fullUri);
+            unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
+            if(uri)
+            {
+                memcpy(uri, fullUri, (uriLen + 1));
+            }
+            else
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for URI to store in the presence node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            result = AddMCPresenceNode(&mcNode, (unsigned char*) uri, response.sequenceNumber);
+            if(result == OC_STACK_NO_MEMORY)
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for Multicast Presence Node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+        }
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+
+    cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &response);
+
+    if (cbResult == OC_STACK_DELETE_TRANSACTION)
+    {
+        FindAndDeleteClientCB(cbNode);
+    }
+
+exit:
+OCFree(fullUri);
+OCFree(ipAddress);
+OCFree(resourceTypeName);
+return result;
+}
+
+
+//This function will be called back by CA layer when a response is received
+void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
+
+    OCStackApplicationResult appResult = OC_STACK_DELETE_TRANSACTION;
+
+    if(NULL == endPoint)
+    {
+        OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
+        return;
+    }
+
+    if(NULL == responseInfo)
+    {
+        OC_LOG(ERROR, TAG, PCF("responseInfo is NULL"));
+        return;
+    }
+
+    if(strcmp(endPoint->resourceUri, OC_PRESENCE_URI) == 0)
+    {
+        HandlePresenceResponse(endPoint, responseInfo);
+        return;
+    }
+
+    ClientCB *cbNode = GetClientCB((CAToken_t *)&(responseInfo->info.token), NULL, NULL);
+
+    if (cbNode)
+    {
+        OC_LOG(INFO, TAG, PCF("Calling into application address space"));
+        OCClientResponse response;
+
+        OCStackResult result = UpdateResponseAddr(&response, endPoint);
+        if(result != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, PCF("Invalid connectivity type in endpoint"));
+            return;
+        }
+
+        response.result = CAToOCStackResult(responseInfo->result);
+        response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
+        response.numRcvdVendorSpecificHeaderOptions = 0;
+        if(responseInfo->info.numOptions > 0)
+        {
+            int start = 0;
+            //First option always with option ID is OC_COAP_OPTION_OBSERVE if it is available.
+            if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
+            {
+                memcpy (&(response.sequenceNumber),
+                            &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
+                response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
+                start = 1;
+            }
+            else
+            {
+               response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
+            }
+
+            if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
+            {
+                OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
+                return;
+            }
+
+            for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
+            {
+                memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
+                 &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
+            }
+        }
+        appResult = cbNode->callBack(cbNode->context,
+                cbNode->handle, &response);
+        if (appResult == OC_STACK_DELETE_TRANSACTION)
+        {
+            FindAndDeleteClientCB(cbNode);
+        }
+    }
+    OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
+    OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
+}
+
+//This function will be called back by CA layer when a request is received
+void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
+    if(!endPoint)
+    {
+        OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
+        return;
+    }
+
+    if(!requestInfo)
+    {
+        OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
+        return;
+    }
+
+    OCStackResult requestResult = OC_STACK_ERROR;
+
+    if(myStackMode == OC_CLIENT)
+    {
+        //TODO: should the client be responding to requests?
+        return;
+    }
+
+    OCServerProtocolRequest serverRequest = {};
+
+    OC_LOG_V(INFO, TAG, PCF("***** Endpoint URI ***** : %s\n"), (char*)endPoint->resourceUri);
+
+    char * newUri = (char *)endPoint->resourceUri;
+    unsigned char * query = NULL;
+    getQueryFromUri(endPoint->resourceUri, &query, &newUri);
+    OC_LOG_V(INFO, TAG, PCF("**********URI without query ****: %s\n"), newUri);
+    OC_LOG_V(INFO, TAG, PCF("**********Query ****: %s\n"), query);
+    if(strlen(newUri) < MAX_URI_LENGTH)
+    {
+        //copy URI
+        memcpy (&(serverRequest.resourceUrl), newUri, strlen(newUri));
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
+        return;
+    }
+    //copy query
+    if(query)
+    {
+        if(strlen((char*)query) < MAX_QUERY_LENGTH)
+        {
+            memcpy (&(serverRequest.query), query, strlen((char*)query));
+        }
+        else
+        {
+            OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
+            return;
+        }
+    }
+    //copy request payload
+    if (requestInfo->info.payload)
+    {
+        serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
+        memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
+                strlen(requestInfo->info.payload));
+        serverRequest.reqTotalSize = strlen((const char *)requestInfo->info.payload) + 1;
+    }
+    else
+    {
+        serverRequest.reqTotalSize = 1;
+    }
+
+    switch (requestInfo->method)
+    {
+        case CA_GET:
+            {
+                serverRequest.method = OC_REST_GET;
+                break;
+            }
+        case CA_PUT:
+            {
+                serverRequest.method = OC_REST_PUT;
+                break;
+            }
+        case CA_POST:
+            {
+                serverRequest.method = OC_REST_POST;
+                break;
+            }
+        case CA_DELETE:
+            {
+                serverRequest.method = OC_REST_DELETE;
+                break;
+            }
+        default:
+            {
+                OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
+                return;
+            }
+    }
+
+    OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", CA_MAX_TOKEN_LEN);
+    OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token, CA_MAX_TOKEN_LEN);
+
+    serverRequest.requestToken = (CAToken_t)OCCalloc(1, CA_MAX_TOKEN_LEN+1);
+    // Module Name
+    if (!serverRequest.requestToken)
+    {
+        OC_LOG(FATAL, TAG, "Server Request Token is NULL");
+        return;
+    }
+    memcpy(serverRequest.requestToken, requestInfo->info.token, CA_MAX_TOKEN_LEN);
+
+    if (requestInfo->info.type == CA_MSG_CONFIRM)
+    {
+        serverRequest.qos = OC_HIGH_QOS;
+    }
+    else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
+    {
+        serverRequest.qos = OC_LOW_QOS;
+    }
+    else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
+    {
+        // TODO-CA: Need to handle this
+    }
+    else if (requestInfo->info.type == CA_MSG_RESET)
+    {
+        // TODO-CA: Need to handle this
+    }
+    // CA does not need the following 3 fields
+    serverRequest.coapID = 0;
+    serverRequest.delayedResNeeded = 0;
+    serverRequest.secured = endPoint->isSecured;
+
+    // copy the address
+    serverRequest.addressInfo      = endPoint->addressInfo;
+    serverRequest.connectivityType = endPoint->connectivityType;
+
+    // copy vendor specific header options
+    // TODO-CA: CA is including non-vendor header options as well, like observe.
+    // Need to filter those out
+    uint8_t tempNum = (requestInfo->info.numOptions);
+    GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
+    if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
+    {
+        OC_LOG(ERROR, TAG,
+                PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
+        OCFree(serverRequest.requestToken);
+        return;
+    }
+    serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
+    if (serverRequest.numRcvdVendorSpecificHeaderOptions)
+    {
+        memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
+            sizeof(CAHeaderOption_t)*tempNum);
+    }
+
+    requestResult = HandleStackRequests (&serverRequest);
+    if(requestResult != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, PCF("HandleStackRequests failed"));
+    }
+    OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
+}
+
 //This function will be called back by occoap layer when a request is received
 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
 {
     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
-
     OCStackResult result = OC_STACK_ERROR;
     ResourceHandling resHandling;
     OCResource *resource;
+    if(!protocolRequest)
+    {
+        OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
+        return OC_STACK_INVALID_PARAM;
+    }
 
     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
     if(!request)
@@ -196,8 +894,8 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
                 protocolRequest->observationOption, protocolRequest->qos,
                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
-                &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
-                protocolRequest->reqTotalSize);
+                protocolRequest->resourceUrl,protocolRequest->reqTotalSize,
+                &protocolRequest->addressInfo, protocolRequest->connectivityType);
         if (OC_STACK_OK != result)
         {
             OC_LOG(ERROR, TAG, PCF("Error adding server request"));
@@ -237,23 +935,274 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
 }
 
 //This function will be called back by occoap layer when a response is received
-void HandleStackResponses(OCResponse * response)
+OCStackResult HandleStackResponses(OCResponse * response)
 {
-    OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
+    OCStackResult result = OC_STACK_OK;
+    OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
+    uint8_t isObserveNotification = 0;
+    ClientCB * cbNode = NULL;
+    if(!response)
+    {
+        OC_LOG(ERROR, TAG, PCF("response is NULL"));
+        return OC_STACK_INVALID_PARAM;
+    }
+#ifdef WITH_PRESENCE
+    uint8_t isPresenceNotification = 0;
+    uint8_t isMulticastPresence = 0;
+    char * resourceTypeName = NULL;
+    uint32_t lowerBound = 0;
+    uint32_t higherBound = 0;
+    char * tok = NULL;
+    unsigned char * bufRes = response->bufRes;
+#endif // WITH_PRESENCE
 
-    if (response->cbNode)
+    cbNode = response->cbNode;
+    if(!cbNode)
     {
-        OC_LOG(INFO, TAG, PCF("Calling into application address space"));
-        result = response->cbNode->callBack(response->cbNode->context,
-                response->cbNode->handle, response->clientResponse);
-        if (result == OC_STACK_DELETE_TRANSACTION ||
+        cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
+    }
+
+    if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
+    {
+        isObserveNotification = 1;
+        OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+    }
+
+    OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
+            response->clientResponse->sequenceNumber);
+    OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
+    OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
+
+#ifdef WITH_PRESENCE
+    if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
+        isPresenceNotification = 1;
+        if(!bufRes)
+        {
+            result = OC_STACK_INVALID_PARAM;
+            goto exit;
+        }
+        char * savePtr;
+        tok = strtok_r((char *)bufRes, "[:]}", &savePtr);
+        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok_r(NULL, "[:]}", &savePtr);
+        bufRes[strlen((char *)bufRes)] = ':';
+        response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
+        OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
+        tok = strtok_r(NULL, "[:]}", &savePtr);
+        response->maxAge = (uint32_t )atoi(tok);
+        OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
+        tok = strtok_r(NULL, "[:]}", &savePtr);
+        if(tok)
+        {
+            resourceTypeName = (char *)OCMalloc(strlen(tok));
+            if(!resourceTypeName)
+            {
+                goto exit;
+            }
+            bufRes[strlen((char *)bufRes)] = ':';
+            strcpy(resourceTypeName, tok);
+            OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
+                    resourceTypeName);
+        }
+        bufRes[strlen((char *)bufRes)] = ']';
+    }
+
+    // Check if the application subcribed for presence
+    if(!cbNode)
+    {
+        cbNode = GetClientCB(NULL, NULL, response->fullUri);
+    }
+
+    // Check if application subscribed for multicast presence
+    if(!cbNode)
+    {
+        snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
+                OC_MULTICAST_IP, response->rcvdUri);
+        cbNode = GetClientCB(NULL, NULL, response->fullUri);
+        if(cbNode)
+        {
+            isMulticastPresence = 1;
+            isPresenceNotification = 0;
+        }
+    }
+
+    if(cbNode && isPresenceNotification)
+    {
+        OC_LOG(INFO, TAG, PCF("Received a presence notification"));
+        if(!cbNode->presence)
+        {
+            cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
+            VERIFY_NON_NULL_V(cbNode->presence);
+            cbNode->presence->timeOut = NULL;
+            cbNode->presence->timeOut = (uint32_t *)
+                    OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
+            if(!(cbNode->presence->timeOut)){
+                OCFree(cbNode->presence);
+                result = OC_STACK_NO_MEMORY;
+            }
+        }
+        if(response->maxAge == 0)
+        {
+            OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+            response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+            if(cbNode->presence)
+            {
+                OCFree(cbNode->presence->timeOut);
+                OCFree(cbNode->presence);
+                cbNode->presence = NULL;
+            }
+        }
+        else
+        {
+            OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
+            cbNode->presence->TTL = response->maxAge;
+            for(int index = 0; index < PresenceTimeOutSize; index++)
+            {
+                lowerBound = GetTime(((float)(PresenceTimeOut[index])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
+                OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
+                        cbNode->presence->timeOut[index]);
+            }
+            cbNode->presence->TTLlevel = 0;
+            OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+            if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
+            {
+                OC_LOG(INFO, TAG, PCF("===============No presence change"));
+                goto exit;
+            }
+            OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
+            cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
+        }
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+    else if(cbNode && isMulticastPresence)
+    {
+        // Check if the same nonce for a given host
+        OCMulticastNode* mcNode = NULL;
+        mcNode = GetMCPresenceNode(response->fullUri);
+
+        if(response->maxAge == 0)
+        {
+            OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+            response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+            if(cbNode->presence)
+            {
+                OCFree(cbNode->presence->timeOut);
+                OCFree(cbNode->presence);
+                cbNode->presence = NULL;
+            }
+        }
+        else if(mcNode != NULL)
+        {
+            if(mcNode->nonce == response->clientResponse->sequenceNumber)
+            {
+                OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            mcNode->nonce = response->clientResponse->sequenceNumber;
+        }
+        else
+        {
+            uint32_t uriLen = strlen((char*)response->fullUri);
+            unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
+            if(uri)
+            {
+                memcpy(uri, response->fullUri, (uriLen + 1));
+            }
+            else
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for URI to store in the presence node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+            result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
+                    response->clientResponse->sequenceNumber);
+            if(result == OC_STACK_NO_MEMORY)
+            {
+                OC_LOG(INFO, TAG,
+                    PCF("===============No Memory for Multicast Presence Node"));
+                result = OC_STACK_NO_MEMORY;
+                goto exit;
+            }
+        }
+
+        // Ensure that a filter is actually applied.
+        if(resourceTypeName && cbNode->filterResourceType)
+        {
+            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+            {
+                goto exit;
+            }
+        }
+    }
+
+    else if(!cbNode && isPresenceNotification)
+    {
+    OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
+                 ------------ ignoring"));
+    }
+    #endif // WITH_PRESENCE
+
+    if(cbNode)
+    {
+        if(isObserveNotification)
+        {
+            OC_LOG(INFO, TAG, PCF("Received an observe notification"));
+            //TODO: check the standard for methods to detect wrap around condition
+            if(cbNode->method == OC_REST_OBSERVE &&
+                    (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
+                            (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
+                                    response->clientResponse->sequenceNumber ==
+                                            MAX_SEQUENCE_NUMBER)))
+            {
+                OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
+                        Ignoring Incoming:%d  Against Current:%d.",
+                        response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
+                goto exit;
+            }
+            if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
+                cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
+            }
+        }
+
+        response->clientResponse->resJSONPayload = bufRes;
+
+        cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
+
+        if (cbResult == OC_STACK_DELETE_TRANSACTION ||
                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
-                response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
+                (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
+                        !isPresenceNotification && !isMulticastPresence))
         {
-            FindAndDeleteClientCB(response->cbNode);
+            FindAndDeleteClientCB(cbNode);
         }
     }
+    else
+    {
+        result = OC_STACK_ERROR;
+    }
+
+    exit:
+    #ifdef WITH_PRESENCE
+    OCFree(resourceTypeName);
+    #endif
+    return result;
 }
 
 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
@@ -349,7 +1298,7 @@ static void incrementSequenceNumber(OCResource * resPtr);
 static OCStackResult verifyUriQueryLength(const char * inputUri,
         uint16_t uriLen);
 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
-OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
+OCStackResult getResourceType(const char * query, unsigned char** resourceType);
 
 //-----------------------------------------------------------------------------
 // Public APIs
@@ -374,37 +1323,81 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
     OCStackResult result = OC_STACK_ERROR;
     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
 
+    // Validate mode
+    if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
+    {
+        OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+        return OC_STACK_ERROR;
+    }
+
     if (ipAddr)
     {
         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
     }
 
-    switch (mode)
+    OCSeedRandom();
+    CAInitialize();
+    //It is ok to select network to CA_WIFI for now
+#ifdef WITH_ARDUINO
+    CAResult_t caResult = CASelectNetwork(CA_ETHERNET);
+#else
+    CAResult_t caResult = CASelectNetwork(CA_WIFI|CA_ETHERNET);
+#endif
+    if(caResult == CA_STATUS_OK)
     {
-    case OC_CLIENT:
-        OC_LOG(INFO, TAG, PCF("Client mode"));
-        break;
-    case OC_SERVER:
-        OC_LOG(INFO, TAG, PCF("Server mode"));
-        break;
-    case OC_CLIENT_SERVER:
-        OC_LOG(INFO, TAG, PCF("Client-server mode"));
-        break;
-    default:
-        OC_LOG(ERROR, TAG, PCF("Invalid mode"));
-        return OC_STACK_ERROR;
-        break;
+        OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
+        CARegisterHandler(HandleCARequests, HandleCAResponses);
+        {
+            OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
+            stackState = OC_STACK_INITIALIZED;
+            result = OC_STACK_OK;
+            switch (mode)
+            {
+                case OC_CLIENT:
+                    caResult = CAStartDiscoveryServer();
+                    OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
+                    break;
+                case OC_SERVER:
+                    caResult = CAStartListeningServer();
+                    OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
+                    break;
+                case OC_CLIENT_SERVER:
+                    caResult = CAStartListeningServer();
+                    if(caResult == CA_STATUS_OK)
+                    {
+                        caResult = CAStartDiscoveryServer();
+                    }
+                    OC_LOG(INFO, TAG, PCF("Client-server mode"));
+                    break;
+                default:
+                    OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+                    return OC_STACK_ERROR;
+                    break;
+            }
+
+        }
+        if (caResult == CA_STATUS_OK)
+        {
+            result = OC_STACK_OK;
+        }
+        else
+        {
+            result = OC_STACK_ERROR;
+        }
     }
-    myStackMode = mode;
 
+    myStackMode = mode;
     defaultDeviceHandler = NULL;
 
+#if defined(__WITH_DTLS__)
+    caResult = CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
+    result = (caResult == CA_STATUS_OK) ? OC_STACK_OK : OC_STACK_ERROR;
+#endif // (__WITH_DTLS__)
+
 #ifdef WITH_PRESENCE
     PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
 #endif // WITH_PRESENCE
 
-    // Make call to OCCoAP layer
-    result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
     if (result == OC_STACK_OK)
     {
         stackState = OC_STACK_INITIALIZED;
@@ -433,12 +1426,19 @@ OCStackResult OCStop()
 
     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
 
-    if (stackState != OC_STACK_INITIALIZED)
+    if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
+    {
+        OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
+        return OC_STACK_OK;
+    }
+    else if (stackState != OC_STACK_INITIALIZED)
     {
         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
         return OC_STACK_ERROR;
     }
 
+    stackState = OC_STACK_UNINIT_IN_PROGRESS;
+
     #ifdef WITH_PRESENCE
     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
@@ -447,9 +1447,12 @@ OCStackResult OCStop()
 
     // Free memory dynamically allocated for resources
     deleteAllResources();
+    DeleteDeviceInfo();
+    CATerminate();
+    //CATerminate does not return any error code. It is OK to assign result to OC_STACK_OK.
+    result = OC_STACK_OK;
 
-    // Make call to OCCoAP layer
-    if (OCStopCoAP() == OC_STACK_OK)
+    if (result == OC_STACK_OK)
     {
         // Remove all observers
         DeleteObserverList();
@@ -458,6 +1461,7 @@ OCStackResult OCStop()
         stackState = OC_STACK_UNINITIALIZED;
         result = OC_STACK_OK;
     } else {
+        stackState = OC_STACK_INITIALIZED;
         result = OC_STACK_ERROR;
     }
 
@@ -472,6 +1476,27 @@ OCStackResult OCStop()
 }
 
 /**
+ * Map OCQualityOfService to CAMessageType
+ *
+ * @param OCQualityOfService - Input qos.
+ *
+ * Returns CA message type for a given qos.
+ */
+CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
+{
+    switch (qos)
+    {
+        case OC_HIGH_QOS:
+            return CA_MSG_CONFIRM;
+        case OC_LOW_QOS:
+        case OC_MEDIUM_QOS:
+        case OC_NA_QOS:
+        default:
+            return CA_MSG_NONCONFIRM;
+    }
+}
+
+/**
  * Verify the lengths of the URI and the query separately
  *
  * @param inputUri       - Input URI and query.
@@ -506,9 +1531,11 @@ OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
 }
 
 /**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource
+ * (specified by that Resource's respective URI).
  *
- * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of
+ *                             calling this API.
  * @param method             - @ref OCMethod to perform on the resource
  * @param requiredUri        - URI of the resource to interact with
  * @param referenceUri       - URI of the reference resource
@@ -525,20 +1552,31 @@ OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
  *     OC_STACK_INVALID_METHOD   - invalid resource method
  *     OC_STACK_INVALID_URI      - invalid required or reference URI
+ *
+ * Note: IN case of CA, when using multicast, the required URI should not contain IP address.
+ *       Instead, it just contains the URI to the resource such as "/oc/core".
  */
-
 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
-                           const char *referenceUri, const char *request,
-                           OCQualityOfService qos, OCCallbackData *cbData,
-                           OCHeaderOption * options, uint8_t numOptions)
+            const char *referenceUri, const char *request, OCConnectivityType conType,
+            OCQualityOfService qos, OCCallbackData *cbData,
+            OCHeaderOption * options, uint8_t numOptions)
 {
     OCStackResult result = OC_STACK_ERROR;
-    OCCoAPToken token;
     ClientCB *clientCB = NULL;
     unsigned char * requestUri = NULL;
     unsigned char * resourceType = NULL;
+    unsigned char * query = NULL;
     char * newUri = (char *)requiredUri;
     (void) referenceUri;
+    CARemoteEndpoint_t* endpoint = NULL;
+    CAResult_t caResult;
+    CAToken_t token = NULL;
+    CAInfo_t requestData;
+    CARequestInfo_t requestInfo;
+    CAGroupEndpoint_t grpEnd = {0};
+
+    // To track if memory is allocated for additional header options
+    uint8_t hdrOptionMemAlloc = 0;
 
     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
 
@@ -546,12 +1584,13 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
 
-    TODO ("Need to form the final query by concatenating require and reference URI's");
+    //TODO ("Need to form the final query by concatenating require and reference URI's");
     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
 
     uint16_t uriLen = strlen(requiredUri);
 
-    // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
+    // ToDo: We should also check if the requiredUri has a mutlicast address,
+    // then qos has to be OC_Low_QOS
     switch (method)
     {
         case OC_REST_GET:
@@ -585,13 +1624,22 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 #ifdef WITH_PRESENCE
     if(method == OC_REST_PRESENCE)
     {
-        result = getResourceType(requiredUri, &resourceType, &newUri);
-        if(resourceType) {
-            OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+        result = getQueryFromUri(requiredUri, &query, &newUri);
+        if(query)
+        {
+            result = getResourceType((char *) query, &resourceType);
+            if(resourceType)
+            {
+                OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+            }
+            else
+            {
+                OC_LOG(DEBUG, TAG, PCF("Resource type is NULL."));
+            }
         }
         else
         {
-            OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+            OC_LOG(DEBUG, TAG, PCF("Query string is NULL."));
         }
         if(result != OC_STACK_OK)
         {
@@ -618,19 +1666,134 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
         goto exit;
     }
 
-    // Generate token which will be used by OCStack to match responses received
-    // with the request
-    OCGenerateCoAPToken(&token);
+    memset(&requestData, 0, sizeof(CAInfo_t));
+    memset(&requestInfo, 0, sizeof(CARequestInfo_t));
+    switch (method)
+    {
+        case OC_REST_GET:
+        case OC_REST_OBSERVE:
+        case OC_REST_OBSERVE_ALL:
+        case OC_REST_CANCEL_OBSERVE:
+            {
+                requestInfo.method = CA_GET;
+                break;
+            }
+        case OC_REST_PUT:
+            {
+                requestInfo.method = CA_PUT;
+                break;
+            }
+        case OC_REST_POST:
+            {
+                requestInfo.method = CA_POST;
+                break;
+            }
+        case OC_REST_DELETE:
+            {
+                requestInfo.method = CA_DELETE;
+                break;
+            }
+        #ifdef WITH_PRESENCE
+        case OC_REST_PRESENCE:
+            {
+                // Replacing method type with GET because "presence"
+                // is a stack layer only implementation.
+                requestInfo.method = CA_GET;
+                break;
+            }
+        #endif
+        default:
+            result = OC_STACK_INVALID_METHOD;
+            goto exit;
+    }
+
+    //High QoS is not supported
+    if(qos == OC_HIGH_QOS)
+    {
+        result = OC_STACK_INVALID_PARAM;
+        goto exit;
+    }
+
+    // create token
+    caResult = CAGenerateToken(&token);
+    if (caResult != CA_STATUS_OK)
+    {
+        OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
+        CADestroyToken(token);
+        goto exit;
+    }
 
-    if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
-            != OC_STACK_OK)
+    requestData.type = qualityOfServiceToMessageType(qos);
+    requestData.token = token;
+    if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
     {
-        result = OC_STACK_NO_MEMORY;
+        result = CreateObserveHeaderOption (&(requestData.options), options,
+                                    numOptions, OC_OBSERVE_REGISTER);
+        if (result != OC_STACK_OK)
+        {
+            goto exit;
+        }
+        hdrOptionMemAlloc = 1;
+        requestData.numOptions = numOptions + 1;
+    }
+    else
+    {
+        requestData.options = (CAHeaderOption_t*)options;
+        requestData.numOptions = numOptions;
+    }
+    requestData.payload = (char *)request;
+
+    requestInfo.info = requestData;
+
+    CAConnectivityType_t caConType;
+
+    result = OCToCAConnectivityType((OCConnectivityType) conType, &caConType);
+    if (result != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, PCF("Invalid Connectivity Type"));
+        goto exit;
+    }
+
+    // send request
+    if(conType == OC_ALL)
+    {
+        grpEnd.connectivityType = caConType;
+
+        grpEnd.resourceUri = (CAURI_t) OCMalloc(uriLen + 1);
+        if(!grpEnd.resourceUri)
+        {
+            result = OC_STACK_NO_MEMORY;
+            goto exit;
+        }
+        strncpy(grpEnd.resourceUri, requiredUri, (uriLen + 1));
+
+        caResult = CASendRequestToAll(&grpEnd, &requestInfo);
+    }
+    else
+    {
+        caResult = CACreateRemoteEndpoint(newUri, caConType, &endpoint);
+
+        if (caResult != CA_STATUS_OK)
+        {
+            OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
+            goto exit;
+        }
+
+        caResult = CASendRequest(endpoint, &requestInfo);
+    }
+
+    if (caResult != CA_STATUS_OK)
+    {
+        OC_LOG(ERROR, TAG, PCF("CASendRequest"));
         goto exit;
     }
 
-    // Make call to OCCoAP layer
-    result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
+    if((result = AddClientCB(&clientCB, cbData, &token, handle, method,
+                             requestUri, resourceType)) != OC_STACK_OK)
+    {
+        result = OC_STACK_NO_MEMORY;
+        goto exit;
+    }
 
 exit:
     if(newUri != requiredUri)
@@ -642,6 +1805,12 @@ exit:
         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
         FindAndDeleteClientCB(clientCB);
     }
+    CADestroyRemoteEndpoint(endpoint);
+    OCFree(grpEnd.resourceUri);
+    if (hdrOptionMemAlloc)
+    {
+        OCFree(requestData.options);
+    }
     return result;
 }
 
@@ -659,7 +1828,8 @@ exit:
  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
  */
 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
-        uint8_t numOptions) {
+        uint8_t numOptions)
+{
     /*
      * This ftn is implemented one of two ways in the case of observation:
      *
@@ -678,6 +1848,12 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
      *      Remove the callback associated on client side.
      */
     OCStackResult ret = OC_STACK_OK;
+    CARemoteEndpoint_t* endpoint = NULL;
+    CAResult_t caResult;
+    CAInfo_t requestData;
+    CARequestInfo_t requestInfo;
+    // Track if memory is allocated for additional header options
+    uint8_t hdrOptionMemAlloc = 0;
 
     if(!handle) {
         return OC_STACK_INVALID_PARAM;
@@ -692,17 +1868,38 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
         {
             case OC_REST_OBSERVE:
             case OC_REST_OBSERVE_ALL:
-                if(qos == OC_HIGH_QOS)
+                //TODO-CA : Why CA_WIFI alone?
+                caResult = CACreateRemoteEndpoint((char *)clientCB->requestUri, CA_WIFI,
+                                                  &endpoint);
+                if (caResult != CA_STATUS_OK)
                 {
-                    ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
-                            &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
-                            numOptions);
+                    OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
+                    return OC_STACK_ERROR;
                 }
-                else
+
+                memset(&requestData, 0, sizeof(CAInfo_t));
+                requestData.type =  qualityOfServiceToMessageType(qos);
+                requestData.token = clientCB->token;
+                if (CreateObserveHeaderOption (&(requestData.options),
+                            options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
+                {
+                    return OC_STACK_ERROR;
+                }
+                hdrOptionMemAlloc = 1;
+                requestData.numOptions = numOptions + 1;
+                memset(&requestInfo, 0, sizeof(CARequestInfo_t));
+                requestInfo.method = CA_GET;
+                requestInfo.info = requestData;
+                // send request
+                caResult = CASendRequest(endpoint, &requestInfo);
+                if (caResult != CA_STATUS_OK)
                 {
-                    FindAndDeleteClientCB(clientCB);
+                    OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
+                }
+                if(caResult == CA_STATUS_OK)
+                {
+                    ret = OC_STACK_OK;
                 }
-                break;
             #ifdef WITH_PRESENCE
             case OC_REST_PRESENCE:
                 FindAndDeleteClientCB(clientCB);
@@ -712,8 +1909,15 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
                 return OC_STACK_INVALID_METHOD;
         }
     }
+    CADestroyRemoteEndpoint(endpoint);
+    if (hdrOptionMemAlloc)
+    {
+        OCFree(requestData.options);
+    }
+
     return ret;
 }
+
 #ifdef WITH_PRESENCE
 OCStackResult OCProcessPresence()
 {
@@ -726,6 +1930,7 @@ OCStackResult OCProcessPresence()
     OCDevAddr dst;
     OCClientResponse clientResponse;
     OCResponse * response = NULL;
+    OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
 
     LL_FOREACH(cbList, cbNode) {
         if(OC_REST_PRESENCE == cbNode->method)
@@ -733,7 +1938,8 @@ OCStackResult OCProcessPresence()
             if(cbNode->presence)
             {
                 uint32_t now = GetTime(0);
-                OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+                OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d",
+                                                        cbNode->presence->TTLlevel);
                 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
 
 
@@ -754,13 +1960,14 @@ OCStackResult OCProcessPresence()
                     {
                         OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
                                 &dst);
-                        result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
-                                (OCDevAddr *) &dst, 0, NULL);
-                        if(result != OC_STACK_OK)
-                        {
-                            goto exit;
-                        }
-                        result = FormOCResponse(&response, cbNode, 0, &clientResponse);
+
+                        clientResponse.sequenceNumber = 0;
+                        clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
+                        clientResponse.addr = (OCDevAddr *) &dst;
+                        clientResponse.resJSONPayload = NULL;
+
+                        result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
+                                &cbNode->token, &clientResponse, NULL);
                         if(result != OC_STACK_OK)
                         {
                             goto exit;
@@ -777,21 +1984,52 @@ OCStackResult OCProcessPresence()
                         result = OC_STACK_INVALID_IP;
                         goto exit;
                     }
-                    HandleStackResponses(response);
+
+                    cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
+                    if (cbResult == OC_STACK_DELETE_TRANSACTION)
+                    {
+                        FindAndDeleteClientCB(cbNode);
+                    }
                 }
+
                 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
                 {
+                    CAResult_t caResult;
+                    CARemoteEndpoint_t* endpoint = NULL;
+                    CAInfo_t requestData;
+                    CARequestInfo_t requestInfo;
+
                     OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
-                    OCCoAPToken token;
-                    OCGenerateCoAPToken(&token);
-                    result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
-                            &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
-                    if(result != OC_STACK_OK)
+
+                    //TODO-CA : Why CA_WIFI alone?
+                    caResult = CACreateRemoteEndpoint((char *)cbNode->requestUri, CA_WIFI,
+                                                  &endpoint);
+
+                    if (caResult != CA_STATUS_OK)
+                    {
+                        OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
+                        goto exit;
+                    }
+
+                    memset(&requestData, 0, sizeof(CAInfo_t));
+                    requestData.type = CA_MSG_NONCONFIRM;
+                    requestData.token = cbNode->token;
+
+                    memset(&requestInfo, 0, sizeof(CARequestInfo_t));
+                    requestInfo.method = CA_GET;
+                    requestInfo.info = requestData;
+
+                    caResult = CASendRequest(endpoint, &requestInfo);
+
+                    if (caResult != CA_STATUS_OK)
                     {
+                        OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
                         goto exit;
                     }
+
                     cbNode->presence->TTLlevel++;
-                    OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
+                    OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
+                                                            cbNode->presence->TTLlevel);
                 }
             }
         }
@@ -803,7 +2041,7 @@ exit:
     }
     return result;
 }
-#endif
+#endif // WITH_PRESENCE
 
 /**
  * Called in main loop of OC client or server.  Allows low-level processing of
@@ -813,13 +2051,12 @@ exit:
  *     OC_STACK_OK    - no errors
  *     OC_STACK_ERROR - stack process error
  */
-OCStackResult OCProcess() {
-
-    OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
+OCStackResult OCProcess()
+{
     #ifdef WITH_PRESENCE
     OCProcessPresence();
     #endif
-    OCProcessCoAP();
+    CAHandleRequestResponse();
 
     return OC_STACK_OK;
 }
@@ -852,15 +2089,26 @@ OCStackResult OCStartPresence(const uint32_t ttl)
 
     if(OC_PRESENCE_UNINITIALIZED == presenceState)
     {
-        OCDevAddr multiCastAddr;
-        OCCoAPToken token;
-
         presenceState = OC_PRESENCE_INITIALIZED;
-        OCGenerateCoAPToken(&token);
-        OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
-        //add the presence observer
-        AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
-            (OCResource *)presenceResource.handle, OC_LOW_QOS);
+
+        CAAddress_t addressInfo;
+        strncpy(addressInfo.IP.ipAddress, "224.0.1.187", CA_IPADDR_SIZE);
+        addressInfo.IP.port = 5683;
+
+        //TODO make sure there is no memory leak here since another copy
+        //of token is being created inside AddObserver
+        CAToken_t caToken = NULL;
+        CAResult_t caResult = CAGenerateToken(&caToken);
+        if (caResult != CA_STATUS_OK)
+        {
+            OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
+            CADestroyToken(caToken);
+            return OC_STACK_ERROR;
+        }
+
+        AddObserver(OC_PRESENCE_URI, NULL, 0, &caToken,
+                (OCResource *)presenceResource.handle, OC_LOW_QOS,
+                &addressInfo, CA_WIFI);
     }
 
     // Each time OCStartPresence is called
@@ -902,16 +2150,30 @@ OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandle
     return OC_STACK_OK;
 }
 
+OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
+
+    if(myStackMode == OC_CLIENT)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    return SaveDeviceInfo(deviceInfo);
+}
+
 /**
  * Create a resource
  *
- * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
+ * @param handle - pointer to handle to newly created resource.  Set by ocstack.
+ *                 Used to refer to resource
  * @param resourceTypeName - name of resource type.  Example: "core.led"
  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
  * @param uri - URI of the resource.  Example:  "/a/led"
  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
  *                        NULL for default entity handler
- * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
+ * @param resourceProperties - properties supported by resource.
+ *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
  *
  * @return
  *     OC_STACK_OK    - no errors
@@ -935,8 +2197,13 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
         return result;
     }
     // Validate parameters
+    if(!uri || (strlen(uri) == 0))
+    {
+        OC_LOG(ERROR, TAG, PCF("URI is invalid"));
+        return OC_STACK_INVALID_URI;
+    }
     // Is it presented during resource discovery?
-    if (!handle || !resourceTypeName || !uri) {
+    if (!handle || !resourceTypeName) {
         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
         return OC_STACK_INVALID_PARAM;
     }
@@ -966,11 +2233,10 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
         }
     }
     // Create the pointer and insert it into the resource list
-    pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+    pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResource));
     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
 
     insertResource(pointer);
@@ -1214,14 +2480,13 @@ OCStackResult BindResourceTypeToResource(OCResource* resource,
     // TODO:  Does resource attribute resentation really have to be maintained in stack?
     // Is it presented during resource discovery?
 
-    TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
+    //TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
 
     // Create the resourcetype and insert it into the resource list
-    pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+    pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceType));
 
     // Set the resourceTypeName
     size = strlen(resourceTypeName) + 1;
@@ -1256,14 +2521,13 @@ OCStackResult BindResourceInterfaceToResource(OCResource* resource,
     // Validate parameters
     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
 
-    TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
+    //TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
 
     // Create the resourceinterface and insert it into the resource list
-    pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+    pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceInterface));
 
     // Set the resourceinterface name
     size = strlen(resourceInterfaceName) + 1;
@@ -1696,7 +2960,6 @@ void incrementSequenceNumber(OCResource * resPtr)
     return;
 }
 
-#ifdef WITH_PRESENCE
 /**
  * Notify Presence subscribers that a resource has been modified
  *
@@ -1705,6 +2968,7 @@ void incrementSequenceNumber(OCResource * resPtr)
  * @param qos          - Quality Of Service
  *
  */
+#ifdef WITH_PRESENCE
 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
 {
     OCResource *resPtr = NULL;
@@ -1726,10 +2990,10 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType)
     }
 
     result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
+
     return result;
 }
-#endif
-
+#endif // WITH_PRESENCE
 /**
  * Notify observers that an observed value has changed.
  *
@@ -1857,7 +3121,6 @@ OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
     else
     {
         // Normal response
-
         // Get pointer to request info
         serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
         if(serverRequest)
@@ -1899,10 +3162,10 @@ static OCDoHandle GenerateInvocationHandle()
 {
     OCDoHandle handle = NULL;
     // Generate token here, it will be deleted when the transaction is deleted
-    handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+    handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
     if (handle)
     {
-        OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+        OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
     }
 
     return handle;
@@ -2323,29 +3586,50 @@ uint8_t OCIsPacketTransferRequired(const char *request, const char *response, ui
 }
 
 /**
- * Retrieves a resource type based upon a uri string if the uri string contains only just one
+ * Retrieves a resource type based upon a query ontains only just one
  * resource attribute (and that has to be of type "rt").
  *
- * @remark This API malloc's memory for the resource type and newURI. Do not malloc resourceType
- * or newURI before passing in.
+ * @remark This API malloc's memory for the resource type. Do not malloc resourceType
+ * before passing in.
  *
- * @param uri - Valid URI for "requiredUri" parameter to OCDoResource API.
+ * @param query - The quert part of the URI
  * @param resourceType - The resource type to be populated; pass by reference.
- * @param newURI - Return URI without resourceType appended to the end of it. This is used to
- *                 ensure that the uri parameter is not modified; pass by reference.
  *
  * @return
- *  OC_STACK_INVALID_URI   - Returns this if the URI is invalid/NULL.
  *  OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
  *  OC_STACK_OK            - Success
  */
-OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI)
+OCStackResult getResourceType(const char * query, unsigned char** resourceType)
+{
+    if(!query)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCStackResult result = OC_STACK_ERROR;
+
+    if(strncmp(query, "rt=", 3) == 0)
+    {
+        *resourceType = (unsigned char *) OCMalloc(strlen(query)-3);
+        if(!*resourceType)
+        {
+            result = OC_STACK_NO_MEMORY;
+        }
+
+        strcpy((char *)*resourceType, ((const char *)&query[3]));
+        result = OC_STACK_OK;
+    }
+
+    return result;
+}
+
+OCStackResult getQueryFromUri(const char * uri, unsigned char** query, char ** newURI)
 {
     if(!uri)
     {
         return OC_STACK_INVALID_URI;
     }
-    if(!resourceType || !newURI)
+    if(!query || !newURI)
     {
         return OC_STACK_INVALID_PARAM;
     }
@@ -2356,21 +3640,24 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
         goto exit;
     }
     strcpy(tempURI, uri);
-    leftToken = strtok((char *)tempURI, "?");
+    char* strTokPtr;
+    leftToken = strtok_r((char *)tempURI, "?", &strTokPtr);
 
+    //TODO-CA: This could be simplified. Clean up required.
     while(leftToken != NULL)
     {
-        if(strncmp(leftToken, "rt=", 3) == 0)
+        if(strncmp(leftToken, "rt=", 3) == 0 || strncmp(leftToken, "if=", 3) == 0)
         {
-            *resourceType = (unsigned char *) OCMalloc(strlen(leftToken)-3);
-            if(!*resourceType)
+            *query = (unsigned char *) OCMalloc(strlen(leftToken) + 1);
+            if(!*query)
             {
+                OCFree(tempURI);
                 goto exit;
             }
-            strcpy((char *)*resourceType, ((const char *)&leftToken[3]));
+            strcpy((char *)*query, ((const char *)&leftToken[0]));
             break;
         }
-        leftToken = strtok(NULL, "?");
+        leftToken = strtok_r(NULL, "?", &strTokPtr);
     }
 
     *newURI = tempURI;
@@ -2380,3 +3667,66 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
     exit:
         return OC_STACK_NO_MEMORY;
 }
+
+const ServerID OCGetServerInstanceID(void)
+{
+    static bool generated = false;
+    static ServerID sid;
+
+    if(generated)
+    {
+        return sid;
+    }
+
+    sid = OCGetRandom();
+    generated = true;
+    return sid;
+}
+
+const char* OCGetServerInstanceIDString(void)
+{
+    // max printed length of a base 10
+    // uint32 is 10 characters, so 11 includes null.
+    // This will change as the representation gets switched
+    // to another value
+    static char buffer[11];
+    int n = sprintf(buffer, "%u", OCGetServerInstanceID());
+    if (n < 0)
+    {
+        buffer[0]='\0';
+    }
+
+    return buffer;
+}
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
+        uint8_t *c, uint8_t *d )
+{
+    if ( !ipAddr || !a || !b || !c || !d ) {
+        OC_LOG(FATAL, TAG, "Invalid argument");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    *a = ipAddr->addr[0];
+    *b = ipAddr->addr[1];
+    *c = ipAddr->addr[2];
+    *d = ipAddr->addr[3];
+
+    return OC_STACK_OK;
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
+{
+    if ( !ipAddr || !port ) {
+        OC_LOG(FATAL, TAG, "Invalid argument");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    *port = *((uint16_t*)&ipAddr->addr[4]);
+
+    return OC_STACK_OK;
+}
+