Update RD with latest master
authorHabib Virji <habib.virji@samsung.com>
Sun, 20 Sep 2015 20:40:46 +0000 (21:40 +0100)
committerHabib Virji <habib.virji@samsung.com>
Sun, 20 Sep 2015 20:41:25 +0000 (21:41 +0100)
Change-Id: Ifaa16985f8bbc59bcf8d81aa03696ee3f6d784ae
Signed-off-by: Habib Virji <habib.virji@samsung.com>
26 files changed:
auto_build.sh
build_common/SConscript
resource/csdk/SConscript
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/include/payload_logging.h
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocpayloadparse.c
resource/csdk/stack/src/ocresource.c
resource/docs/Doxyfile
service/SConscript
service/resource-directory/SConscript [new file with mode: 0755]
service/resource-directory/include/rd_client.h [new file with mode: 0644]
service/resource-directory/include/rd_payload.h [new file with mode: 0644]
service/resource-directory/include/rd_server.h [new file with mode: 0644]
service/resource-directory/include/rd_types.h [new file with mode: 0644]
service/resource-directory/samples/SConscript [new file with mode: 0644]
service/resource-directory/samples/rd_main.c [new file with mode: 0644]
service/resource-directory/samples/rd_publishingClient.cpp [new file with mode: 0644]
service/resource-directory/samples/rd_queryClient.cpp [new file with mode: 0644]
service/resource-directory/src/internal/rd_storage.c [new file with mode: 0644]
service/resource-directory/src/internal/rd_storage.h [new file with mode: 0644]
service/resource-directory/src/rd_client.c [new file with mode: 0644]
service/resource-directory/src/rd_payload.c [new file with mode: 0644]
service/resource-directory/src/rd_server.c [new file with mode: 0644]

index 2a09953..415f36a 100755 (executable)
@@ -12,6 +12,8 @@ function build_all()
                build_linux_secured $1 $2
                build_linux_unsecured_with_ra $1 $2
                build_linux_secured_with_ra $1 $2
+               build_linux_unsecured_with_rd $1 $2
+               build_linux_secured_with_rd $1 $2
        fi
 
        build_android $1 $2
@@ -58,6 +60,18 @@ function build_linux_secured_with_ra()
        scons RELEASE=$1 WITH_RA=1 SECURED=1 $2
 }
 
+function build_linux_unsecured_with_rd()
+{
+       echo "*********** Build for linux With Resource Directory *************"
+       scons RELEASE=$1 WITH_RD=1 $2
+}
+
+function build_linux_secured_with_rd()
+{
+       echo "*********** Build for linux With Resource Directory & Security ************"
+       scons RELEASE=$1 WITH_RD=1 SECURED=1 $2
+}
+
 function build_android()
 {
        # Note: for android, as oic-resource uses C++11 feature stoi and to_string,
@@ -141,8 +155,8 @@ function  help()
        echo "Usage:"
         echo "  build:"
         echo "     `basename $0` <target_build>"
-       echo "      Allowed values for <target_build>: all, linux_unsecured, linux_secured, linux_unsecured_with_ra, linux_secured_with_ra, android, arduino, tizen, darwin"
-       echo "      Note: \"linux\" will build \"linux_unsecured\", \"linux_secured\", \"linux_unsecured_with_ra\" & \"linux_secured_with_ra\"."
+       echo "      Allowed values for <target_build>: all, linux_unsecured, linux_secured, linux_unsecured_with_ra, linux_secured_with_ra, linux_unsecured_with_rd, linux_secured_with_rd, android, arduino, tizen, darwin"
+       echo "      Note: \"linux\" will build \"linux_unsecured\", \"linux_secured\", \"linux_unsecured_with_ra\", \"linux_secured_with_ra\", \"linux_secured_with_rd\" & \"linux_unsecured_with_rd\"."
        echo "      Any selection will build both debug and release versions of all available targets in the scope you've"
        echo "      selected. To choose any specific command, please use the SCons commandline directly. Please refer"
        echo "      to [IOTIVITY_REPO]/Readme.scons.txt."
@@ -185,6 +199,14 @@ then
        then
                build_linux_secured_with_ra true
                build_linux_secured_with_ra false
+       elif [ $1 = 'linux_unsecured_with_rd' ]
+       then
+               build_linux_unsecured_with_rd true
+               build_linux_unsecured_with_rd false
+       elif [ $1 = 'linux_secured_with_rd' ]
+       then
+               build_linux_secured_with_rd true
+               build_linux_secured_with_rd false
        elif [ $1 = 'android' ]
        then
                build_android true
index 5626312..f7edffd 100644 (file)
@@ -79,6 +79,7 @@ help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map
 
 
 help_vars.Add(BoolVariable('WITH_RA', 'Build with Remote Access module', False))
+help_vars.Add(EnumVariable('WITH_RD', 'Build including Resource Directory', '0', allowed_values=('0', '1')))
 
 if target_os in targets_disallow_multitransport:
        help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'IP', ['BT', 'BLE', 'IP']))
index 9f887e9..edc083f 100644 (file)
@@ -101,6 +101,11 @@ if env.get('SECURED') == '1':
 if env.get('LOGGING'):
        liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
+if env.get('WITH_RD') == '1':
+       liboctbstack_env.PrependUnique(CPPPATH = ['../../service/resource-directory/include'])
+       liboctbstack_env.AppendUnique(CPPDEFINES = ['-DWITH_RD'])
+       liboctbstack_env.AppendUnique(LIBS = ['resource_directory'])
+
 liboctbstack_env.Append(LIBS = ['c_common'])
 
 if liboctbstack_env.get('ROUTING') in ['GW', 'EP']:
index 37d56f9..e90558c 100755 (executable)
 #include <inttypes.h>
 #include "octypes.h"
 
+#ifdef WITH_RD
+#include "rd_payload.h"
+#endif
+
 #ifdef __cplusplus
 extern "C"
 {
index b82d1be..6269687 100644 (file)
@@ -882,7 +882,8 @@ typedef enum
     PAYLOAD_TYPE_PLATFORM,
     PAYLOAD_TYPE_REPRESENTATION,
     PAYLOAD_TYPE_SECURITY,
-    PAYLOAD_TYPE_PRESENCE
+    PAYLOAD_TYPE_PRESENCE,
+    PAYLOAD_TYPE_RD
 } OCPayloadType;
 
 typedef struct
index 691bf08..797c8b3 100644 (file)
@@ -259,6 +259,11 @@ static inline void OCPayloadLog(LogLevel level, OCPayload* payload)
         case PAYLOAD_TYPE_SECURITY:
             OCPayloadLogSecurity(level, (OCSecurityPayload*)payload);
             break;
+#ifdef WITH_RD
+        case PAYLOAD_TYPE_RD:
+            OCRDPayloadLog(level, tag, (OCRDPayload*)payload);
+            break;
+#endif
         default:
             OC_LOG_V(level, PL_TAG, "Unknown Payload Type: %d", payload->type);
             break;
index 6be1ffe..8145378 100755 (executable)
@@ -59,6 +59,11 @@ void OCPayloadDestroy(OCPayload* payload)
         case PAYLOAD_TYPE_SECURITY:
             OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
             break;
+#ifdef WITH_RD
+        case PAYLOAD_TYPE_RD:
+           OCRDPayloadDestroy((OCRDPayload*)payload);
+           break;
+#endif
         default:
             OC_LOG_V(ERROR, TAG, "Unsupported payload type in destroy: %d", payload->type);
             OICFree(payload);
index e838e4d..8e64af5 100644 (file)
@@ -140,6 +140,10 @@ static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, s
             return OCConvertPresencePayload((OCPresencePayload*)payload, outPayload, size);
         case PAYLOAD_TYPE_SECURITY:
             return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size);
+#ifdef WITH_RD
+        case PAYLOAD_TYPE_RD:
+            return OCRDPayloadToCbor((OCRDPayload*)payload, outPayload, size);
+#endif
         default:
             OC_LOG_V(INFO,TAG, "ConvertPayload default %d", payload->type);
             return OC_STACK_NOTIMPL;
index e3596da..36f726b 100644 (file)
@@ -43,7 +43,7 @@ OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
     CborValue rootValue;
     bool err = false;
 
-    OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d", payloadSize, payload);
+    OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d", payloadSize);
     if((err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue)) != false)
     {
         OC_LOG_V(ERROR, TAG, "CBOR Parser init failed: %d", err);
@@ -87,6 +87,11 @@ OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
         case PAYLOAD_TYPE_SECURITY:
             result = OCParseSecurityPayload(outPayload, &arrayValue);
             break;
+#ifdef WITH_RD
+        case PAYLOAD_TYPE_RD:
+            result = OCRDCborToPayload(&arrayValue, outPayload);
+            break;
+#endif
         default:
             OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
             result = OC_STACK_ERROR;
index 95265bb..c927807 100644 (file)
 #include "secureresourcemanager.h"
 #include "cacommon.h"
 #include "cainterface.h"
+
+#ifdef WITH_RD
+#include "rd_server.h"
+#endif 
+
 #ifdef ROUTING_GATEWAY
 #include "routingmanager.h"
 #endif
@@ -540,6 +545,74 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes
     return OCDoResponse(&response);
 }
 
+#ifdef WITH_RD
+static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType, OCRepPayload **repPayload)
+{
+    char *uri = NULL;
+    char *rt = NULL;
+    char *itf = NULL;
+
+    if (OCRDCheckPublishedResource(interfaceType, resourceType, &uri, &rt, &itf) == OC_STACK_OK)
+    {
+        if (!uri || !rt || !itf)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+            // if any of the parameter has memory allocated free each one of them.
+            OICFree(uri);
+            OICFree(rt);
+            OICFree(itf);
+            return OC_STACK_NO_MEMORY;
+        }
+
+        OCRepPayload *rdResource = OICCalloc(1, sizeof(OCRepPayload));
+        if (!rdResource)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+            OICFree(uri);
+            OICFree(rt);
+            OICFree(itf);
+            return OC_STACK_NO_MEMORY;
+        }
+
+        rdResource->uri = uri;
+
+        rdResource->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        if(!rdResource->types)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+            OICFree(uri);
+            OICFree(rt);
+            OICFree(itf);
+            OICFree(rdResource);
+            return OC_STACK_NO_MEMORY;
+        }
+        rdResource->types->value = rt;
+
+        rdResource->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
+        if(!rdResource->interfaces)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+            OICFree(uri);
+            OICFree(rt);
+            OICFree(itf);
+            OICFree(rdResource);
+            return OC_STACK_NO_MEMORY;
+        }
+        rdResource->interfaces->value = itf;
+
+        *repPayload = rdResource;
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
+                             on the resource directory");
+    }
+    return OC_STACK_ERROR;
+}
+#endif
+
 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
 {
     if (!request || !resource)
@@ -573,7 +646,23 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
             {
                 for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
                 {
-                    if(includeThisResourceInResponse(resource, filterOne, filterTwo))
+                    bool foundResourceAtRD = false;
+#ifdef WITH_RD
+                    if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
+                    {
+                        OCRepPayload *repPayload = NULL;
+                        discoveryResult = checkResourceExistsAtRD(filterOne, filterTwo, &repPayload);
+                        if (discoveryResult != OC_STACK_OK)
+                        {
+                             break;
+                        }
+                        discoveryResult = BuildVirtualResourceResponse((OCResource *)repPayload,
+                                    (OCDiscoveryPayload*)payload,
+                                    &request->devAddr);
+                        foundResourceAtRD = true;
+                    }
+#endif
+                    if(!foundResourceAtRD && includeThisResourceInResponse(resource, filterOne, filterTwo))
                     {
                         discoveryResult = BuildVirtualResourceResponse(resource,
                                 (OCDiscoveryPayload*)payload,
index 77c863d..cf72346 100644 (file)
@@ -674,6 +674,7 @@ INPUT                  = . \
                          ../../service/protocol-plugin/plugin-manager/src/PluginManager.h \
                          ../../service/notification-manager/NotificationManager/include/hosting.h \
                          ../../service/resource-encapsulation/include \
+                         ../../service/resource-directory/include \
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
index be349be..f712f25 100644 (file)
@@ -45,3 +45,6 @@ if target_os not in ['arduino','darwin']:
        if target_os not in ['tizen']:
                SConscript('resource-encapsulation/SConscript')
 
+       # Build resource directory project
+       if env.get('WITH_RD') == '1':
+               SConscript('resource-directory/SConscript')
diff --git a/service/resource-directory/SConscript b/service/resource-directory/SConscript
new file mode 100755 (executable)
index 0000000..76200c2
--- /dev/null
@@ -0,0 +1,83 @@
+#******************************************************************
+#
+# Copyright 2015 Samsung Electronics All Rights Reserved.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# Resource Directory build script
+##
+
+Import('env')
+
+if env.get('RELEASE'):
+    env.AppendUnique(CCFLAGS = ['-Os'])
+    env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+    env.AppendUnique(CCFLAGS = ['-g'])
+
+if env.get('LOGGING'):
+    env.AppendUnique(CPPDEFINES = ['-DTB_LOG'])
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+rd_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+rd_env.AppendUnique(CPPPATH = ['include'])
+rd_env.AppendUnique(CPPPATH = ['src/internal'])
+rd_env.AppendUnique(CPPPATH = ['../../resource/csdk/logger/include'])
+rd_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'libcoap'])
+
+if target_os not in ['windows', 'winrt']:
+    rd_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-Wextra'])
+
+if target_os == 'linux':
+    rd_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+    rd_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+    rd_env.AppendUnique(LIBS = ['gnustl_static'])
+
+    if not env.get('RELEASE'):
+        rd_env.AppendUnique(LIBS = ['log'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+RD_SRC_DIR = 'src/'
+rd_src = [
+        RD_SRC_DIR + '/internal/rd_storage.c',
+        RD_SRC_DIR + 'rd_server.c',
+        RD_SRC_DIR + 'rd_payload.c',
+        RD_SRC_DIR + 'rd_client.c',
+         ]
+
+if target_os in ['tizen'] :
+    rdsdk = rd_env.SharedLibrary('resource_directory', rd_src)
+else :
+    rdsdk = rd_env.StaticLibrary('resource_directory', rd_src)
+
+rd_env.InstallTarget(rdsdk, 'libresource_directory')
+
+######################################################################
+# Samples for the resource directory
+######################################################################
+SConscript('samples/SConscript')
diff --git a/service/resource-directory/include/rd_client.h b/service/resource-directory/include/rd_client.h
new file mode 100644 (file)
index 0000000..20becb7
--- /dev/null
@@ -0,0 +1,60 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _RESOURCE_DIRECTORY_CLIENT_H_
+#define _RESOURCE_DIRECTORY_CLIENT_H_
+
+// Iotivity Base CAPI
+#include "ocstack.h"
+
+#include "rd_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Discovers the resource directory.
+ * This function searches a RD server and obtain the bias factor.
+ *
+ * @param cbBiasFactor callback function invoked when bias factor is returned by
+ *                     the Resource Directory Server
+ *
+ * @return ::OC_STACK_OK upon success, ::OC_STACK_ERROR in case of error.
+ */
+OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor);
+
+/**
+ * Publish resource on the RD.
+ *
+ * @param addr The IP address of the RD, it could be either retrieved via OCRDDiscover().
+ * @param port The port of the RD.
+ * @param num This denotes the number of registered resource handles being passed
+ *            for the remaining arguments.
+ *
+ * @returns ::OC_STACK_OK when successful and OC_STACK_ERROR when query failed.
+ */
+OCStackResult OCRDPublish(char *addr, uint16_t port, int num, ...);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //_RESOURCE_DIRECTORY_CLIENT_H_
diff --git a/service/resource-directory/include/rd_payload.h b/service/resource-directory/include/rd_payload.h
new file mode 100644 (file)
index 0000000..9146975
--- /dev/null
@@ -0,0 +1,134 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _RESOURCE_DIRECTORY_PAYLOAD_H_
+#define _RESOURCE_DIRECTORY_PAYLOAD_H_
+
+#include <cbor.h>
+
+#include "rd_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Converts RD payload from structure to CBOR format. It creates the outPayload
+ * which is then transmitted over the wire.
+ *
+ * @param rdPayload Contains structure holding values of OCRDPayload.
+ * @param outPayload The payload in the CBOR format converting OCRDPayload
+ * structure.
+ * @param size Length of the payload.
+ *
+ * @return ::OC_STACK_OK returns if successful and OC_STACK_ERROR returns if
+ * failed in creating CBOR.
+ */
+OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload,
+                                uint8_t **outPayload, size_t *size);
+
+/**
+ * Converts CBOR to OCRDPayload.
+ *
+ * @param rdCBORPayload Payload received from other end in CBOR format.
+ * @param outPayload Parsing the values from CBOR into OCRDPayload structure.
+ *
+ * @return ::OC_STACK_OK returns if successful and OC_STACK_ERROR returns if
+ * failed in parsing CBOR.
+ */
+OCStackResult OCRDCborToPayload(const CborValue *rdCBORPayload, OCPayload **outPayload);
+
+/**
+ * Initializes RD payload structure.
+ *
+ * @param payloadType Defines whether payload is RD_PAYLOAD_TYPE_DISCOVERY or
+ * RD_PAYLOAD_TYPE_PUBLISH.
+ *
+ * @return Allocated memory for the OCRDPayload and NULL in case if failed to
+ * allocate memory
+ */
+OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType);
+
+/**
+ * Initializes RD Discovery payload structure and sets the bias factor.
+ *
+ * @param biasFactor Value specifies the selection factor. It is weigthage of
+ * CPU, Memory, Network, Load and Power capability of the RD server.
+ *
+ * @return Allocated memory for the OCRDDiscoveryPayload and NULL in case if
+ * failed to allocate memory.
+ */
+OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor);
+
+/**
+ * Creates the links payload, which is then embedded inside OCRDPublishPayload.
+ *
+ * @param uri  The Web Link Address of the resource.
+ * @param rt   The resource type of the published resource.
+ * @param itf  The interface type of the published resource.
+ * @param linkPayload The address of the allocated memory or NULL in case if failed
+ *                    to allocate memory.
+ */
+void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
+        OCRDLinksPayload **linkPayload);
+
+/**
+ * Creates the links payload, which is then embedded inside OCRDPublishPayload.
+ *
+ * @param ttl  Time to live of the published resource..
+ * @param linkPayload  The link payload with uri, rt and itf.
+ *
+ * @return  Allocated memory of OCRDPublishPayload or NULL in case if failed
+ *          to allocate memory.
+ */
+OCRDPublishPayload *OCRDPublishPayloadCreate(const int ttl,
+        OCRDLinksPayload *linkPayload);
+
+/**
+ * Free memory allocation of the RDPayload and its internal structure.
+ *
+ * @param payload Pointer to already allocated memory for OCRDPayload.
+ */
+void OCRDPayloadDestroy(OCRDPayload *payload);
+
+/**
+ * Logs the content of the OCRDPayload.
+ *
+ * @param level Log level DEBUG or INFO or ERROR.
+ * @param tag File specific tag to use.
+ * @param payload Pointer to already allocated memory for OCRDPayload.
+ */
+void OCRDPayloadLog(LogLevel level, const char *tag, const OCRDPayload *payload);
+
+/**
+ * Logs the subset of the OCRDPayload, prints separately OCRDPublish.
+ *
+ * @param level Log level DEBUG or INFO or ERROR.
+ * @param tag File specific tag to use.
+ * @param payload Pointer to already allocated memory for OCRDPublish.
+ */
+void OCRDPublishPayloadLog(LogLevel level, const char *tag,
+        const OCRDPublishPayload *rdPublish);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
diff --git a/service/resource-directory/include/rd_server.h b/service/resource-directory/include/rd_server.h
new file mode 100644 (file)
index 0000000..8a3631e
--- /dev/null
@@ -0,0 +1,68 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _RESOURCE_DIRECTORY_SERVER_H_
+#define _RESOURCE_DIRECTORY_SERVER_H_
+
+// Iotivity Base CAPI
+#include "ocstack.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+* Starts resource directory.
+* This function creates a RD server and create resource /oic/rd.
+*
+* @return ::OC_STACK_OK upon success, ::OC_STACK_ERROR in case of error.
+*/
+OCStackResult OCRDStart();
+
+/**
+* Stops resource directory.
+* This function will stop the resource directory and removes all published
+* resources information.
+*
+* @return ::OC_STACK_OK upon success, ::OC_STACK_ERROR is returned except
+* the case that OC_STACK_SUCCESS is returned.
+*/
+OCStackResult OCRDStop();
+
+/**
+ * Checks based on the resource type if the entity exists in the resource directory.
+ *
+ * @param interfaceType a interface type that is being queried.
+ * @param resourceType a resource type that is being queried.
+ * @param uri A URI of the resource found;
+ * @param rt A resource type of the message queried.
+ * @param itf A resource type of the interface.
+ *
+ * @return ::OC_STACK_OK upon success, ::OC_STACK_ERROR is returned except
+ * the case that OC_STACK_SUCCESS is returned.
+ */
+OCStackResult OCRDCheckPublishedResource(const char *interfaceType, const char *resourceType,
+         char **uri, char **rt, char **itf);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //_RESOURCE_DIRECTORY_H_
diff --git a/service/resource-directory/include/rd_types.h b/service/resource-directory/include/rd_types.h
new file mode 100644 (file)
index 0000000..31dfd14
--- /dev/null
@@ -0,0 +1,126 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#ifndef _RESOURCE_DIRECTORY_TYPES_H_
+#define _RESOURCE_DIRECTORY_TYPES_H_
+
+#include "ocpayload.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/** Resource Directory URI used to Discover RD and Publish resources.*/
+#define OC_RSRVD_RD_URI                  "/oic/rd"
+
+/** To represent resource type with rd.*/
+#define OC_RSRVD_RESOURCE_TYPE_RD        "oic.wk.rd"
+
+/** RD Discovery bias factor type. */
+#define OC_RSRVD_RD_DISCOVERY_SEL        "sel"
+
+/** To represent resource type with Publish RD.*/
+#define OC_RSRVD_RESOURCE_TYPE_RDPUBLISH "oic.wk.rdPub"
+
+/** Max ADDR SIZE */
+#define MAX_ADDR_STR_SIZE (40)
+
+/** Callback function for returning RDDiscovery Result. */
+typedef int (* OCRDBiasFactorCB)(char addr[MAX_ADDR_STR_SIZE], uint16_t port);
+
+/** Context structure used sending it as part of the callback context. */
+typedef struct
+{
+    /** Stores the context value of the message sent. */
+    void *context;
+    /** Pointing to the callback function that OCRDDiscover() received. */
+    OCRDBiasFactorCB cbFunc;
+} OCRDClientContextCB;
+
+/**
+ * Structure holding discovery payload.
+ */
+typedef struct
+{
+    /** Value holding the bias factor of the RD. */
+    uint8_t sel;
+} OCRDDiscoveryPayload;
+
+/**
+ * Structure holding RD Links Payload. It is a sub-structure used in
+ * OCRDPublishPayload.
+ */
+typedef struct OCRDLinksPayload
+{
+    /** Web Link Address of the resource. */
+    char *href;
+    /** Resource type of the resource. */
+    char *rt;
+    /** Interace type of the resource. */
+    char *itf;
+    /** Holding address of the next resource. */
+    struct OCRDLinksPayload *next;
+} OCRDLinksPayload;
+
+/**
+ * Structure holding RD Publish payload.
+ */
+typedef struct
+{
+    /** Device Name. */
+    OCDeviceInfo deviceName;
+    /** Device id. */
+    OCIdentity deviceId;
+    /** Time to keep holding resource.*/
+    uint32_t ttl;
+    /** List of resource information that will be stored at RD.*/
+    OCRDLinksPayload *links;
+} OCRDPublishPayload;
+
+/**
+ * Enum values of multiple RD type payload.
+ */
+typedef enum
+{
+    /** Value pf the RD discovery payload. */
+    RD_PAYLOAD_TYPE_DISCOVERY,
+    /** Value of the RD publish payload. */
+    RD_PAYLOAD_TYPE_PUBLISH
+} OCRDPayloadType;
+
+/**
+ * RD Payload that will be transmitted over the wire.
+ */
+typedef struct
+{
+    /** Used in ocpayload to check type of the packet. This matches other OC payload.*/
+    OCPayload base;
+    /** Used internally in RD to check the payload whether discovery or publish.*/
+    OCRDPayloadType payloadType;
+    /** Pointer to the discovery response payload.*/
+    OCRDDiscoveryPayload *rdDiscovery;
+    /** Pointer to the publish payload.*/
+    OCRDPublishPayload *rdPublish;
+} OCRDPayload;
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
diff --git a/service/resource-directory/samples/SConscript b/service/resource-directory/samples/SConscript
new file mode 100644 (file)
index 0000000..b9a2a16
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# ResourceDirectory Sample Apps build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+rd_sample_app_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+rd_sample_app_env.AppendUnique(CPPPATH = ['../include'])
+
+rd_sample_app_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-Wextra', '-std=c++0x'])
+rd_sample_app_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+rd_sample_app_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
+rd_sample_app_env.PrependUnique(LIBS = ['resource_directory', 'oc', 'octbstack'])
+
+if env.get('SECURED') == '1':
+    rd_sample_app_env.AppendUnique(LIBS = ['tinydtls'])
+
+####################################################################
+# Source files and Targets
+######################################################################
+rd_server = rd_sample_app_env.Program('rd_server', 'rd_main.c')
+rd_publishingClient = rd_sample_app_env.Program('rd_publishingClient', 'rd_publishingClient.cpp')
+rd_queryClient = rd_sample_app_env.Program('rd_queryClient', 'rd_queryClient.cpp')
+
+Alias("resource_directory", [rd_server, rd_publishingClient])
+
+env.AppendTarget('resource_directory')
diff --git a/service/resource-directory/samples/rd_main.c b/service/resource-directory/samples/rd_main.c
new file mode 100644 (file)
index 0000000..41d5abf
--- /dev/null
@@ -0,0 +1,84 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include "rd_server.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+int g_quitFlag = 0;
+
+void handleSigInt(int signum);
+
+/*
+* This method is an entry point of Resource Directory.
+* This function should be run only on the device that it could be host device.
+*/
+
+int main()
+{
+    printf("OCResourceDirectory is starting...\n");
+
+    if (OCRDStart() != OC_STACK_OK)
+    {
+        printf("OCRDStart failed...\n");
+        return 0;
+    }
+
+    printf("OCRDStart successfully...\n");
+
+    signal(SIGINT, handleSigInt);
+    while (!g_quitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OCRDStop();
+            printf("OCStack process error\n");
+            return 0;
+        }
+    }
+
+    if (OCRDStop() != OC_STACK_OK)
+    {
+        printf("OCRDStop failed...\n");
+    }
+    else
+    {
+        printf("OCRDStop success...\n");
+    }
+
+    printf("Exiting OCResourceDirectory main loop...\n");
+    return 0;
+
+}
+
+/*
+* This is a signal handling function for SIGINT(CTRL+C).
+* A Resource Directory handle the SIGINT signal for safe exit.
+*
+* @param[in] signal
+*                 signal number of caught signal.
+*/
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        g_quitFlag = 1;
+    }
+}
diff --git a/service/resource-directory/samples/rd_publishingClient.cpp b/service/resource-directory/samples/rd_publishingClient.cpp
new file mode 100644 (file)
index 0000000..bc6e2d1
--- /dev/null
@@ -0,0 +1,147 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <iostream>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "oic_string.h"
+
+#include "rd_client.h"
+
+using namespace OC;
+
+OCResourceHandle g_curResource_t = NULL;
+OCResourceHandle g_curResource_l = NULL;
+char rdAddress[MAX_ADDR_STR_SIZE];
+uint16_t rdPort;
+
+void registerLocalResources()
+{
+    std::string resourceURI_thermostat = "/a/thermostat";
+    std::string resourceTypeName_thermostat = "core.thermostat";
+    std::string resourceURI_light = "/a/light";
+    std::string resourceTypeName_light = "core.light";
+    std::string resourceInterface = DEFAULT_INTERFACE;
+    uint8_t resourceProperty = OC_DISCOVERABLE;
+
+    OCStackResult result = OCPlatform::registerResource(g_curResource_t,
+                           resourceURI_thermostat,
+                           resourceTypeName_thermostat,
+                           resourceInterface,
+                           NULL,
+                           resourceProperty);
+
+    if (OC_STACK_OK != result)
+    {
+        throw std::runtime_error(
+            std::string("Device Resource failed to start") + std::to_string(result));
+    }
+
+    result = OCPlatform::registerResource(g_curResource_l,
+                                          resourceURI_light,
+                                          resourceTypeName_light,
+                                          resourceInterface,
+                                          NULL,
+                                          resourceProperty);
+
+    if (OC_STACK_OK != result)
+    {
+        throw std::runtime_error(
+            std::string("Device Resource failed to start") + std::to_string(result));
+    }
+}
+
+void printHelp()
+{
+    std::cout << std::endl;
+    std::cout << "********************************************" << std::endl;
+    std::cout << "*  method Type : 1 - Discover RD           *" << std::endl;
+    std::cout << "*  method Type : 2 - Publish               *" << std::endl;
+    std::cout << "*  method Type : 3 - Update                *" << std::endl;
+    std::cout << "*  method Type : 4 - Delete                *" << std::endl;
+    std::cout << "*  method Type : 5 - Status                *" << std::endl;
+    std::cout << "********************************************" << std::endl;
+    std::cout << std::endl;
+}
+
+int biasFactorCB(char addr[MAX_ADDR_STR_SIZE], uint16_t port)
+{
+    OICStrcpy(rdAddress, MAX_ADDR_STR_SIZE, addr);
+    rdPort = port;
+    std::cout << "RD Address is : " <<  addr << ":" << port << std::endl;
+    return 0;
+}
+
+int main(int argc , char *argv[])
+{
+    int in;
+    PlatformConfig cfg;
+
+    OCPlatform::Configure(cfg);
+
+    std::cout << "Created Platform..." << std::endl;
+
+    registerLocalResources();
+
+    while (1)
+    {
+        sleep(2);
+
+        if (g_curResource_t == NULL || g_curResource_l == NULL)
+        {
+            continue;
+        }
+        printHelp();
+
+        in = 0;
+        std::cin >> in;
+
+        if (std::cin.fail())
+        {
+            std::cin.clear();
+            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+            std::cout << "Invalid input type, please try again" << std::endl;
+            continue;
+        }
+
+        try
+        {
+            switch ((int)in)
+            {
+                case 1:
+                    OCRDDiscover(biasFactorCB);
+                    break;
+                case 2:
+                    OCRDPublish(rdAddress, rdPort, 2, g_curResource_t, g_curResource_l);
+                    break;
+                case 3:
+                    break;
+                default:
+                    std::cout << "Invalid input, please try again" << std::endl;
+                    break;
+            }
+        }
+        catch (OCException e)
+        {
+            std::cout << "Caught OCException [Code: " << e.code() << " Reason: " << e.reason() << std::endl;
+        }
+    }
+    return 0;
+}
diff --git a/service/resource-directory/samples/rd_queryClient.cpp b/service/resource-directory/samples/rd_queryClient.cpp
new file mode 100644 (file)
index 0000000..4a24c9f
--- /dev/null
@@ -0,0 +1,79 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <vector>
+
+#include "OCApi.h"
+#include "OCPlatform.h"
+
+bool g_foundResource = true;
+
+void foundResource(std::shared_ptr< OC::OCResource > resource)
+{
+    try
+    {
+        std::cout << "Found resource response." << std::endl;
+        if (resource)
+        {
+            if (resource->uri() == "/a/light")
+            {
+                std::cout << "Found Resource at @ URI: " << resource->uri() << "\tHost Address: " <<
+                          resource->host() << std::endl;
+            }
+        }
+        else
+        {
+            std::cout << "Resource is invalid " << resource->uri() << std::endl;
+        }
+        g_foundResource = false;
+        exit(0);
+    }
+    catch (std::exception &ex)
+    {
+        std::cout << "Exception: " << ex.what() << " in foundResource" << std::endl;
+        exit(1);
+    }
+}
+
+int main()
+{
+    OC::PlatformConfig cfg;
+    OC::OCPlatform::Configure(cfg);
+    bool sendRequest = true;
+
+    std::cout << "Created Platform..." << std::endl;
+
+    while (g_foundResource)
+    {
+        try
+        {
+            if (sendRequest)
+            {
+                sendRequest = false;
+                std::cout << "Finding Resource light" << std::endl;
+                OC::OCPlatform::findResource("",  "/oic/res?rt=core.light", CT_DEFAULT, &foundResource);
+            }
+        }
+        catch (OC::OCException &ex)
+        {
+            sendRequest = true;
+            std::cout << "Exception finding resources : " << ex.reason() << std::endl;
+        }
+    }
+}
diff --git a/service/resource-directory/src/internal/rd_storage.c b/service/resource-directory/src/internal/rd_storage.c
new file mode 100644 (file)
index 0000000..878cc36
--- /dev/null
@@ -0,0 +1,159 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include "rd_storage.h"
+
+#include <pthread.h>
+
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "logger.h"
+
+#include "rd_payload.h"
+
+#define TAG  PCF("RDStorage")
+
+pthread_mutex_t storageMutex = PTHREAD_MUTEX_INITIALIZER;
+// This variable holds the published resources on the RD.
+static OCRDStorePublishResources *g_rdStorage = NULL;
+
+static void printStoragedResources(OCRDStorePublishResources *payload)
+{
+    OC_LOG_V(DEBUG, TAG, "Print Storage Resources ... ");
+    for (OCRDStorePublishResources *temp = payload; temp; temp = temp->next)
+    {
+        if (temp->publishResource)
+        {
+            OCRDPublishPayloadLog(DEBUG, TAG, temp->publishResource);
+        }
+    }
+}
+
+OCStackResult OCRDStorePublishedResources(OCRDPublishPayload *payload)
+{
+    OCRDStorePublishResources *storeResource = OICCalloc(1, sizeof(OCRDStorePublishResources));
+    if (!storeResource)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory for OCRDStorePublishResources.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OC_LOG_V(DEBUG, TAG, "Storing Resources ... ");
+
+    OCRDLinksPayload* linksPayload = NULL;
+    for ( OCRDLinksPayload* links = payload->links ; links; links = links->next)
+    {
+        OCRDLinksPayloadCreate(links->href, links->rt, links->itf, &linksPayload);
+    }
+
+    storeResource->publishResource = OCRDPublishPayloadCreate(payload->ttl, linksPayload);
+    if (!storeResource->publishResource)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory for OCRDPublishResources.");
+        OICFree(storeResource);
+        return OC_STACK_NO_MEMORY;
+    }
+    storeResource->next = NULL;
+
+    pthread_mutex_lock(&storageMutex);
+    if (g_rdStorage)
+    {
+        OCRDStorePublishResources *temp = g_rdStorage;
+        while (temp->next)
+        {
+            temp = temp->next;
+        }
+        temp->next = storeResource;
+    }
+    else
+    {
+        g_rdStorage = storeResource;
+    }
+    pthread_mutex_unlock(&storageMutex);
+
+    printStoragedResources(g_rdStorage);
+    return OC_STACK_OK;
+}
+
+OCStackResult OCRDCheckPublishedResource(const char *interfaceType, const char *resourceType,
+        char **uri, char **rt, char **itf)
+{
+    // ResourceType and InterfaceType if both are NULL it will return. If either is
+    // not null it will continue execution.
+    if (!resourceType && !interfaceType)
+    {
+        OC_LOG_V(DEBUG, TAG, "Missing resource type and interace type.");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OC_LOG_V(DEBUG, TAG, "Check Resource in RD");
+
+    if (g_rdStorage && g_rdStorage->publishResource && g_rdStorage->publishResource->links)
+    {
+        for (OCRDLinksPayload *tLinks = g_rdStorage->publishResource->links; tLinks; tLinks = tLinks->next)
+        {
+            bool found = false;
+            // If either rt or itf are NULL, it should skip remaining code execution.
+            if (!tLinks->rt || !tLinks->itf)
+            {
+                OC_LOG_V(DEBUG, TAG, "Either resource type and interface type are missing.");
+                continue;
+            }
+            OC_LOG_V(DEBUG, TAG, "Resource Type: %s %s", resourceType, tLinks->rt);
+            OC_LOG_V(DEBUG, TAG, "Resource Type: %s %s", interfaceType, tLinks->itf);
+            if (resourceType && strcmp(resourceType, tLinks->rt) == 0)
+            {
+                found = true;
+            }
+
+            if (interfaceType && strcmp(interfaceType, tLinks->itf) == 0)
+            {
+                found = true;
+            }
+
+            if (found)
+            {
+                *uri = OICStrdup(tLinks->href);
+                if (!*uri)
+                {
+                    OC_LOG_V(ERROR, TAG, "Copy failed..");
+                    return false;
+                }
+                *rt = OICStrdup(tLinks->rt);
+                if (!*rt)
+                {
+                    OC_LOG_V(ERROR, TAG, "Copy failed..");
+                    OICFree(*uri);
+                    return false;
+                }
+                *itf = OICStrdup(tLinks->itf);
+                if (!*itf)
+                {
+                    OC_LOG_V(ERROR, TAG, "Copy failed..");
+                    OICFree(*uri);
+                    OICFree(*rt);
+                    return false;
+                }
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
diff --git a/service/resource-directory/src/internal/rd_storage.h b/service/resource-directory/src/internal/rd_storage.h
new file mode 100644 (file)
index 0000000..cc55425
--- /dev/null
@@ -0,0 +1,47 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#ifndef _RESOURCE_DIRECTORY_SERVER_STORAGE_H_
+#define _RESOURCE_DIRECTORY_SERVER_STORAGE_H_
+
+#include "rd_types.h"
+
+/** Stucture holding Published Resources on the Resource Directory. */
+typedef struct OCRDStorePublishResources
+{
+    /** Publish resource. */
+    OCRDPublishPayload *publishResource;
+    /** Linked list pointing to next published resource. */
+    struct OCRDStorePublishResources *next;
+} OCRDStorePublishResources;
+
+/**
+ * Stores the publish resources.
+ *
+ * @param payload RDPublish payload sent from the remote device.
+ *
+ * @return ::OC_STACK_OK upon success, ::OC_STACK_ERROR in case of error.
+ */
+OCStackResult OCRDStorePublishedResources(OCRDPublishPayload *payload);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //_RESOURCE_DIRECTORY_SERVER_STORAGE_H_
diff --git a/service/resource-directory/src/rd_client.c b/service/resource-directory/src/rd_client.c
new file mode 100644 (file)
index 0000000..63077ca
--- /dev/null
@@ -0,0 +1,220 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <stdarg.h>
+
+#include "rd_client.h"
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+#include "rd_payload.h"
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define OC_RD_PUBLISH_TTL 86400
+
+#define TAG  PCF("RDClient")
+
+static OCStackResult sendRequest(OCMethod method, char *uri, OCDevAddr *addr,
+        OCPayload *payload, OCCallbackData cbData)
+{
+    OCDoHandle handle;
+    OCStackResult result;
+
+    result = OCDoResource(&handle,
+        method,
+        uri,
+        addr,
+        payload,
+        CT_ADAPTER_IP,
+        OC_LOW_QOS,
+        &cbData,
+        NULL,
+        0);
+
+    if (result == OC_STACK_OK)
+    {
+        OC_LOG_V(DEBUG, TAG, "Resource Directory send successful...");
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "Resource Directory send failed...");
+    }
+
+    return result;
+}
+
+static OCStackApplicationResult handlePublishCB(void *ctx,
+        OCDoHandle handle, OCClientResponse *clientResponse)
+{
+    OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
+    OC_LOG_V(DEBUG, TAG, "Successfully published resources.");
+
+    // TOOO: Stop multicast traffic on the client.
+
+    return ret;
+}
+
+static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB)
+{
+    OC_LOG_V(DEBUG, TAG, "\tAddress of the RD: %s:%d", clientResponse->devAddr.addr,
+            clientResponse->devAddr.port);
+
+    OCRDPayload *payload = (OCRDPayload *) clientResponse->payload;
+    OCRDPayloadLog(DEBUG, TAG, payload);
+
+    // TODO: Multiple Resource Directory will have different biasFactor,
+    // needs to cache here detail
+    // and after certain timeout then decide based on the biasFactor.
+    //if (biasFactor > 75)
+    if (clientCB)
+    {
+        clientCB(clientResponse->devAddr.addr, clientResponse->devAddr.port);
+    }
+}
+
+static OCStackApplicationResult handleDiscoverCB(void *ctx,
+        OCDoHandle handle, OCClientResponse *clientResponse)
+{
+    OC_LOG(DEBUG, TAG, "Found Resource Directory");
+    OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION;
+
+    OCRDClientContextCB *cb = (OCRDClientContextCB *)ctx;
+    if (!cb)
+    {
+        OC_LOG(ERROR, TAG, "RD Context Invalid Parameters.");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if (cb->context != (void *) DEFAULT_CONTEXT_VALUE)
+    {
+        OC_LOG(ERROR, TAG, "RD Context Invalid Context Value Parameters.");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OC_LOG(DEBUG, TAG, "Callback Context for DISCOVER query received successfully.");
+
+    if (clientResponse && clientResponse->result == OC_STACK_OK)
+    {
+        retreiveRDDetails(clientResponse, cb->cbFunc);
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Discovery of RD Failed");
+    }
+
+    OICFree(cb);
+
+    return ret;
+}
+
+OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor)
+{
+    if (!cbBiasFactor)
+    {
+        OC_LOG(DEBUG, TAG, "No callback function specified.");
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    /* Start a discovery query*/
+    char queryUri[MAX_URI_LENGTH] = { '\0' };
+    snprintf(queryUri, MAX_URI_LENGTH, "coap://%s%s", OC_MULTICAST_PREFIX, OC_RSRVD_RD_URI);
+
+    OC_LOG_V(DEBUG, TAG, "Querying RD: %s\n", queryUri);
+
+    OCRDClientContextCB *cbContext = OICCalloc(1, sizeof(OCRDClientContextCB));
+    if (!cbContext)
+    {
+        OC_LOG(ERROR, TAG, "Failed allocating memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    cbContext->context = (void *)DEFAULT_CONTEXT_VALUE;
+    cbContext->cbFunc = cbBiasFactor;
+
+    OCCallbackData cbData;
+    cbData.cb = handleDiscoverCB;
+    cbData.context = (void *)(cbContext);
+    cbData.cd = NULL;
+
+    return sendRequest(OC_REST_DISCOVER, queryUri, NULL, NULL, cbData);
+}
+
+OCStackResult OCRDPublish(char *addr, uint16_t port, int numArg, ... )
+{
+    if (!addr)
+    {
+        OC_LOG_V(ERROR, TAG, "RD address not specified.");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    char targetUri[MAX_URI_LENGTH];
+    snprintf(targetUri, MAX_URI_LENGTH, "coap://%s:%d%s?rt=%s", addr, port,
+            OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
+    OC_LOG_V(DEBUG, TAG, "Target URI : %s", targetUri);
+
+    // Gather all resources locally and do publish
+    OCCallbackData cbData = { 0 };
+    cbData.cb = &handlePublishCB;
+    cbData.cd = NULL;
+    cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+
+    OCRDLinksPayload* linksPayload = NULL;
+
+    va_list arguments;
+    va_start (arguments, numArg);
+
+    for (int j = 0 ; j < numArg; j++)
+    {
+        OCResourceHandle handle = va_arg(arguments, OCResourceHandle);
+        if (handle)
+        {
+            const char* uri = OCGetResourceUri(handle);
+            const char* rt  = OCGetResourceTypeName(handle, 0);
+            const char* itf = OCGetResourceInterfaceName(handle, 0);
+            if (uri && rt && itf)
+            {
+                OCRDLinksPayloadCreate(uri, rt, itf, &linksPayload);
+            }
+        }
+    }
+    va_end(arguments);
+
+    OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_PUBLISH);
+    if (!rdPayload)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+    rdPayload->rdPublish = OCRDPublishPayloadCreate(OC_RD_PUBLISH_TTL, linksPayload);
+    if (!rdPayload->rdPublish)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCDevAddr rdAddr = { 0 };
+    OICStrcpy(rdAddr.addr, MAX_ADDR_STR_SIZE, addr);
+    rdAddr.port = port;
+
+    OCRDPayloadLog(DEBUG, TAG, rdPayload);
+
+    return sendRequest(OC_REST_POST, targetUri, &rdAddr, (OCPayload *)rdPayload, cbData);
+}
diff --git a/service/resource-directory/src/rd_payload.c b/service/resource-directory/src/rd_payload.c
new file mode 100644 (file)
index 0000000..c025f78
--- /dev/null
@@ -0,0 +1,645 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include "rd_payload.h"
+
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+#include "octypes.h"
+#include "ocstack.h"
+#include "logger.h"
+
+#define TAG PCF("OCRDPayload")
+
+#define CBOR_ROOT_ARRAY_LENGTH 2
+#define CBOR_LINK_ARRAY_LENGTH 3
+
+static void linksPayloadDestroy(OCRDLinksPayload *linkPayload)
+{
+    OCRDLinksPayload *links = linkPayload;
+
+    while (links)
+    {
+        OICFree(links->href);
+        OICFree(links->rt);
+        OICFree(links->itf);
+        OCRDLinksPayload *tmp = links;
+        links = links->next;
+        OICFree(tmp);
+    }
+}
+
+OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPayload, size_t *size)
+{
+    if (!outPayload || !size)
+    {
+        OC_LOG_V(ERROR, TAG, "Invalid parameters.");
+        return OC_STACK_ERROR;
+    }
+
+    *outPayload = (uint8_t *)OICCalloc(1, MAX_REQUEST_LENGTH);
+    if (!*outPayload)
+    {
+        goto no_memory;
+    }
+
+    *size = MAX_REQUEST_LENGTH;
+
+    OCRDPayloadLog(DEBUG, TAG, rdPayload);
+
+    CborEncoder encoder;
+    int flags = 0;
+    cbor_encoder_init(&encoder, *outPayload, *size, flags);
+
+    CborEncoder rootArray;
+    CborError cborEncoderResult;
+    cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, CBOR_ROOT_ARRAY_LENGTH);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed creating cbor array.");
+        goto exit;
+    }
+
+    cborEncoderResult = cbor_encode_uint(&rootArray, rdPayload->base.type);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed setting rdPayload->base.type.");
+        goto exit;
+    }
+
+    CborEncoder map;
+    cborEncoderResult = cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed creating cbor map.");
+        goto exit;
+    }
+
+    cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_CONTENT_TYPE,
+        sizeof(OC_RSRVD_CONTENT_TYPE) - 1);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed setting content type.");
+        goto exit;
+    }
+
+    cborEncoderResult = cbor_encode_uint(&map, rdPayload->payloadType);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed setting rdPayload->payloadType.");
+        goto exit;
+    }
+
+    if (rdPayload->payloadType == RD_PAYLOAD_TYPE_DISCOVERY)
+    {
+        if (rdPayload->rdDiscovery && rdPayload->rdDiscovery->sel)
+        {
+            cborEncoderResult = cbor_encode_text_string(&map,
+                OC_RSRVD_RD_DISCOVERY_SEL, sizeof(OC_RSRVD_RD_DISCOVERY_SEL) -1);
+            if (CborNoError != cborEncoderResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed setting discovery sel type.");
+                goto exit;
+            }
+            cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdDiscovery->sel);
+            if (CborNoError != cborEncoderResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed setting discovery sel value.");
+                goto exit;
+            }
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "Missing sel parameter in the discovery payload.");
+            goto exit;
+        }
+    }
+    else if (rdPayload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
+    {
+        cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish ttl type.");
+            goto exit;
+        }
+
+        cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdPublish->ttl);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish ttl value.");
+            goto exit;
+        }
+
+        CborEncoder linksArray;
+        cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish links type.");
+            goto exit;
+        }
+
+        cborEncoderResult = cbor_encoder_create_array(&map, &linksArray, CborIndefiniteLength);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed setting publish links array.");
+            goto exit;
+        }
+
+        {
+            OCRDLinksPayload *rtPtr = rdPayload->rdPublish->links;
+            while(rtPtr)
+            {
+                CborEncoder linksMap;
+                cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap, CBOR_LINK_ARRAY_LENGTH);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish map.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_HREF,
+                        sizeof(OC_RSRVD_HREF) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish href type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->href,
+                        strlen(rtPtr->href));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish href value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_INTERFACE,
+                        sizeof(OC_RSRVD_INTERFACE) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish itf type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->itf,
+                        strlen(rtPtr->itf));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish itf value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_RESOURCE_TYPE,
+                        sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish rt type.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->rt,
+                        strlen(rtPtr->rt));
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed setting publish rt value.");
+                    goto exit;
+                }
+
+                cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap);
+                if (CborNoError != cborEncoderResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed closing linksMap publish map.");
+                    goto exit;
+                }
+
+                rtPtr = rtPtr->next;
+            }
+        }
+        cborEncoderResult = cbor_encoder_close_container(&map, &linksArray);
+        if (CborNoError != cborEncoderResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed closing linksArray container.");
+            goto exit;
+        }
+    }
+
+    cborEncoderResult = cbor_encoder_close_container(&rootArray, &map);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed closing map container.");
+        goto exit;
+    }
+
+    cborEncoderResult = cbor_encoder_close_container(&encoder, &rootArray);
+    if (CborNoError != cborEncoderResult)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed closing encoder container.");
+        goto exit;
+    }
+
+    *size = encoder.ptr - *outPayload;
+    uint8_t *tempPayload = (uint8_t *)OICRealloc(*outPayload, *size);
+    if (!tempPayload)
+    {
+        goto no_memory;
+    }
+
+    *outPayload = tempPayload;
+    return OC_STACK_OK;
+
+no_memory:
+    OC_LOG_V(ERROR, TAG, "Memory allocation failed.");
+    OICFree(*outPayload);
+    return OC_STACK_NO_MEMORY;
+
+exit:
+    OICFree(*outPayload);
+    return OC_STACK_ERROR;
+}
+
+OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPayload)
+{
+    CborValue *rdCBORPayload = (CborValue *)cborPayload;
+    OCRDPayload *rdPayload = NULL;
+
+    if (!cbor_value_is_map(rdCBORPayload))
+    {
+        OC_LOG_V(ERROR, TAG, "RD CBOR Payload is not in map format.");
+        return OC_STACK_ERROR;
+    }
+    else
+    {
+        CborValue curVal;
+        CborError cborFindResult;
+        cborFindResult = cbor_value_map_find_value(rdCBORPayload,
+            OC_RSRVD_CONTENT_TYPE, &curVal);
+        if (CborNoError != cborFindResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE type in the payload.");
+            goto exit;
+        }
+
+        int payloadType = 0 ;
+        if (cbor_value_is_valid(&curVal))
+        {
+            cborFindResult = cbor_value_get_int(&curVal, &payloadType);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE value in the payload.");
+                goto exit;
+            }
+        }
+
+        rdPayload = OCRDPayloadCreate(payloadType);
+        if (!rdPayload)
+        {
+            goto no_memory;
+        }
+
+        if (RD_PAYLOAD_TYPE_DISCOVERY == payloadType)
+        {
+            cborFindResult = cbor_value_map_find_value(rdCBORPayload,
+                OC_RSRVD_RD_DISCOVERY_SEL, &curVal);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_RD_DISCOVERY_SEL type in the payload.");
+                goto exit;
+            }
+
+            int biasFactor = 0;
+            if (cbor_value_is_valid(&curVal))
+            {
+                cborFindResult = cbor_value_get_int(&curVal, &biasFactor);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_RD_DISCOVERY_SEL value in the payload.");
+                    goto exit;
+                }
+            }
+
+            rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(biasFactor);
+            if (!rdPayload->rdDiscovery)
+            {
+                goto no_memory;
+            }
+        }
+        else
+        {    // TTL
+            int ttl = 0;
+            cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_TTL, &curVal);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL type in the payload.");
+                goto exit;
+            }
+
+            cborFindResult = cbor_value_get_int(&curVal, &ttl);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL value in the payload.");
+                goto exit;
+            }
+
+            // Link Array
+            CborValue linkArray;
+            cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_LINKS, &linkArray);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_LINKS type in the payload.");
+                goto exit;
+            }
+
+            CborValue linkVal;
+            cborFindResult = cbor_value_enter_container(&linkArray, &linkVal);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed entering linkArray container in the payload.");
+                goto exit;
+            }
+
+            OCRDLinksPayload *links = NULL;
+            while(cbor_value_is_map(&linkVal))
+            {
+                char *href = NULL;
+                char *itf = NULL;
+                char *rt = NULL;
+                size_t len;
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_HREF, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &href, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF value in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_INTERFACE, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &itf, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE value in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE type in the payload.");
+                    goto exit;
+                }
+
+                cborFindResult = cbor_value_dup_text_string(&curVal, &rt, &len, NULL);
+                if (CborNoError != cborFindResult)
+                {
+                    OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE value in the payload.");
+                    goto exit;
+                }
+
+                OCRDLinksPayloadCreate(href, rt, itf, &links);
+                if (!links)
+                {
+                    goto no_memory;
+                }
+
+                cborFindResult = cbor_value_advance(&linkVal);
+                if (CborNoError != cborFindResult)
+                {
+                        OC_LOG_V(ERROR, TAG, "Failed advancing the linkVal payload.");
+                        goto exit;
+                }
+            }
+            cborFindResult = cbor_value_advance(&linkArray);
+            if (CborNoError != cborFindResult)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed advancing the linkArray payload.");
+                goto exit;
+            }
+            rdPayload->rdPublish = OCRDPublishPayloadCreate(ttl, links);
+            if (!rdPayload->rdPublish)
+            {
+                goto no_memory;
+            }
+        }
+
+        OCRDPayloadLog(DEBUG, TAG, rdPayload);
+        cborFindResult = cbor_value_advance(rdCBORPayload);
+        if (CborNoError != cborFindResult)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
+            goto exit;
+        }
+        *outPayload = (OCPayload *)rdPayload;
+    }
+    return OC_STACK_OK;
+no_memory:
+    OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
+    OCRDPayloadDestroy(rdPayload);
+    return OC_STACK_NO_MEMORY;
+
+exit:
+    OCRDPayloadDestroy(rdPayload);
+    return OC_STACK_ERROR;
+}
+
+OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType)
+{
+    OCRDPayload *rdPayload = (OCRDPayload *)OICCalloc(1, sizeof(OCRDPayload));
+
+    if (!rdPayload)
+    {
+        return NULL;
+    }
+
+    rdPayload->base.type = PAYLOAD_TYPE_RD;
+    rdPayload->payloadType = payloadType;
+
+    return rdPayload;
+}
+
+void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
+        OCRDLinksPayload **linksPayload)
+{
+    OCRDLinksPayload *payload = OICCalloc(1, sizeof(OCRDLinksPayload));
+    if (!payload)
+    {
+        goto no_memory;
+    }
+
+    payload->href = OICStrdup(uri);
+    if (!payload->href)
+    {
+        goto no_memory;
+    }
+
+    payload->rt = OICStrdup(rt);
+    if (!payload->rt)
+    {
+        goto no_memory;
+    }
+
+    payload->itf = OICStrdup(itf);
+    if (!payload->itf)
+    {
+        goto no_memory;
+    }
+
+    payload->next = NULL;
+
+    if (*linksPayload == NULL)
+    {
+        *linksPayload = payload;
+    }
+    else
+    {
+        OCRDLinksPayload *temp = *linksPayload;
+        while (temp->next)
+        {
+            temp = temp->next;
+        }
+        temp->next = payload;
+    }
+    return;
+
+no_memory:
+    OC_LOG_V(ERROR, TAG, "Memory allocation failed.");
+    linksPayloadDestroy(payload);
+}
+
+OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor)
+{
+    OCRDDiscoveryPayload *discoveryPayload = OICCalloc(1, sizeof(OCRDDiscoveryPayload));
+
+    if (!discoveryPayload)
+    {
+        return NULL;
+    }
+    discoveryPayload->sel = biasFactor;
+
+    return discoveryPayload;
+}
+
+
+OCRDPublishPayload* OCRDPublishPayloadCreate(int ttl,
+        OCRDLinksPayload *linksPayload)
+{
+    OCRDPublishPayload *rdPublish = OICCalloc(1, sizeof(OCRDPublishPayload));
+    if (!rdPublish)
+    {
+        return NULL;
+    }
+
+    //TODO: Find way of device device id.
+    // rdPayload->rdPublish->id = (uint8_t *)OICCalloc(1, UUID_SIZE);
+    // memcpy(rdPayload->rdPublish->id, , UUID_SIZE);
+    //TODO: Find way of device device name.
+    // rdPayload->rdPublish->n = (char*)OICCalloc(1, strlen(name));
+    // memcpy(rdPayload->rdPublish->n, , strlen(name));
+    rdPublish->ttl = ttl; // TODO Expose API to allow user to set this value.
+    rdPublish->links = linksPayload;
+
+    return rdPublish;
+}
+
+void OCRDPayloadDestroy(OCRDPayload *payload)
+{
+    if (!payload)
+    {
+        return;
+    }
+
+    if (payload->rdDiscovery)
+    {
+        OICFree(payload->rdDiscovery);
+    }
+
+    if (payload->rdPublish)
+    {
+        if (payload->rdPublish->links)
+        {
+            linksPayloadDestroy(payload->rdPublish->links);
+        }
+
+        if (payload->rdPublish->deviceName.deviceName)
+        {
+            OICFree(payload->rdPublish->deviceName.deviceName);
+        }
+
+        OICFree(payload->rdPublish);
+    }
+
+    OICFree(payload);
+}
+
+void OCRDPayloadLog(LogLevel level, const char *tag, const OCRDPayload *payload)
+{
+    if (!payload)
+    {
+        return;
+    }
+
+    OC_LOG_V(level, tag, "BaseType : %d", payload->base.type);
+    OC_LOG_V(level, tag, "RD Payload Type : %d", payload->payloadType);
+
+    if (payload->rdDiscovery)
+    {
+        OC_LOG_V(level, tag, "RD Payload Discovery BIAS : %d", payload->rdDiscovery->sel);
+    }
+    OCRDPublishPayloadLog(level, tag, payload->rdPublish);
+}
+
+void OCRDPublishPayloadLog(LogLevel level, const char *tag, const OCRDPublishPayload *rdPublish)
+{
+    if (rdPublish)
+    {
+        if (rdPublish->deviceName.deviceName)
+        {
+            OC_LOG_V(level, tag, "RD Payload Pulish Name : %s", rdPublish->deviceName.deviceName);
+        }
+
+        if (rdPublish->deviceId.id)
+        {
+            OC_LOG_V(level, tag, "RD Payload Publish ID : %s",  rdPublish->deviceId.id);
+        }
+
+        OC_LOG_V(level, tag, "RD Payload Publish TTL : %d", rdPublish->ttl);
+
+        if (rdPublish->links)
+        {
+            for (OCRDLinksPayload *temp = rdPublish->links; temp; temp = temp->next)
+            {
+                OC_LOG_V(level, tag, "RD Payload Publish Link HREF : %s", temp->href);
+                OC_LOG_V(level, tag, "RD Payload Publish Link RT : %s", temp->rt);
+                OC_LOG_V(level, tag, "RD Payload Publish Link ITF : %s", temp->itf);
+            }
+        }
+    }
+}
diff --git a/service/resource-directory/src/rd_server.c b/service/resource-directory/src/rd_server.c
new file mode 100644 (file)
index 0000000..b95def3
--- /dev/null
@@ -0,0 +1,198 @@
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//******************************************************************
+//
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include "rd_server.h"
+
+#include "rd_types.h"
+#include "rd_payload.h"
+#include "rd_storage.h"
+
+#include "logger.h"
+
+#define TAG  PCF("RDServer")
+
+// This is temporary hardcoded value for bias factor.
+#define OC_RD_DISC_SEL 100
+
+static OCStackResult sendResponse(const OCEntityHandlerRequest *ehRequest, OCRDPayload *rdPayload)
+{
+    OCEntityHandlerResponse response = { 0 };
+    response.requestHandle = ehRequest->requestHandle;
+    response.resourceHandle = ehRequest->resource;
+    response.ehResult = OC_EH_OK;
+    response.payload = (OCPayload*)(rdPayload);
+    response.payload->type = PAYLOAD_TYPE_RD;
+
+    return OCDoResponse(&response);
+}
+
+/**
+ * This internal method handles RD discovery request.
+ * Responds with the RD discovery payload message.
+ */
+static OCEntityHandlerResult handleGetRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    if (!ehRequest)
+    {
+        OC_LOG_V(DEBUG, TAG, "Invalid request pointer.");
+        return OC_EH_ERROR;
+    }
+
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OC_LOG_V(DEBUG, TAG, "Received OC_REST_GET from client with query: %s.", ehRequest->query);
+
+    OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_DISCOVERY);
+    if (!rdPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+
+    rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(OC_RD_DISC_SEL);
+    if (!rdPayload->rdDiscovery)
+    {
+        OCRDPayloadDestroy(rdPayload);
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OCRDPayloadLog(DEBUG, TAG, rdPayload);
+
+    if (sendResponse(ehRequest, rdPayload) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "Sending response failed.");
+        ehResult = OC_EH_ERROR;
+    }
+
+    OCRDPayloadDestroy(rdPayload);
+
+    return ehResult;
+}
+
+/**
+ * This internal method handles RD publish request.
+ * Responds with the RD success message.
+ */
+static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    OC_LOG_V(DEBUG, TAG, "Received OC_REST_PUT from client with query: %s.", ehRequest->query);
+
+    if (!ehRequest)
+    {
+        OC_LOG_V(DEBUG, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRDPayload *payload = (OCRDPayload *)ehRequest->payload;
+    if (payload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
+    {
+        OCRDStorePublishedResources(payload->rdPublish);
+    }
+
+    return ehResult;
+}
+
+/*
+ * This internal method is the entity handler for RD resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+static OCEntityHandlerResult rdEntityHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *ehRequest, void *callbackParameter)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if (!ehRequest)
+    {
+        return ehRet;
+    }
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG_V(DEBUG, TAG, "Flag includes OC_REQUEST_FLAG.");
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+            case OC_REST_DISCOVER:
+                handleGetRequest(ehRequest);
+                break;
+            case OC_REST_POST:
+                handlePublishRequest(ehRequest);
+                break;
+            case OC_REST_PUT:
+            case OC_REST_DELETE:
+            case OC_REST_OBSERVE:
+            case OC_REST_OBSERVE_ALL:
+            case OC_REST_CANCEL_OBSERVE:
+            case OC_REST_PRESENCE:
+            case OC_REST_NOMETHOD:
+                break;
+        }
+    }
+
+    return ehRet;
+}
+
+/**
+ * Starts resource directory server and registers RD resource
+ */
+OCStackResult OCRDStart()
+{
+    OCStackResult result = OCInit(NULL, 0, OC_CLIENT_SERVER);
+    OCResourceHandle rdHandle = NULL;
+
+    if (result == OC_STACK_OK)
+    {
+        result = OCCreateResource(&rdHandle,
+                                  OC_RSRVD_RESOURCE_TYPE_RD,
+                                  OC_RSRVD_INTERFACE_DEFAULT,
+                                  OC_RSRVD_RD_URI,
+                                  rdEntityHandler,
+                                  NULL,
+                                  (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE));
+
+        if (result == OC_STACK_OK)
+        {
+            OC_LOG_V(DEBUG, TAG, "Resource Directory Started.");
+        }
+        else
+        {
+            OC_LOG(ERROR, TAG, "Failed starting Resource Directory.");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * Stops resource directory server
+ */
+OCStackResult OCRDStop()
+{
+    OCStackResult result = OCStop();
+
+    if (result == OC_STACK_OK)
+    {
+        OC_LOG_V(DEBUG, TAG, "Resource Directory Stopped.");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Failed stopping Resource Directory.");
+    }
+    return result;
+}