Publishing project from SPIN to public 87/78387/1
authorRamasamy <ram.kannan@samsung.com>
Tue, 5 Jul 2016 09:16:45 +0000 (14:46 +0530)
committerRamasamy <ram.kannan@samsung.com>
Tue, 5 Jul 2016 09:16:51 +0000 (14:46 +0530)
- publishing to www.tizen.org
- repository: iot-broker-service to remote-rsc-svc
- branch: devel/ibs_api to tizen

signed-off-by: Ram <ram.kannan@samsung.com>
Change-Id: I8d06e7bc6d54c69bf3da335dec0edcdcd9c3d282

90 files changed:
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2 [new file with mode: 0644]
doc/rrs_doc.h [new file with mode: 0644]
include/rrs.h [new file with mode: 0644]
include/rrs_control_data.h [new file with mode: 0644]
include/rrs_error.h [new file with mode: 0644]
include/rrs_event_data.h [new file with mode: 0644]
include/rrs_main.h [new file with mode: 0644]
include/rrs_resource.h [new file with mode: 0644]
packaging/capi-rrs-client.manifest [new file with mode: 0644]
packaging/remote-resource-service.service [new file with mode: 0755]
packaging/remote-resource-service.spec [new file with mode: 0644]
packaging/rrs-serverd.manifest [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0644]
src/brokers/CMakeLists.txt [new file with mode: 0644]
src/brokers/sensor_framework/CMakeLists.txt [new file with mode: 0755]
src/brokers/sensor_framework/SensorFrameworkBroker.cpp [new file with mode: 0755]
src/brokers/sensor_framework/SensorFrameworkBroker.h [new file with mode: 0755]
src/client/CMakeLists.txt [new file with mode: 0644]
src/client/ClientManager.cpp [new file with mode: 0644]
src/client/ClientManager.h [new file with mode: 0644]
src/client/FindResourceInfo.cpp [new file with mode: 0644]
src/client/FindResourceInfo.h [new file with mode: 0644]
src/client/ResourceClient.cpp [new file with mode: 0644]
src/client/ResourceClient.h [new file with mode: 0644]
src/client/RrsManager.cpp [new file with mode: 0644]
src/client/RrsManager.h [new file with mode: 0644]
src/client/rrs-client.pc.in [new file with mode: 0644]
src/client/rrs_resource.cpp [new file with mode: 0644]
src/common/BaseLock.cpp [new file with mode: 0755]
src/common/BaseLock.h [new file with mode: 0755]
src/common/CMakeLists.txt [new file with mode: 0755]
src/common/IotconToRrs.cpp [new file with mode: 0644]
src/common/IotconToRrs.h [new file with mode: 0644]
src/common/Json.cpp [new file with mode: 0644]
src/common/Json.h [new file with mode: 0644]
src/common/Mutex.cpp [new file with mode: 0755]
src/common/Mutex.h [new file with mode: 0755]
src/common/common.cpp [new file with mode: 0755]
src/common/common.h [new file with mode: 0755]
src/common/rrs-svr-db.dat [new file with mode: 0644]
src/common/rrs.cpp [new file with mode: 0644]
src/common/rrs_common.cpp [new file with mode: 0644]
src/common/rrs_control_data.cpp [new file with mode: 0644]
src/common/rrs_event_data.cpp [new file with mode: 0644]
src/common/schema.cpp [new file with mode: 0644]
src/common/schema.h [new file with mode: 0644]
src/common/schema_types_internal.h [new file with mode: 0644]
src/common/schemas/accelerometer.json [new file with mode: 0644]
src/common/schemas/autorotation.json [new file with mode: 0644]
src/common/schemas/geomagneticrotationvector.json [new file with mode: 0644]
src/common/schemas/gravity.json [new file with mode: 0644]
src/common/schemas/gyroscope.json [new file with mode: 0644]
src/common/schemas/gyroscoperotationvector.json [new file with mode: 0644]
src/common/schemas/hrm.json [new file with mode: 0644]
src/common/schemas/hrmledgreen.json [new file with mode: 0644]
src/common/schemas/hrmledir.json [new file with mode: 0644]
src/common/schemas/hrmledred.json [new file with mode: 0644]
src/common/schemas/humidity.json [new file with mode: 0644]
src/common/schemas/light.json [new file with mode: 0644]
src/common/schemas/linearacceleration.json [new file with mode: 0644]
src/common/schemas/magnetometer.json [new file with mode: 0644]
src/common/schemas/orientation.json [new file with mode: 0644]
src/common/schemas/pressure.json [new file with mode: 0644]
src/common/schemas/proximity.json [new file with mode: 0644]
src/common/schemas/rotationvector.json [new file with mode: 0644]
src/common/schemas/rrsdiscovery.json [new file with mode: 0644]
src/common/schemas/sensorcontrol.json [new file with mode: 0644]
src/common/schemas/temperature.json [new file with mode: 0644]
src/common/schemas/uncalibratedgyroscope.json [new file with mode: 0644]
src/common/schemas/uncalibratedmagnetometer.json [new file with mode: 0644]
src/common/schemas/uv.json [new file with mode: 0644]
src/common/services_common.h [new file with mode: 0644]
src/server/CMakeLists.txt [new file with mode: 0644]
src/server/daemon/CMakeLists.txt [new file with mode: 0755]
src/server/daemon/PluginLoader.cpp [new file with mode: 0755]
src/server/daemon/PluginLoader.h [new file with mode: 0755]
src/server/daemon/ResourceQueue.cpp [new file with mode: 0755]
src/server/daemon/ResourceQueue.h [new file with mode: 0755]
src/server/daemon/ResourceServer.cpp [new file with mode: 0644]
src/server/daemon/ResourceServer.h [new file with mode: 0644]
src/server/daemon/Server.cpp [new file with mode: 0755]
src/server/daemon/Server.h [new file with mode: 0755]
src/server/daemon/ServiceManager.cpp [new file with mode: 0755]
src/server/daemon/ServiceManager.h [new file with mode: 0755]
src/server/daemon/WorkerThread.cpp [new file with mode: 0755]
src/server/daemon/WorkerThread.h [new file with mode: 0755]
src/server/daemon/main.cpp [new file with mode: 0755]
test/CMakeLists.txt [new file with mode: 0644]
test/rrs-test.cpp [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..68f852a
--- /dev/null
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.6)
+project(iot-broker_main CXX)
+
+# Setup For pkgconfig File
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "${PREFIX}/bin")
+SET(LIBDIR "${PREFIX}/lib")
+SET(INCLUDEDIR "${PREFIX}/include")
+SET(VERSION 1.0)
+
+SET(OCLIB "oc")
+SET(OCLOGGER "oc_logger")
+SET(OCLOGGER_CORE "oc_logger_core")
+SET(CA "connectivity_abstraction")
+SET(OCTBSTACK "octbstack")
+
+# Common Options
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2 -omit-frame-pointer -std=gnu++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-section -Wl,--print-gc-section")
+MESSAGE("FLAGS: ${CMAKE_CXX_FLAGS}")
+MESSAGE("FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
+
+add_definitions(-DUSE_DLOG_LOG)
+
+# Internal Debugging Options
+#add_definitions(-Wall -g -D_DEBUG)
+
+# Sub-directory
+add_subdirectory(src)
+
+# Tests
+add_subdirectory(test)
+
+FILE(GLOB RRS_HEADER include/*.h)
+INSTALL(FILES ${RRS_HEADER} DESTINATION ${INCLUDEDIR})
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644 (file)
index 0000000..91cbe82
--- /dev/null
@@ -0,0 +1,203 @@
+Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/doc/rrs_doc.h b/doc/rrs_doc.h
new file mode 100644 (file)
index 0000000..56fc348
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __RRS_DOC_H__
+#define __RRS_DOC_H__
+
+/**
+ * @ingroup    CAPI_CONVERGENCE_FRAMEWORK
+ * @defgroup   CAPI_RRS_MODULE Remote Resource Service
+ *
+ * @brief      The Remote Resource Service (RRS) provides Application and Platform
+ * Developer with APIs, enabling access to nearby Tizen resources.
+ *
+ * @section    CAPI_RRS_MODULE_HEADER Required Header
+ * \#include <rrs.h>
+ *
+ * @section    CAPI_RRS_MODULE_OVERVIEW Overview
+ *
+ * The Remote Resource Service is used to connect to resources on remote devices.
+ *
+ * @section    CAPI_RRS_MODULE_FEATURE Features
+ * Tizen Convergence - Remote Resource Service enables applications on a device
+ * to connect with the remote resources on any other Tizen device over IOTCON
+ * connectivity. New resources are introduced by adding new resource schema files.
+ * Schema files are parsed to instantiate identical resource representations on
+ * both client and server. Data communication between resource client and server
+ * happens by exchanging resource representation state data.
+ *
+ * @subsection CAPI_RRS_MODULE_API Resources
+ * Applications which use the Remote Resource Service API can discover, control,
+ * monitor and receive data events from remote resources. The API provides handles
+ * for connecting with multiple remote resources on different devices.
+ *
+ * @subsection CAPI_RRS_MODULE_SERVER RRS Server
+ * These Tizen resources created on a device are connected to the different mobile
+ * services through a service broker. The RRS server provides management for the
+ * various created resources and the service brokers.
+ *
+ *
+ * @if WEARABLE
+ * @section    CAPI_RRS_MODULE_FEATURE Related Features
+ * This API is related with the following features:
+ *  - http://tizen.org/feature/network.internet
+ *  - http://tizen.org/feature/network.bluetooth
+ *  - http://tizen.org/feature/network.wifi
+ *  - http://tizen.org/feature/network.wifi.direct
+ *  - http://tizen.org/feature/sensor.accelerometer
+ *  - http://tizen.org/feature/sensor.accelerometer.wakeup
+ *  - http://tizen.org/feature/sensor.activity_recognition
+ *  - http://tizen.org/feature/sensor.barometer
+ *  - http://tizen.org/feature/sensor.barometer.wakeup
+ *  - http://tizen.org/feature/sensor.gesture_recognition
+ *  - http://tizen.org/feature/sensor.gravity
+ *  - http://tizen.org/feature/sensor.gyroscope
+ *  - http://tizen.org/feature/sensor.gyroscope.wakeup
+ *  - http://tizen.org/feature/sensor.heart_rate_monitor
+ *  - http://tizen.org/feature/sensor.humidity
+ *  - http://tizen.org/feature/sensor.linear_acceleration
+ *  - http://tizen.org/feature/sensor.magnetometer
+ *  - http://tizen.org/feature/sensor.magnetometer.wakeup
+ *  - http://tizen.org/feature/sensor.pedometer
+ *  - http://tizen.org/feature/sensor.photometer
+ *  - http://tizen.org/feature/sensor.photometer.wakeup
+ *  - http://tizen.org/feature/sensor.proximity
+ *  - http://tizen.org/feature/sensor.proximity.wakeup
+ *  - http://tizen.org/feature/sensor.rotation_vector
+ *  - http://tizen.org/feature/sensor.temperature
+ *  - http://tizen.org/feature/sensor.tiltmeter
+ *  - http://tizen.org/feature/sensor.tiltmeter.wakeup
+ *  - http://tizen.org/feature/sensor.ultraviolet
+ *  - http://tizen.org/feature/sensor.wrist_up
+ *
+ * It is recommended to design feature related codes in your application for
+ * reliability.\n
+ *
+ * You can check if a device supports the related features for this API by using
+ * @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of
+ * your application.\n
+ *
+ * To ensure your application is only running on the device with specific
+ * features, please define the features in your manifest file using the manifest
+ * editor in the SDK.\n
+ *
+ * More details on featuring your application can be found from
+ * <a href="https://developer.tizen.org/development/tools/native-tools/manifest-text-editor#feature"><b>Feature Element</b>.</a>
+ * @endif
+ */
+
+#endif /*__RRS_DOC_H__ */
diff --git a/include/rrs.h b/include/rrs.h
new file mode 100644 (file)
index 0000000..313542b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_H_
+#define _RRS_H_
+
+#include <tizen_type.h>
+#include "rrs_main.h"
+#include "rrs_resource.h"
+#include "rrs_error.h"
+#include "rrs_event_data.h"
+#include "rrs_control_data.h"
+
+/*
+ * CAPI_RRS_MODULE
+ *
+ * This file includes all the modules
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RRS_H_ */
diff --git a/include/rrs_control_data.h b/include/rrs_control_data.h
new file mode 100644 (file)
index 0000000..d888c86
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_CONTROL_DATA_H_
+#define _RRS_CONTROL_DATA_H_
+
+#include "rrs_main.h"
+
+/**
+ * @ingroup    CAPI_RRS_CLIENT
+ * @defgroup   CAPI_RRS_CONTROL_DATA_MODULE Control data
+ *
+ * @file rrs_control_data.h
+ * @brief This file contains the RRS Control Data API
+ * @addtogroup CAPI_RRS_CONTROL_DATA_MODULE
+ * @{
+ * @brief This provides APIs related to control data handling
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief      Handle of control data.
+ * @details The handle to generate control data for controlling remote resource.
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_control_data_destroy().
+ *
+ * @see rrs_control_data_destroy()
+ */
+typedef void * rrs_control_data_h;
+
+
+/**
+ * @brief      Creates an instance of structured control data.
+ * @details This function creates an instance of structured control data and issues a new handle for it.
+ * @since_tizen 3.0
+ *
+ * @remarks @a data handle must be released using rrs_control_data_destroy().
+ *
+ * @param[in]  type            Resource type
+ * @param[out] data            The handle of newly created data instance
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_INVALID_TYPE Invalid type
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see rrs_control_data_destroy()
+ * @see rrs_control_data_clone()
+ * @see rrs_resource_e
+ */
+int rrs_control_data_create(const rrs_resource_e type,
+               rrs_control_data_h *data);
+
+
+/**
+ * @brief      Destroys the data handle.
+ * @details This function releases the data handle.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle to destroy
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_control_data_clone()
+ */
+int rrs_control_data_destroy(rrs_control_data_h data);
+
+
+/**
+ * @brief      Clones the data handle.
+ * @details This function clones the structured data handle @a origin.
+ * @since_tizen 3.0
+ *
+ * @remarks @a cloned must be released using rrs_control_data_destroy().
+ *
+ * @param[in]  origin          The original data handle
+ * @param[out] cloned          A cloned data handle
+ * @return     0 on success, otherwise a negative error data
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_control_data_destroy()
+ */
+int rrs_control_data_clone(const rrs_control_data_h origin,
+               rrs_control_data_h *cloned);
+
+
+/**
+ * @brief      Sets boolean field value.
+ * @details This function sets the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_send_control()
+ */
+int rrs_control_data_set_bool(rrs_control_data_h data,
+               const char *name,
+               const bool value);
+
+
+/**
+ * @brief      Sets integer field value.
+ * @details This function sets the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_send_control()
+ */
+int rrs_control_data_set_int(rrs_control_data_h data,
+               const char *name,
+               const int value);
+
+
+/**
+ * @brief      Sets floating point field value.
+ * @details This function sets the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_send_control()
+ */
+int rrs_control_data_set_double(rrs_control_data_h data,
+               const char *name,
+               const double value);
+
+
+/**
+ * @brief      Sets string field value.
+ * @details This function sets the string field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_send_control()
+ */
+int rrs_control_data_set_string(rrs_control_data_h data,
+               const char *name,
+               const char *value);
+
+
+/**
+ * @brief      Gets boolean field value.
+ * @details This function gets the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to bool in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_monitor_control()
+ */
+int rrs_control_data_get_bool(const rrs_control_data_h data,
+               const char *name,
+               bool *value);
+
+
+/**
+ * @brief      Gets integer field value.
+ * @details This function gets the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to int in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_monitor_control()
+ */
+int rrs_control_data_get_int(const rrs_control_data_h data,
+               const char *name,
+               int *value);
+
+
+/**
+ * @brief      Gets floating point field value.
+ * @details This function gets the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to double in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_monitor_control()
+ */
+int rrs_control_data_get_double(const rrs_control_data_h data,
+               const char *name,
+               double *value);
+
+
+/**
+ * @brief      Gets string field value.
+ * @details This function gets the sting field value.
+ * @since_tizen 3.0
+ *
+ * @remarks Release the value @a value using free().
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to char * in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_control_data_create() functions.
+ *
+ * @see rrs_control_data_create()
+ * @see rrs_resource_monitor_control()
+ */
+int rrs_control_data_get_string(const rrs_control_data_h data,
+               const char *name,
+               char **value);
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+#endif /* _RRS_CONTROL_DATA_H_ */
diff --git a/include/rrs_error.h b/include/rrs_error.h
new file mode 100644 (file)
index 0000000..cc3f9e7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_ERROR_H_
+#define _RRS_ERROR_H_
+
+#include <tizen_type.h>
+#include <tizen_error.h>
+
+/**
+ * @ingroup    CAPI_RRS_MODULE
+ * @defgroup   CAPI_RRS_ERROR_MODULE Errors
+ *
+ * @file rrs_error.h
+ * @brief This file contains the list of RRS errors
+ *
+ * @addtogroup CAPI_RRS_ERROR_MODULE
+ * @{
+ * @brief This provides a list of RRS API errors
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Base RRS error code (to be added to tizen header files)
+ * @since_tizen 3.0
+ */
+#define TIZEN_ERROR_RRS_SERVICE 1000
+
+/**
+ * @brief Enumerations of RRS error codes
+ * @since_tizen 3.0
+ */
+typedef enum {
+       RRS_ERROR_NONE = TIZEN_ERROR_NONE,      /**< Successful */
+       RRS_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER,    /**< Invalid Parameter */
+       RRS_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION,    /**< Invalid Operation */
+       RRS_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY,    /**< Out Of Memory */
+       RRS_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED,    /**< Permission Denied */
+       RRS_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED,    /**< Not Supported */
+       RRS_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA,        /**< No Data Error */
+       RRS_ERROR_UNKNOWN = TIZEN_ERROR_UNKNOWN,        /**< Unknown Error */
+       RRS_ERROR_KEY_NOT_AVAILABLE = TIZEN_ERROR_KEY_NOT_AVAILABLE,    /**< Key Not Available */
+       RRS_ERROR_SERVICE_NOT_AVAILABLE = TIZEN_ERROR_RRS_SERVICE | 0x01,       /**< Service Not Available */
+       RRS_ERROR_NOT_FOUND = TIZEN_ERROR_RRS_SERVICE | 0x02,   /**< Not Found Error */
+       RRS_ERROR_NETWORK_UNREACHABLE = TIZEN_ERROR_RRS_SERVICE | 0x03, /**< Network Unreachable */
+       RRS_ERROR_TIMEOUT = TIZEN_ERROR_RRS_SERVICE | 0x04,     /**< Timeout */
+       RRS_ERROR_INVALID_TYPE = TIZEN_ERROR_RRS_SERVICE | 0x05 /**< Invalid Type */
+} rrs_error_e;
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* _RRS_ERROR_H_ */
diff --git a/include/rrs_event_data.h b/include/rrs_event_data.h
new file mode 100644 (file)
index 0000000..c0c3fce
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_EVENT_DATA_H_
+#define _RRS_EVENT_DATA_H_
+
+#include "rrs_main.h"
+
+/**
+ * @ingroup    CAPI_RRS_CLIENT
+ * @defgroup   CAPI_RRS_EVENT_DATA_MODULE Event data
+ *
+ * @file rrs_event_data.h
+ * @brief This file contains the RRS Event Data API
+ * @addtogroup CAPI_RRS_EVENT_DATA_MODULE
+ * @{
+ * @brief This provides APIs related to event data handling
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief      Handle of event data.
+ * @details The handle to generate event data for sent events from remote resource.
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_event_data_destroy().
+ *
+ * @see rrs_event_data_destroy()
+ */
+typedef void * rrs_event_data_h;
+
+
+/**
+ * @brief      Creates an instance of structured event data.
+ * @details This function creates an instance of structured event data and issues a new handle for it.
+ * @since_tizen 3.0
+ *
+ * @remarks @a data handle must be released using rrs_event_data_destroy().
+ *
+ * @param[in]  type            Resource_type
+ * @param[out] data            The handle of newly created data instance
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_INVALID_TYPE Invalid type
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see rrs_event_data_destroy()
+ * @see rrs_event_data_clone()
+ * @see rrs_resource_e
+ */
+int rrs_event_data_create(const rrs_resource_e type,
+               rrs_event_data_h *data);
+
+
+/**
+ * @brief      Destroys the data handle.
+ * @details This function releases the data handle.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle to destroy
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_event_data_clone()
+ */
+int rrs_event_data_destroy(rrs_event_data_h data);
+
+
+/**
+ * @brief      Clones the data handle.
+ * @details This function clones the structured data handle @a origin.
+ * @since_tizen 3.0
+ *
+ * @remarks @a cloned must be released using rrs_event_data_destroy().
+ *
+ * @param[in]  origin          The original data handle
+ * @param[out] cloned          A cloned data handle
+ * @return     0 on success, otherwise a negative error data
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_event_data_destroy()
+ */
+int rrs_event_data_clone(const rrs_event_data_h origin,
+               rrs_event_data_h *cloned);
+
+
+/**
+ * @brief      Sets boolean field value.
+ * @details This function sets the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ */
+int rrs_event_data_set_bool(rrs_event_data_h data,
+               const char *name,
+               const bool value);
+
+
+/**
+ * @brief      Sets integer field value.
+ * @details This function sets the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ */
+int rrs_event_data_set_int(rrs_event_data_h data,
+               const char *name,
+               const int value);
+
+
+/**
+ * @brief      Sets floating point field value.
+ * @details This function sets the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ */
+int rrs_event_data_set_double(rrs_event_data_h data,
+               const char *name,
+               const double value);
+
+
+/**
+ * @brief      Sets string field value.
+ * @details This function sets the string field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  value           The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ */
+int rrs_event_data_set_string(rrs_event_data_h data,
+               const char *name,
+               const char *value);
+
+
+/**
+ * @brief      Gets boolean field value.
+ * @details This function gets the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to bool in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_resource_receive_event()
+ */
+int rrs_event_data_get_bool(const rrs_event_data_h data,
+               const char *name,
+               bool *value);
+
+
+/**
+ * @brief      Gets integer field value.
+ * @details This function gets the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to int in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_resource_receive_event()
+ */
+int rrs_event_data_get_int(const rrs_event_data_h data,
+               const char *name,
+               int *value);
+
+
+/**
+ * @brief      Gets floating point field value.
+ * @details This function gets the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to double in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_resource_receive_event()
+ */
+int rrs_event_data_get_double(const rrs_event_data_h data,
+               const char *name,
+               double *value);
+
+
+/**
+ * @brief      Gets string field value.
+ * @details This function gets the sting field value.
+ * @since_tizen 3.0
+ *
+ * @remarks Release the value @a value using free().
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[out] value           The pointer to char * in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre @a data handle is created with rrs_event_data_create() functions.
+ *
+ * @see rrs_event_data_create()
+ * @see rrs_resource_receive_event()
+ */
+int rrs_event_data_get_string(const rrs_event_data_h data,
+               const char *name,
+               char **value);
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+#endif /* _RRS_EVENT_DATA_H_ */
diff --git a/include/rrs_main.h b/include/rrs_main.h
new file mode 100644 (file)
index 0000000..de66132
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_MAIN_H_
+#define _RRS_MAIN_H_
+
+#include <tizen_type.h>
+#include <iotcon.h>
+#include <common.h>
+#include "rrs_error.h"
+
+/**
+ * @ingroup    CAPI_RRS_MODULE
+ * @defgroup   CAPI_RRS_MAIN_MODULE General
+ *
+ * @file rrs_main.h
+ * @brief This file contains functions related to RRS API.
+ * @addtogroup CAPI_RRS_MAIN_MODULE
+ * @{
+ * @brief This provides APIs related to RRS
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief      Handle of the RRS.
+ * @details The RRS handle can be obtained via call of rrs_create().
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_destroy().
+ *
+ * @par Example
+ * @code
+ * #include <rrs.h>
+ * // Usage of RRS in the app
+ * int main(void) {
+ *     // Creating RRS
+ *     rrs_h rrs = 0;
+ *     rrs_create(&rrs);
+ *
+ *     // Do something with RRS
+ *     // Destroy schema and data when no more needed
+ *     rrs_destroy(rrs);
+ *
+ *     return 0;
+ * }
+ * @endcode
+ *
+ * @see rrs_create()
+ * @see rrs_destroy()
+ */
+typedef int rrs_h;
+
+
+/**
+ * @brief      Enumerations of resources, supported by RRS
+ * @since_tizen 3.0
+ */
+typedef enum _rrs_resource_e {
+       RRS_RESOURCE_NONE = 0,                  /**< Invalid sensor */
+       RRS_RESOURCE_DISCOVERY = 1,             /**< Discovery resource */
+       RRS_RESOURCE_ACCELEROMETER,             /**< Accelerometer sensor */
+       RRS_RESOURCE_PROXIMITY,                 /**< Proximity sensor */
+       RRS_RESOURCE_AUTO_ROTATION,             /**< Auto rotation sensor */
+       RRS_RESOURCE_HRM,                               /**< Bio HRM sensor */
+       RRS_RESOURCE_HRM_LED_GREEN,             /**< Bio LED green sensor */
+       RRS_RESOURCE_HRM_LED_RED,               /**< Bio LED RED sensor */
+       RRS_RESOURCE_HRM_LED_IR,                /**< Bio LED IR sensor */
+       RRS_RESOURCE_GYROSCOPE,                 /**< Gyroscope sensor */
+       RRS_RESOURCE_MAGNETOMETER,              /**< Geomagnetic sensor */
+       RRS_RESOURCE_LIGHT,                             /**< Light sensor */
+       RRS_RESOURCE_PRESSURE,                  /**< Pressure sensor */
+       RRS_RESOURCE_TEMPERATURE,               /**< Temperature sensor */
+       RRS_RESOURCE_HUMIDITY,                  /**< Humidity sensor */
+       RRS_RESOURCE_UV,                                /**< Ultraviolet sensor */
+       RRS_RESOURCE_ORIENTATION,               /**< Orientation sensor */
+       RRS_RESOURCE_GRAVITY,                   /**< Gravity sensor */
+       RRS_RESOURCE_LINEAR_ACCELERATION,/**< Linear acceleration sensor */
+       RRS_RESOURCE_ROTATION_VECTOR,   /**< Rotation vector sensor */
+       RRS_RESOURCE_GYROSCOPE_ROTATION_VECTOR,         /**< Gyroscope Rotation Vector sensor */
+       RRS_RESOURCE_GEOMAGNETIC_ROTATION_VECTOR,       /**< Geomagnetic Rotation Vector sensor */
+       RRS_RESOURCE_UNCALIBRATED_GYROSCOPE,            /**< Uncalibrated gyroscope sensor */
+       RRS_RESOURCE_UNCALIBRATED_MAGNETOMETER,         /**< Uncalibrated geomagnetic sensor */
+       RRS_RESOURCE_ALL
+} rrs_resource_e;
+
+/**
+ * @brief      Creates an RRS and assigns it with a handle.
+ * @details This function creates an RRS and issues a new handle for it.
+ * \n The handle is used to discover resources.
+ * @since_tizen 3.0
+ *
+ * @remarks @a rrs handle must be released using rrs_destroy().
+ *
+ * @param[out] rrs             A handle of the newly created RRS
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_destroy()
+ */
+int rrs_create(rrs_h *rrs);
+
+
+/**
+ * @brief      Destroys the RRS handle.
+ * @details This function releases the RRS handle.
+ * @since_tizen 3.0
+ *
+ * @param[in]  rrs             The RRS handle to destroy
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre Call rrs_create() to create RRS and get its handle.
+ *
+ * @see rrs_create()
+ */
+int rrs_destroy(const rrs_h rrs);
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* _RRS_MAIN_H_ */
diff --git a/include/rrs_resource.h b/include/rrs_resource.h
new file mode 100644 (file)
index 0000000..8fe4543
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_RESOURCE_H_
+#define _RRS_RESOURCE_H_
+
+#include "rrs_main.h"
+#include "rrs_event_data.h"
+#include "rrs_control_data.h"
+
+/**
+ * @ingroup    CAPI_RRS_CLIENT
+ * @defgroup   CAPI_RRS_RESOURCE_MODULE Resource
+ *
+ * @file rrs_resource.h
+ * @brief This file contains the RRS Resource Client API
+ * @addtogroup CAPI_RRS_RESOURCE_MODULE
+ * @{
+ * @brief This provides APIs related to client-side usage of resource
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief      Handle of the virtual resource.
+ * @details The resource handle can be obtained via call of
+ * rrs_resource_find().
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_resource_destroy().
+ *
+ *
+ * @see rrs_create()
+ * @see rrs_destroy()
+ */
+typedef int rrs_resource_h;
+
+
+/**
+ * @brief Callback for each remote resource found.
+ * @details This callback is invoked when remote resources are found. The
+ * resource handle obtained is valid outside of this callback. The handle
+ * may be released with rrs_resource_destroy().
+ * @since_tizen 3.0
+ *
+ * @param[in]  result          The result of remote resource search
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  user_data       The user data passed from rrs_resource_find()
+ *
+ * @pre rrs_resource_find() will invoke this callback.
+ *
+ * @see rrs_resource_find()
+ * @see #rrs_resource_h
+ */
+typedef bool(*rrs_resource_found_cb) (rrs_error_e result,
+               rrs_resource_h resource,
+               void *user_data);
+
+
+/**
+ * @brief      Callback that iterates over list of found remote resources.
+ * @details This callback is invoked when remote found resources. The
+ * resource handle obtained is valid outside of this callback. The handle
+ * may be released with rrs_resource_destroy().
+ * @since_tizen 3.0
+ *
+ * @remarks @a resource must not be released by the user.
+ *
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  user_data       The user data passed from rrs_foreach_resource()
+ * @return     @c true to continue with the next iteration of the loop, \n @c
+ * false to break out of the loop
+ *
+ * @pre rrs_foreach_resource() will invoke this callback.
+ *
+ * @see rrs_foreach_resource()
+ * @see #rrs_resource_h
+ */
+typedef bool(*rrs_foreach_resource_cb) (rrs_resource_h resource,
+               void *user_data);
+
+
+/**
+ * @brief Callback triggered when client resource information is removed from server resource observers.
+ * @details This callback is triggered when server responds to removal of remote resource information.
+ * The resource handle obtained is not valid outside of this callback.
+ * @since_tizen 3.0
+ *
+ * @remarks @a resource must not be released by the user.
+ *
+ * @param[in]  result          The result of resource destroy request
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  user_data       The user data passed from rrs_resource_destroy()
+ *
+ * @pre rrs_resource_destroy() will invoke this callback.
+ *
+ * @see rrs_resource_destroy()
+ * @see #rrs_resource_h
+ */
+typedef void(*rrs_resource_destroy_cb) (rrs_error_e result,
+               rrs_resource_h resource,
+               void *user_data);
+
+
+/**
+ * @brief      Called to notify remote resource event data is received.
+ * @details This callback is invoked when remote resource event is received in the client.
+ * The event data handle obtained is not valid outside of this callback and can be cloned
+ * using rrs_event_data_clone().
+ * @since_tizen 3.0
+ *
+ * @param[in]  result          The result of request
+ * @param[in]  event           The handle of received resource event data
+ * @param[in]  user_data       The user data pointer passed in rrs_resource_subscribe_event()
+ *
+ * @pre RRS invokes this callback when remote resource is changed
+ * on the server.
+ *
+ * @see rrs_resource_subscribe_event()
+ * @see rrs_resource_unsubscribe_event()
+ */
+typedef void(*rrs_resource_observe_cb) (rrs_error_e result,
+               rrs_event_data_h event,
+               void *user_data);
+
+
+/**
+ * @brief      Called to notify response from remote resource for send control.
+ * @details This callback is invoked when remote resource responds to send control command.
+ * The resource handle obtained is valid outside of this callback. The handle may be
+ * released with rrs_resource_destroy().
+ * @since_tizen 3.0
+ *
+ * @param[in]  result          The result of request
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  user_data       The user data pointer passed in rrs_resource_send_control()
+ *
+ * @pre RRS invokes this callback when remote resource responds to send control.
+ *
+ * @see rrs_resource_send_control()
+ */
+typedef void(*rrs_resource_send_control_cb) (rrs_error_e result,
+               rrs_resource_h resource,
+               void *user_data);
+
+
+/**
+ * @brief      Called to notify control information received from remote resource.
+ * @details This callback is invoked when remote resource responds to monitor control command.
+ * The resource handle obtained is valid outside of this callback. The resource handle may be
+ * released with rrs_resource_destroy(). The control data handle obtained is not valid outside of
+ * this callback and can be cloned using rrs_control_data_clone(). The control data handle can be
+ * destroyed using rrs_control_data_destroy().
+ * @since_tizen 3.0
+ *
+ * @param[in]  result          The result of request
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  control         The handle of control information received
+ * @param[in]  user_data       The user data pointer passed in rrs_resource_send_control()
+ *
+ * @pre RRS invokes this callback when remote resource responds to rrs_resource_monitor_control().
+ *
+ * @see rrs_resource_monitor_control()
+ */
+typedef void(*rrs_resource_monitor_control_cb) (rrs_error_e result,
+               rrs_resource_h resource,
+               rrs_control_data_h control,
+               void *user_data);
+
+
+/**
+ * @brief      Called to notify event data information received from remote resource.
+ * @details This callback is invoked when remote resource resource responds to receive event command.
+ * The resource handle obtained is valid outside of this callback. The resource handle may be
+ * released with rrs_resource_destroy(). The event data handle obtained is not valid outside of
+ * this callback and can be cloned using rrs_event_data_clone(). The event data handle can be
+ * destroyed using rrs_event_data_destroy().
+ * @since_tizen 3.0
+ *
+ * @param[in]  result          The result of request
+ * @param[in]  resource        The handle of remote resource
+ * @param[in]  event           The handle of event data received
+ * @param[in]  user_data       The user data pointer passed in rrs_resource_receive_event()
+ *
+ * @pre RRS invokes this callback when remote resource responds to rrs_resource_receive_event().
+ *
+ * @see rrs_resource_receive_event()
+ */
+typedef void(*rrs_resource_receive_event_cb) (rrs_error_e result,
+               rrs_resource_h resource,
+               rrs_event_data_h event,
+               void *user_data);
+
+
+/**
+ * @brief      Find nearby resources by id.
+ * @details This function finds all nearby resources of a specified type.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  rrs             The RRS handle of the group
+ * @param[in]  type    The specified resource type
+ * @param[in]  callback        The callback which will retrieve the remote resource handles
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     RRS_ERROR_NONE on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_TYPE Invalid Type
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_NOT_FOUND Not Found
+ *
+ * @see rrs_resource_found_cb()
+ * @see rrs_resource_destroy()
+ * @see rrs_resoruce_e
+ */
+int rrs_resource_find(const rrs_h rrs,
+               const rrs_resource_e type,
+               rrs_resource_found_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Iterate over found resource handles.
+ * @details This function provides each found resource handle, through callback.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  type    The specified resource type
+ * @param[in]  callback        The callback which will retrieve the remote resource handles
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_TYPE Invalid Type
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see rrs_foreach_resource_cb()
+ * @see rrs_resource_destroy()
+ */
+int rrs_foreach_resource(const rrs_h rrs,
+               const rrs_resource_e type,
+               rrs_foreach_resource_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Destroys the resource client handle.
+ * @details This function releases the resource client handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle to destroy
+ * @param[in]  callback        The callback triggered once client information is removed in remote resource.
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_find()
+ * @see rrs_resource_destroy_cb()
+ */
+int rrs_resource_destroy(const rrs_resource_h resource,
+               rrs_resource_destroy_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Gets the count of found resource handles stored in client.
+ * @details This function provides the count of found remote resource handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  type    The specified resource type
+ * @param[out] count   The number of resources found
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_get_count()
+ */
+int rrs_resource_get_count(const rrs_h rrs,
+               const rrs_resource_e type,
+               int *count);
+
+
+/**
+ * @brief      Get resource type based on resource handle.
+ * @details This function gets the remote resource type based on remote resource handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[out] type            Resource type
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_find()
+ */
+int rrs_resource_get_type(const rrs_resource_h resource,
+               rrs_resource_e *type);
+
+
+/**
+ * @brief      Get device id of the resource based on resource handle.
+ * @details This function gets the remote device id based on remote resource handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[out] device_id   Device ID
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_find()
+ */
+int rrs_resource_get_device_id(const rrs_resource_h resource,
+               char **device_id);
+
+
+/**
+ * @brief      Get device name of the resource based on resource handle.
+ * @details This function gets the remote device name based on remote resource handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[out] device_name     Device Name
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_find()
+ */
+int rrs_resource_get_device_name(const rrs_resource_h resource,
+               char **device_name);
+
+
+/**
+ * @brief      Get uri path of the resource based on resource handle.
+ * @details This function gets the remote uri path of resource based on remote resource handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[out] uri_path        URI path of the resource
+ * @remark  Please free memory
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @pre Call rrs_resource_find() to find nearby remote resources.
+ *
+ * @see rrs_resource_find()
+ */
+int rrs_resource_get_uri_path(const rrs_resource_h resource,
+               char **uri_path);
+
+
+/**
+ * @brief      Send remote resource control data.
+ * @details This function sends the control data to remote resource.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[in]  control         The control data to send to the remote resource
+ * @param[in]  callback        The function triggered after remote resource responds to send control.
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see rrs_resource_monitor_control()
+ * @see rrs_resource_send_control_cb()
+ */
+int rrs_resource_send_control(const rrs_resource_h resource,
+               const rrs_control_data_h control,
+               rrs_resource_send_control_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Receive remote resource control data state.
+ * @details This function receives the control data from remote resource.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @param[in]  callback        The function triggered after remote resource responds with control data state.
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see rrs_resource_send_control()
+ * @see rrs_resource_monitor_control_cb()
+ */
+int rrs_resource_monitor_control(const rrs_resource_h resource,
+               rrs_resource_monitor_control_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Receive remote resource event data.
+ * @details This function receives the event data from remote resource.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource handle
+ * @param[in]  callback        The function is triggered after remote resource responds with event data.
+ * @param[in]  user_data       The user data pointer to be passed to callback functions
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @see rrs_resource_unsubscribe_event()
+ * @see rrs_resource_monitor_control_cb()
+ */
+int rrs_resource_receive_event(const rrs_resource_h resource,
+               rrs_resource_receive_event_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Subscribe for events from remote resource
+ * @details This function subscribes for remote resource events.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource handle
+ * @param[in]  callback        The callback which will be invoked when remote resource sends event data.
+ * @param[in]  user_data       The user data pointer to be passed to the callback function
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre call rrs_resource_find() to find remote resource handles.
+ *
+ * @see rrs_resource_unset_observe_cb()
+ * @see rrs_resource_observe_cb()
+ */
+int rrs_resource_subscribe_event(const rrs_resource_h resource,
+               rrs_resource_observe_cb callback,
+               void *user_data);
+
+
+/**
+ * @brief      Un-subscribe for events from remote resource
+ * @details This function un-subscribes for remote resource events.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  resource        The resource client handle
+ * @return     0 on success, otherwise a non-negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ * @retval     #RRS_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre call rrs_resource_find() to find remote resource handles.
+ *
+ * @see rrs_resource_subscribe_event()
+ */
+int rrs_resource_unsubscribe_event(const rrs_resource_h resource);
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+#endif /* _RRS_RESOURCE_H_ */
diff --git a/packaging/capi-rrs-client.manifest b/packaging/capi-rrs-client.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/packaging/remote-resource-service.service b/packaging/remote-resource-service.service
new file mode 100755 (executable)
index 0000000..83ad0fd
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=RRS service
+After=dlog-main.service dbus.service
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/rrs-server
+Restart=always
+
+[Install]
+WantedBy=default.target
diff --git a/packaging/remote-resource-service.spec b/packaging/remote-resource-service.spec
new file mode 100644 (file)
index 0000000..fc9b0d5
--- /dev/null
@@ -0,0 +1,201 @@
+Name:       rrs-serverd
+Summary:    Remote Resource Service
+Version:    0.0.1
+Release:    0
+Group:      Network & Connectivity/Service
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+Source1:    remote-resource-service.service
+Source2:       %{name}.manifest
+Source3:       capi-rrs-client.manifest
+
+BuildRequires:  cmake
+BuildRequires:  boost-devel
+BuildRequires:  pkgconfig(iotcon)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(json-glib-1.0)
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(cynara-creds-gdbus)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-session)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(capi-system-info)
+BuildRequires:  pkgconfig(libtzplatform-config)
+Requires(post):  /sbin/ldconfig
+Requires(postun):  /sbin/ldconfig
+
+%define build_test_suite ON
+
+%description
+remote resource service
+
+%package rrs-serverd
+Summary:    Remote Resource Service
+Group:      Network & Connectivity/Service
+Requires:   %{name} = %{version}-%{release}
+
+%description rrs-serverd
+remote resource service
+
+%package -n capi-rrs-client
+Summary:    Client library
+Group:      Network & Connectivity/Service
+Requires:   %{name} = %{version}-%{release}
+
+%description -n capi-rrs-client
+remote resource service client
+
+%package -n capi-rrs-client-devel
+Summary:    Client library devel
+Group:      Network & Connectivity/Service
+Requires:   %{name} = %{version}-%{release}
+
+%description -n capi-rrs-client-devel
+remote resource service client devel
+
+%if %{build_test_suite} == "ON"
+%package -n rrs-test
+Summary:    Test executable
+Group:      Network & Connectivity/Service
+Requires:   %{name} = %{version}-%{release}
+
+%description -n rrs-test
+Sensor functional testing
+
+%endif
+
+%prep
+%setup -q
+
+cp %{SOURCE2} ./
+cp %{SOURCE3} ./
+
+
+%build
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+
+export   CFLAGS+=" -Wextra -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wswitch-default"
+export CXXFLAGS+=" -Wextra -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wswitch-default -Wnon-virtual-dtor -Wno-c++0x-compat -std=c++0x"
+
+export   CFLAGS+=" -Wno-unused-parameter -Wno-empty-body"
+export CXXFLAGS+=" -Wno-unused-parameter -Wno-empty-body"
+
+export   CFLAGS+=" -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow -fno-common"
+export CXXFLAGS+=" -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow"
+
+export   CFLAGS+=" -DTIZEN_ENGINEER_MODE"
+export CXXFLAGS+=" -DTIZEN_ENGINEER_MODE"
+export   FFLAGS+=" -DTIZEN_ENGINEER_MODE"
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} -DLIBDIR=%{_libdir}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+mkdir -p %{buildroot}%{_libdir}/systemd/system
+mkdir -p %{buildroot}%{_libdir}/systemd/system/default.target.wants
+ln -sf remote-resource-service.service %{buildroot}%{_libdir}/systemd/system/default.target.wants/remote-resource-service.service
+mkdir -p %{buildroot}/usr/share/license
+#cp LICENSE %{buildroot}/usr/share/license/%{name}
+
+%post -n capi-rrs-client -p /sbin/ldconfig
+%post -n capi-rrs-client-devel -p /sbin/ldconfig
+
+%postun -n capi-rrs-client -p /sbin/ldconfig
+%postun -n capi-rrs-client-devel -p /sbin/ldconfig
+
+chown -R root:root %{buildroot}/root/share/rrs/*.dat
+chsmack -a '_' %{buildroot}/root/share/rrs/*.dat
+
+chown -R owner:users %{buildroot}/home/owner/share/rrs/*.dat
+chsmack -a 'User::App::Shared' %{buildroot}/home/owner/share/rrs/*.dat
+
+%files -n rrs-serverd
+%manifest packaging/rrs-serverd.manifest
+%defattr(-,root,root,-)
+%{_bindir}/rrs-server*
+%{_libdir}/rrs/libsensor-framework-broker.so*
+%{_includedir}/*
+%{_libdir}/systemd/system/remote-resource-service.service
+%{_libdir}/systemd/system/default.target.wants/remote-resource-service.service
+%license LICENSE.APLv2
+%attr(0644,root,root)/usr/share/rrs/*.dat
+/root/share/rrs/*.dat
+%attr(0644,root,root)/usr/lib/rrs/schemas/rrsdiscovery.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/sensorcontrol.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/accelerometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/proximity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/autorotation.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/geomagneticrotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gravity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gyroscope.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gyroscoperotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrm.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledgreen.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledir.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledred.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/humidity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/light.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/linearacceleration.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/magnetometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/orientation.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/pressure.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/rotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/temperature.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uncalibratedgyroscope.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uncalibratedmagnetometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uv.json
+
+%files -n capi-rrs-client
+%manifest packaging/capi-rrs-client.manifest
+%defattr(-,root,root,-)
+%{_libdir}/librrs-client.so*
+%{_libdir}/librrs-common.so*
+%license LICENSE.APLv2
+%attr(0644,root,root)/usr/share/rrs/*.dat
+%attr(0644,owner,users)/home/owner/share/rrs/*.dat
+%attr(0644,root,root)/usr/lib/rrs/schemas/rrsdiscovery.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/sensorcontrol.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/accelerometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/proximity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/autorotation.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/geomagneticrotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gravity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gyroscope.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/gyroscoperotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrm.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledgreen.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledir.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/hrmledred.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/humidity.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/light.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/linearacceleration.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/magnetometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/orientation.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/pressure.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/rotationvector.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/temperature.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uncalibratedgyroscope.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uncalibratedmagnetometer.json
+%attr(0644,root,root)/usr/lib/rrs/schemas/uv.json
+
+%files -n capi-rrs-client-devel
+%defattr(-,root,root,-)
+%{_includedir}/*.h
+%{_libdir}/librrs-client.so*
+%{_libdir}/librrs-common.so*
+%{_libdir}/pkgconfig/rrs-client.pc
+%license LICENSE.APLv2
+
+
+%if %{build_test_suite} == "ON"
+%files -n rrs-test
+%defattr(-,root,root,-)
+%{_bindir}/rrs-test
+%license LICENSE.APLv2
+%endif
diff --git a/packaging/rrs-serverd.manifest b/packaging/rrs-serverd.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c370631
--- /dev/null
@@ -0,0 +1,4 @@
+add_subdirectory(common)
+add_subdirectory(server)
+add_subdirectory(brokers)
+add_subdirectory(client)
\ No newline at end of file
diff --git a/src/brokers/CMakeLists.txt b/src/brokers/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b25348f
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(sensor_framework)
\ No newline at end of file
diff --git a/src/brokers/sensor_framework/CMakeLists.txt b/src/brokers/sensor_framework/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..7c05c29
--- /dev/null
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.6)
+project(sensor-framework-broker CXX)
+
+SET(SERVICE_NAME sensor-framework-broker)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(sf-broker-pkgs REQUIRED glib-2.0 gio-2.0 dlog sensor iotcon)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_SOURCE_DIR}/src/common)
+include_directories(${CMAKE_SOURCE_DIR}/src/server/daemon)
+
+FOREACH(flag ${sf-broker-pkgs_LDFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${sf-broker-pkgs_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+add_library(${SERVICE_NAME} SHARED
+               SensorFrameworkBroker.cpp
+               )
+
+target_link_libraries(${SERVICE_NAME} ${sf-broker-pkgs_LDFLAGS} "-lm")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"RRS-BROKER\"")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+
+install(TARGETS ${SERVICE_NAME} DESTINATION lib/rrs)
diff --git a/src/brokers/sensor_framework/SensorFrameworkBroker.cpp b/src/brokers/sensor_framework/SensorFrameworkBroker.cpp
new file mode 100755 (executable)
index 0000000..7ffc3fe
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "SensorFrameworkBroker.h"
+#include "common.h"
+#include "schema.h"
+
+using std::bind1st;
+using std::mem_fun;
+
+#define BROKER_NAME "SENSOR_FRAMEWORK_BROKER"
+
+#define ACCELEROMETER_RAW_DATA_EVENT           (ACCELEROMETER_SENSOR << 16) | 0x0001
+#define PROXIMITY_CHANGE_STATE_EVENT           (PROXIMITY_SENSOR << 16) | 0x0001
+
+SensorFrameworkBroker::SensorFrameworkBroker()
+{
+       __name = std::string(BROKER_NAME);
+       ServiceManager::setThread(SensorFrameworkBroker::working, this);
+}
+
+SensorFrameworkBroker::~SensorFrameworkBroker()
+{
+       INFO("SensorFrameworkBroker is destroyed!\n");
+}
+
+bool SensorFrameworkBroker::init()
+{
+       INFO("%s is created!\n", getName());
+       return true;
+}
+
+void SensorFrameworkBroker::getSensorInfo(const rrs_resource_e resource_type, sensor_type_t *sensor_type, unsigned int *event_type)
+{
+       switch(resource_type) {
+               case RRS_RESOURCE_ACCELEROMETER:
+                       *sensor_type = ACCELEROMETER_SENSOR;
+                       *event_type = ACCELEROMETER_RAW_DATA_EVENT;
+                       break;
+
+               case RRS_RESOURCE_PROXIMITY:
+                       *sensor_type = PROXIMITY_SENSOR;
+                       *event_type = PROXIMITY_CHANGE_STATE_EVENT;
+                       break;
+
+               default :
+                       break;
+       }
+}
+
+RrsService SensorFrameworkBroker::getType(void) {
+       return SENSOR_FRAMEWORK;
+}
+
+const char* SensorFrameworkBroker::getName(void)
+{
+       return __name.c_str();
+}
+
+bool SensorFrameworkBroker::working(void *inst)
+{
+       SensorFrameworkBroker *broker = (SensorFrameworkBroker *)inst;
+       return broker->processCommand();
+}
+
+bool SensorFrameworkBroker::onStart(void)
+{
+       INFO("Sensor Framework Broker Thread Started\n");
+       return startThread();
+}
+
+bool SensorFrameworkBroker::onStop(void)
+{
+       INFO("Sensor Framework Broker Thread Stopped\n");
+       return stopThread();
+}
+
+bool SensorFrameworkBroker::processEvent(const BrokerResource event_resource)
+{
+       ResourceQueue::__receive_event_instance().push(event_resource);
+       return true;
+}
+
+void SensorFrameworkBroker::__sensord_callback(const sensor_t sensor, const unsigned int event_type, sensor_data_t *data, void *user_data)
+{
+       SensorFrameworkBroker *broker_map_ptr = (SensorFrameworkBroker *) user_data;
+       BrokerResource event_resource;
+       BrokerResource *event_resource_ptr = NULL;
+
+       switch(event_type >> 16) {
+               case ACCELEROMETER_SENSOR:
+                       // fix resource index = 1 hardcoding in the future
+                       event_resource_ptr = broker_map_ptr->getEventResourceInfo(RRS_RESOURCE_ACCELEROMETER, 1);
+
+                       event_resource.service_type = event_resource_ptr->service_type;
+                       event_resource.resource_type = event_resource_ptr->resource_type;
+                       event_resource.resource_index = event_resource_ptr->resource_index;
+
+                       rrs_event_data_clone(event_resource_ptr->data, &(event_resource.data));
+
+                       rrs_event_data_set_double(event_resource.data, "x", data->values[0]);
+                       rrs_event_data_set_double(event_resource.data, "y", data->values[1]);
+                       rrs_event_data_set_double(event_resource.data, "z", data->values[2]);
+
+                       DBG("Sensor Type = %d, Event Type = %d, [%lld] [%6.6f] [%6.6f] [%6.6f]\n", sensor, event_type, data->timestamp, data->values[0], data->values[1], data->values[2]);
+                       break;
+
+               case PROXIMITY_SENSOR:
+                       // fix resource index = 1 hardcoding in the future
+                       event_resource_ptr = broker_map_ptr->getEventResourceInfo(RRS_RESOURCE_PROXIMITY, 1);
+
+                       event_resource.service_type = event_resource_ptr->service_type;
+                       event_resource.resource_type = event_resource_ptr->resource_type;
+                       event_resource.resource_index = event_resource_ptr->resource_index;
+
+                       rrs_event_data_clone(event_resource_ptr->data, &(event_resource.data));
+
+                       rrs_event_data_set_int(event_resource.data, "state", data->values[0]);
+
+                       DBG("Sensor Type = %d, Event Type = %d, [%lld] [%6.6f]\n", sensor, event_type, data->timestamp, data->values[0]);
+                       break;
+
+               default :
+                       break;
+       }
+
+       processEvent(event_resource);
+}
+
+bool SensorFrameworkBroker::conSensor(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr)
+{
+       rrs_data_h control_data = broker_command_ptr.data;
+       unsigned int event_type = 0;
+       sensor_type_t sensor_type = UNKNOWN_SENSOR;
+
+       getSensorInfo(broker_command_ptr.resource_type, &sensor_type, &event_type);
+       sensor_t sensor = sensord_get_sensor(sensor_type);
+
+       if (!control_data) {
+               ERR("No Resource delivered in the command!!!");
+       }
+
+       if (!addClient(broker_command_ptr.resource_type)) {
+               ERR("Error adding client information for resource - %d", broker_command_ptr.resource_type);
+               return false;
+       }
+
+       if (getClientCnt(broker_command_ptr.resource_type) == 1) {
+               command_resource_ptr = getControlResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+               if (command_resource_ptr == NULL) {
+                       command_resource_ptr = new BrokerResource;
+                       command_resource_ptr->service_type = broker_command_ptr.service_type;
+                       command_resource_ptr->resource_type = broker_command_ptr.resource_type;
+                       command_resource_ptr->resource_index = broker_command_ptr.resource_index;
+                       rrs_data_clone(control_data, &(command_resource_ptr->data));
+                       addControlResource(command_resource_ptr->resource_type, command_resource_ptr);
+               }
+
+               event_resource_ptr = getEventResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+               if (event_resource_ptr == NULL) {
+                       event_resource_ptr = new BrokerResource;
+                       event_resource_ptr->service_type = broker_command_ptr.service_type;
+                       event_resource_ptr->resource_type = broker_command_ptr.resource_type;
+                       event_resource_ptr->resource_index = broker_command_ptr.resource_index;
+                       addEventResource(event_resource_ptr->resource_type, event_resource_ptr);
+
+                       if (rrs_event_data_create(event_resource_ptr->resource_type, &(event_resource_ptr->data))) {
+                               ERR("rrs_event_data_create() failed");
+                               return false;
+                       }
+               }
+
+               command_resource_ptr->handle = sensord_connect(sensor);
+
+               INFO("Connected handle - %d, sensor event - %d\n", command_resource_ptr->handle, event_type);
+
+               rrs_data_set_bool(command_resource_ptr->data, "connect_sensor", true);
+               rrs_data_set_bool(command_resource_ptr->data, "disconnect_sensor", false);
+       }
+
+       return true;
+}
+
+bool SensorFrameworkBroker::disconSensor(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr)
+{
+       if (!deleteClient(broker_command_ptr.resource_type)) {
+               ERR("Error deleting client information for resource - %d", broker_command_ptr.resource_type);
+               return false;
+       }
+
+       if (getClientCnt(broker_command_ptr.resource_type) == 0) {
+               command_resource_ptr = getControlResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+               if (command_resource_ptr != NULL) {
+                       sensord_stop(command_resource_ptr->handle);
+                       sensord_disconnect(command_resource_ptr->handle);
+
+                       INFO("Disconnected handle - %d\n", command_resource_ptr->handle);
+
+                       rrs_control_data_destroy(command_resource_ptr->data);
+                       deleteControlResource(command_resource_ptr->resource_type, command_resource_ptr->resource_index);
+                       delete command_resource_ptr;
+               } else {
+                       ERR("Information for Resource Type - %d, Resource Index - %d, is missing in broker", broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+                       return false;
+               }
+
+               event_resource_ptr = getEventResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+               if (event_resource_ptr != NULL) {
+                       rrs_event_data_destroy(event_resource_ptr->data);
+                       deleteEventResource(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+                       delete event_resource_ptr;
+               } else {
+                       ERR("Information for Resource Type - %d, Resource Index - %d, is missing in broker", broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+bool SensorFrameworkBroker::regEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, int interval, int max_batch_latency)
+{
+       unsigned int event_type = 0;
+       sensor_type_t sensor_type = UNKNOWN_SENSOR;
+
+       getSensorInfo(broker_command_ptr.resource_type, &sensor_type, &event_type);
+
+       command_resource_ptr = getControlResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+       if (command_resource_ptr == NULL) {
+               ERR("Broker not connected to resource\n");
+               return false;
+       }
+
+       if (!sensord_register_event(command_resource_ptr->handle, event_type, interval, max_batch_latency, __sensord_callback, (void *) this)) {
+               ERR("Error registering handle - %d, sensor event - %d, interval - %d\n", command_resource_ptr->handle, event_type, interval);
+               return false;
+       }
+
+       if (getClientCnt(broker_command_ptr.resource_type) == 1) {
+               sensord_start(command_resource_ptr->handle, 0);
+       }
+
+       rrs_data_set_bool(command_resource_ptr->data, "register_event", true);
+       rrs_data_set_int(command_resource_ptr->data, "interval", interval);
+       rrs_data_set_int(command_resource_ptr->data, "max_batch_latency", max_batch_latency);
+
+       return true;
+}
+
+bool SensorFrameworkBroker::unregEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr)
+{
+       unsigned int event_type = 0;
+       sensor_type_t sensor_type = UNKNOWN_SENSOR;
+
+       getSensorInfo(broker_command_ptr.resource_type, &sensor_type, &event_type);
+
+       command_resource_ptr = getControlResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+       if (command_resource_ptr == NULL) {
+               ERR("Broker not connected to resource\n");
+               return false;
+       }
+
+       if (!sensord_unregister_event(command_resource_ptr->handle, event_type)) {
+               ERR("Error unregistering sensor event - %d\n\n", event_type);
+               return false;
+       }
+
+       rrs_data_set_bool(command_resource_ptr->data, "unregister_event", true);
+
+       return true;
+}
+
+bool SensorFrameworkBroker::pollEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr)
+{
+       sensor_data_t data;
+       BrokerResource event_resource;
+       unsigned int event_type = 0;
+       sensor_type_t sensor_type = UNKNOWN_SENSOR;
+
+       getSensorInfo(broker_command_ptr.resource_type, &sensor_type, &event_type);
+
+       command_resource_ptr = getControlResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+       if (command_resource_ptr == NULL) {
+               ERR("Broker not connected to resource\n");
+               return false;
+       }
+
+       if (getClientCnt(broker_command_ptr.resource_type) == 1) {
+               sensord_start(command_resource_ptr->handle, 0);
+       }
+
+       event_resource_ptr = getEventResourceInfo(broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+       if (event_resource_ptr == NULL) {
+               ERR("Information for Resource Type - %d, Resource Index - %d, is missing in broker", broker_command_ptr.resource_type, broker_command_ptr.resource_index);
+               return false;
+       }
+
+       rrs_data_set_bool(command_resource_ptr->data, "get_data", true);
+
+       if (!sensord_get_data(command_resource_ptr->handle, event_type, &data)) {
+               ERR("Error getting data from sensord");
+               return false;
+       }
+
+       switch(event_type >> 16) {
+               case ACCELEROMETER_SENSOR:
+                       rrs_data_set_double(event_resource_ptr->data, "x", data.values[0]);
+                       rrs_data_set_double(event_resource_ptr->data, "y", data.values[1]);
+                       rrs_data_set_double(event_resource_ptr->data, "z", data.values[2]);
+                       break;
+               case PROXIMITY_SENSOR:
+                       rrs_data_set_int(event_resource_ptr->data, "state", data.values[0]);
+                       break;
+               default :
+                       break;
+       }
+
+       if (getClientCnt(broker_command_ptr.resource_type) == 0) {
+               sensord_stop(command_resource_ptr->handle);
+       }
+
+       event_resource.service_type = event_resource_ptr->service_type;
+       event_resource.resource_type = event_resource_ptr->resource_type;
+       event_resource.resource_index = event_resource_ptr->resource_index;
+       rrs_data_clone(event_resource_ptr->data, &(event_resource.data));
+
+       ResourceQueue::__receive_event_instance().push(event_resource);
+
+       return true;
+}
+
+bool SensorFrameworkBroker::processCommand()
+{
+       int interval = 0;
+       int max_batch_latency = 0;
+       bool connect_sensor = false;
+       bool disconnect_sensor = false;
+       bool register_event = false;
+       bool unregister_event = false;
+       bool get_data = false;
+
+       rrs_data_h control_data = NULL;
+       BrokerResource *broker_command_ptr = NULL;
+       BrokerResource *command_resource_ptr = NULL, *event_resource_ptr = NULL;
+
+       broker_command_ptr = (BrokerResource *) ResourceQueue::__transmit_control_instance().pop();
+
+       if (broker_command_ptr->service_type != SENSOR_FRAMEWORK)
+               return true;
+
+       control_data = broker_command_ptr->data;
+       if (!control_data) {
+               ERR("No Resource delivered in the command!!!");
+       }
+
+       if (broker_command_ptr->service_type == SENSOR_FRAMEWORK) {
+               rrs_data_get_bool(control_data, "connect_sensor", &connect_sensor);
+               rrs_data_get_bool(control_data, "disconnect_sensor", &disconnect_sensor);
+               rrs_data_get_int(control_data, "interval", &interval);
+               rrs_data_get_int(control_data, "max_batch_latency", &max_batch_latency);
+               rrs_data_get_bool(control_data, "register_event", &register_event);
+               rrs_data_get_bool(control_data, "unregister_event", &unregister_event);
+               rrs_data_get_bool(control_data, "get_data", &get_data);
+
+               INFO("\tconnect_sensor: %d, disconnect_sensor: %d, interval: %d, max batch lat: %d, reg event: %d, unreg event: %d, get data %d",
+                    connect_sensor, disconnect_sensor, interval, max_batch_latency, register_event, unregister_event, get_data);
+
+               if (connect_sensor) {
+                       if (!conSensor(*broker_command_ptr, command_resource_ptr, event_resource_ptr)) {
+                               ERR("Error connecting to resource - %d", broker_command_ptr->resource_type);
+                               return false;
+                       }
+
+                       INFO("SensorFrameworkBroker: Connected Sensor!\n");
+
+                       rrs_data_set_bool(control_data, "connect_sensor", false);
+               }
+               if (register_event) {
+                       if (!regEvent(*broker_command_ptr, command_resource_ptr, interval, max_batch_latency)) {
+                               ERR("Error registering for resource event - %d", broker_command_ptr->resource_type);
+                               return false;
+                       }
+
+                       rrs_data_set_bool(control_data, "register_event", false);
+
+                       INFO("SensorFrameworkBroker: Registered for Sensor Data Event!\n");
+               }
+               if (unregister_event) {
+                       if (!unregEvent(*broker_command_ptr, command_resource_ptr)) {
+                               ERR("Error unregistering resource event - %d", broker_command_ptr->resource_type);
+                               return false;
+                       }
+
+                       rrs_data_set_bool(control_data, "unregister_event", false);
+
+                       INFO("SensorFrameworkBroker: Unregistered for Sensor Data Event!\n");
+               }
+               if (get_data) {
+                       if (!pollEvent(*broker_command_ptr, command_resource_ptr, event_resource_ptr)) {
+                               ERR("Error polling data from resource - %d", broker_command_ptr->resource_type);
+                               return false;
+                       }
+
+                       rrs_data_set_bool(control_data, "get_data", false);
+
+                       INFO("SensorFrameworkBroker: Polling for Sensor Data completed!\n");
+               }
+               if (disconnect_sensor) {
+                       if (!disconSensor(*broker_command_ptr, command_resource_ptr, event_resource_ptr)) {
+                               ERR("Error disconnecting from resource - %d", broker_command_ptr->resource_type);
+                               return false;
+                       }
+
+                       rrs_data_set_bool(control_data, "disconnect_sensor", false);
+
+                       INFO("SensorFrameworkBroker: Disconnected Sensor!\n");
+               }
+       }
+
+       rrs_data_destroy(control_data);
+
+       return true;
+}
+
+extern "C" IotTizenModule* create(void)
+{
+       SensorFrameworkBroker *broker = NULL;
+
+       try {
+               broker = new(std::nothrow) SensorFrameworkBroker;
+       } catch (int err) {
+               ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
+               return NULL;
+       }
+
+       IotTizenModule *broker_module = new(std::nothrow) IotTizenModule;
+       RETVM_IF(!broker_module || !broker, NULL, "Failed to allocate memory");
+
+       broker_module->modules.push_back(broker);
+
+       return broker_module;
+}
diff --git a/src/brokers/sensor_framework/SensorFrameworkBroker.h b/src/brokers/sensor_framework/SensorFrameworkBroker.h
new file mode 100755 (executable)
index 0000000..9daf29f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SENSOR_FRAMEWORK_BROKER_H_
+#define _SENSOR_FRAMEWORK_BROKER_H_
+
+#include <sensor_internal.h>
+#include <sensor_common.h>
+#include "ServiceManager.h"
+#include "PluginLoader.h"
+#include "rrs.h"
+
+class SensorFrameworkBroker : public ServiceManager {
+public:
+       SensorFrameworkBroker();
+       virtual ~SensorFrameworkBroker();
+
+       bool init();
+       RrsService getType(void);
+       const char* getName(void);
+       static bool working(void *inst);
+       static bool processEvent(const BrokerResource broker_resource);
+       bool processCommand(void);
+
+       static void __sensord_callback(const sensor_t sensor, const unsigned int event_type, sensor_data_t *data, void *user_data);
+
+private:
+       bool onStart(void);
+       bool onStop(void);
+       void getSensorInfo(const rrs_resource_e resource_type, sensor_type_t *sensor_type, unsigned int *event_type);
+       bool conSensor(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr);
+       bool disconSensor(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr);
+       bool regEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, int interval, int max_batch_latency);
+       bool unregEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr);
+       bool pollEvent(const BrokerResource broker_command_ptr, BrokerResource *command_resource_ptr, BrokerResource *event_resource_ptr);
+
+       std::string __name;
+};
+
+#endif
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
new file mode 100644 (file)
index 0000000..98aecee
--- /dev/null
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 2.6)
+project(rrs-client CXX)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(rrs-client-pkgs REQUIRED dlog glib-2.0 iotcon)
+
+INCLUDE_DIRECTORIES(include)
+FILE(GLOB rrs-client-srcs *.c *.cpp)
+
+FOREACH(flag ${rrs-client-pkgs_LDFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${rrs-client-pkgs_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_SOURCE_DIR}/include)
+include_directories(${CMAKE_SOURCE_DIR}/src/common)
+
+add_library(${PROJECT_NAME} SHARED ${rrs-client-srcs} )
+
+target_link_libraries(${PROJECT_NAME} ${rrs-client-pkgs_LDFLAGS} "rrs-common" "-lrt -ldl -pthread")
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY)
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"RRS-CLIENT\"")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+
+install(TARGETS ${PROJECT_NAME} DESTINATION lib)
+INSTALL(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
+
diff --git a/src/client/ClientManager.cpp b/src/client/ClientManager.cpp
new file mode 100644 (file)
index 0000000..f82cbee
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "ClientManager.h"
+#include <stdlib.h>
+#include <glib.h>
+#include <string>
+#include "common.h"
+
+ClientManager::ClientManager()
+{
+}
+
+ClientManager::~ClientManager()
+{
+}
+
+void ClientManager::addResource(const rrs_resource_e res, ResourceClient *info)
+{
+       client_map::iterator it;
+
+       it = __clientInfo.insert(std::make_pair(res, info));
+}
+
+bool ClientManager::deleteResource(const iotcon_remote_resource_h resource)
+{
+       client_map::iterator it;
+
+       for (it = __clientInfo.begin(); it != __clientInfo.end(); ++it) {
+               if (((*it).second)->__remoteResource == resource) {
+                       __clientInfo.erase(it);
+               }
+       }
+
+       return true;
+}
+
+rrs_resource_h ClientManager::createHandle(ResourceClient *resource)
+{
+       int handle = 1;
+
+       AUTOLOCK(__handleLock);
+
+       while (__handleInfo.count(handle) > 0)
+               handle++;
+
+       if (handle == MAX_CLIENT_HANDLE) {
+               ERR("Max Handles reached");
+               return ERROR_HANDLE;
+       }
+
+       __handleInfo.insert(std::pair<int,ResourceClient *> (handle, resource));
+
+       return handle;
+}
+
+bool ClientManager::deleteHandle(const rrs_resource_h handle)
+{
+       AUTOLOCK(__handleLock);
+
+       auto it_handle = __handleInfo.find(handle);
+
+       if (it_handle == __handleInfo.end()) {
+               ERR("Handle[%d] is not found", handle);
+               return false;
+       }
+
+       __handleInfo.erase(it_handle);
+       return true;
+}
+
+int ClientManager::getHandle(ResourceClient *resource)
+{
+       handle_map::iterator it;
+
+       for (it = __handleInfo.begin(); it != __handleInfo.end(); ++it) {
+               if (it->second == resource) {
+                       return (it->first);
+               }
+       }
+
+       INFO("Handle not found for resource with address - %p", resource);
+
+       return ERROR_HANDLE;
+}
+
+bool ClientManager::getResourceFromHandle(const rrs_resource_h handle, ResourceClient **resource)
+{
+       auto it_handle = __handleInfo.find(handle);
+
+       if (it_handle == __handleInfo.end()) {
+               ERR("Handle[%d] is not found", handle);
+               return false;
+       }
+
+       *resource = it_handle->second;
+       return true;
+}
+
+ResourceClient *ClientManager::getResourceInfo(const iotcon_remote_resource_h resource)
+{
+       client_map::iterator it;
+
+       for (it = __clientInfo.begin(); it != __clientInfo.end(); ++it) {
+               if ((it->second)->__remoteResource == resource) {
+                       return (it->second);
+               }
+       }
+
+       return NULL;
+}
+
+bool ClientManager::iterateForEachResource(const rrs_resource_e type, foreach_resource_cb callback, void *user_data)
+{
+       handle_map::iterator it;
+
+       for (it = __handleInfo.begin(); it != __handleInfo.end(); ++it) {
+               if ((it->second)->__resourceType == type) {
+                       if (callback(it->first, user_data) == false)
+                               return false;
+               }
+       }
+
+       return true;
+}
+
+int ClientManager::getCount(const rrs_resource_e type)
+{
+       client_map::iterator it;
+       int count = 0;
+
+       for (it = __clientInfo.begin(); it != __clientInfo.end(); ++it) {
+               if ((it->second)->__resourceType == type) {
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+ClientManager& ClientManager::__get_instance()
+{
+       static ClientManager inst;
+       return inst;
+}
diff --git a/src/client/ClientManager.h b/src/client/ClientManager.h
new file mode 100644 (file)
index 0000000..f629d87
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _CLIENT_MANAGER_H_
+#define _CLIENT_MANAGER_H_
+
+#include <stdint.h>
+#include <map>
+#include <unordered_map>
+#include "rrs.h"
+#include "schema.h"
+#include "services_common.h"
+#include "ResourceClient.h"
+#include "Mutex.h"
+
+#define MAX_CLIENT_HANDLE 10000
+#define ERROR_HANDLE -1
+
+typedef bool(*foreach_resource_cb) (rrs_resource_h resource, void *user_data);
+
+class ClientManager {
+public:
+       typedef std::multimap<rrs_resource_e, ResourceClient *> client_map;
+       typedef std::unordered_map<rrs_resource_h, ResourceClient *> handle_map;
+
+       static ClientManager& __get_instance();
+       rrs_resource_h createHandle(ResourceClient *resource);
+       bool deleteHandle(const rrs_resource_h handle);
+       int getHandle(ResourceClient *resource);
+       bool getResourceFromHandle(const rrs_resource_h handle, ResourceClient **resource);
+       void addResource(const rrs_resource_e res, ResourceClient *info);
+       bool deleteResource(const iotcon_remote_resource_h resource);
+       ResourceClient *getResourceInfo(const iotcon_remote_resource_h resource);
+       bool iterateForEachResource(const rrs_resource_e type, foreach_resource_cb callback, void *user_data);
+       int getCount(const rrs_resource_e type);
+
+       client_map __clientInfo;
+       handle_map __handleInfo;
+       Mutex __handleLock;
+private:
+       ClientManager();
+       virtual ~ClientManager();
+};
+
+#endif /* _CLIENT_MANAGER_H_ */
diff --git a/src/client/FindResourceInfo.cpp b/src/client/FindResourceInfo.cpp
new file mode 100644 (file)
index 0000000..9792561
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 "FindResourceInfo.h"
+
+FindResourceInfo::FindResourceInfo()
+: __foundcb(NULL)
+, __foundData(NULL)
+, __rrs(0)
+, __resourceType(RRS_RESOURCE_NONE)
+{
+}
+
+FindResourceInfo::~FindResourceInfo()
+{
+}
+
diff --git a/src/client/FindResourceInfo.h b/src/client/FindResourceInfo.h
new file mode 100644 (file)
index 0000000..f621326
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _FIND_RESOURCE_INFO_H_
+#define _FIND_RESOURCE_INFO_H_
+
+#include "rrs.h"
+
+class FindResourceInfo {
+public:
+       FindResourceInfo();
+       virtual ~FindResourceInfo();
+
+       rrs_resource_found_cb __foundcb;
+       void *__foundData;
+       rrs_h __rrs;
+       rrs_resource_e __resourceType;
+};
+
+#endif /* _FIND_RESOURCE_INFO_H_ */
diff --git a/src/client/ResourceClient.cpp b/src/client/ResourceClient.cpp
new file mode 100644 (file)
index 0000000..cc486e0
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd 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 "ResourceClient.h"
+#include <stdlib.h>
+#include <glib.h>
+#include <string>
+#include <tizen_type.h>
+#include <new>
+#include "common.h"
+#include "IotconToRrs.h"
+#include "ClientManager.h"
+#include "RrsManager.h"
+
+ResourceClient::ResourceClient()
+: __foundcb(NULL)
+, __foundDiscoverycb(NULL)
+, __observecb(NULL)
+, __sendControlcb(NULL)
+, __monitorControlcb(NULL)
+, __receiveEventcb(NULL)
+, __destroycb(NULL)
+, __remoteResource(NULL)
+, __interfaces(NULL)
+, __connectivityType(IOTCON_CONNECTIVITY_ALL)
+, __eventRepr(NULL)
+, __foundData(NULL)
+, __foundDiscoveryData(NULL)
+, __observeData(NULL)
+, __sendControlData(NULL)
+, __monitorControlData(NULL)
+, __receiveEventData(NULL)
+, __destroyData(NULL)
+, __rrs(0)
+, __resourceType(RRS_RESOURCE_NONE)
+, __controlSchema(NULL)
+, __eventSchema(NULL)
+, __controlData(NULL)
+, __eventData(NULL)
+, __observeEnabled(false)
+, __type(NULL)
+, __hostAddress(NULL)
+{
+}
+
+ResourceClient::~ResourceClient()
+{
+       if (__controlData)
+               rrs_data_destroy(__controlData);
+       __controlData = NULL;
+
+       if (__eventData)
+               rrs_data_destroy(__eventData);
+       __eventData = NULL;
+
+       if (__controlSchema)
+               rrs_schema_destroy(__controlSchema);
+       __controlSchema = NULL;
+
+       if (__eventSchema)
+               rrs_schema_destroy(__eventSchema);
+       __eventSchema = NULL;
+}
+
+void ResourceClient::__on_observe(iotcon_remote_resource_h resource, iotcon_error_e err, int sequence_number, iotcon_response_h response, void *user_data)
+{
+       ResourceClient *client = (ResourceClient *) user_data;
+
+       if (sequence_number > 0) {
+               client->onResponseGetEvent(response);
+               client->__observecb(RRS_ERROR_NONE, client->__eventData, client->__observeData);
+       }
+}
+
+void ResourceClient::__on_response(iotcon_remote_resource_h resource, iotcon_error_e err, iotcon_request_type_e request_type, iotcon_response_h response, void *user_data)
+{
+       INFO("request(%d) was successful", request_type);
+
+       ResourceClient *inst = (ResourceClient *)user_data;
+
+       switch (request_type) {
+       case IOTCON_REQUEST_GET:
+               inst->onResponseGetControl(response);
+               break;
+       case IOTCON_REQUEST_PUT:
+               inst->onResponsePut(response);
+               break;
+       case IOTCON_REQUEST_DELETE:
+               inst->onResponseDelete(response);
+               break;
+       default:
+               ERR("Invalid request type (%d)", request_type);
+               return;
+       }
+}
+
+bool ResourceClient::__found_discovery_resource(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+       ResourceClient *client = NULL;
+       FindResourceInfo *info = NULL;
+
+       if (resource == NULL || user_data == NULL)
+               return false;
+
+       INFO("===== discovery resource found =====");
+
+       client = new (std::nothrow) ResourceClient;
+       if (client == NULL) {
+               ERR("Error allocating memory for remote discovery resource handle!");
+               return false;
+       }
+
+       info = (FindResourceInfo *) user_data;
+
+       client->__rrs = info->__rrs;
+       client->__resourceType = info->__resourceType;
+       client->__foundDiscoverycb = info->__foundcb;
+       client->__foundDiscoveryData = info->__foundData;
+
+       ret = iotcon_remote_resource_get_host_address(resource, &client->__hostAddress);
+       if (ret != IOTCON_ERROR_NONE) {
+               delete client;
+               ERR("iotcon_remote_resource_get_host_address() Fail(%d)", ret);
+               return false;
+       }
+
+       DBG("[%s] resource host : %s", client->__uriPath, client->__hostAddress);
+
+       ret = iotcon_remote_resource_get_connectivity_type(resource, &client->__connectivityType);
+       if (ret != IOTCON_ERROR_NONE) {
+               delete client;
+               ERR("iotcon_remote_resource_get_connectivity_type() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_remote_resource_get_interfaces(resource, &client->__interfaces);
+       if (ret != IOTCON_ERROR_NONE) {
+               delete client;
+               ERR("iotcon_remote_resource_get_interfaces() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = rrs_discovery_schema_load(client->__resourceType, &client->__controlSchema);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_discovery_schema_load() Fail(%d)", ret);
+               delete client;
+               return false;
+       }
+
+       ret = rrs_schema_create_data(client->__controlSchema, &client->__controlData);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() Fail(%d)", ret);
+               rrs_schema_destroy(client->__controlSchema);
+               delete client;
+               return false;
+       }
+
+       ret = iotcon_remote_resource_clone(resource, &client->__remoteResource);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_clone() Fail(%d)", ret);
+               rrs_data_destroy(client->__controlData);
+               rrs_schema_destroy(client->__controlSchema);
+               delete client;
+               return false;
+       }
+
+       ClientManager::__get_instance().addResource(client->__resourceType, client);
+
+       handle = ClientManager::__get_instance().createHandle(client);
+       if (handle == ERROR_HANDLE) {
+               ERR("Error creating new client handle!");
+               delete client;
+               return false;
+       }
+
+       if (client->__foundDiscoverycb != NULL)
+               client->__foundDiscoverycb(RRS_ERROR_NONE, handle, client->__foundDiscoveryData);
+
+       return true;
+}
+
+bool ResourceClient::__found_resource(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+       ResourceClient *client = NULL;
+       FindResourceInfo *info = NULL;
+       char *hostAddress = NULL;
+
+       if (resource == NULL || user_data == NULL)
+               return false;
+
+       INFO("===== resource found =====");
+
+       client = new (std::nothrow) ResourceClient;
+       if (client == NULL) {
+               ERR("Error allocating memory for remote resource handle!");
+               return false;
+       }
+
+       info = (FindResourceInfo *) user_data;
+
+       client->__rrs = info->__rrs;
+       client->__resourceType = info->__resourceType;
+       client->__foundcb = info->__foundcb;
+       client->__foundData = info->__foundData;
+
+       ret = iotcon_remote_resource_get_host_address(resource, &hostAddress);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_get_host_address() Fail(%d)", ret);
+               delete client;
+               return false;
+       }
+       DBG("[%s] resource host : %s", client->__uriPath, hostAddress);
+       client->__hostAddress = strdup(hostAddress);
+
+       ret = iotcon_remote_resource_get_connectivity_type(resource, &client->__connectivityType);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_get_connectivity_type() Fail(%d)", ret);
+               delete client;
+               return false;
+       }
+
+       ret = iotcon_remote_resource_get_interfaces(resource, &client->__interfaces);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_get_interfaces() Fail(%d)", ret);
+               delete client;
+               return false;
+       }
+
+       ret = rrs_schema_load(client->__resourceType, &client->__controlSchema, &client->__eventSchema);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_schema_load() Fail(%d)", ret);
+               delete client;
+               return false;
+       }
+
+       ret = rrs_schema_create_data(client->__controlSchema, &client->__controlData);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() Fail(%d)", ret);
+               rrs_schema_destroy(client->__controlSchema);
+               rrs_schema_destroy(client->__eventSchema);
+               delete client;
+               return false;
+       }
+
+       ret = rrs_schema_create_data(client->__eventSchema, &client->__eventData);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() Fail(%d)", ret);
+               rrs_data_destroy(client->__controlData);
+               rrs_schema_destroy(client->__controlSchema);
+               rrs_schema_destroy(client->__eventSchema);
+               delete client;
+               return false;
+       }
+
+       ret = iotcon_remote_resource_clone(resource, &client->__remoteResource);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_clone() Fail(%d)", ret);
+               rrs_data_destroy(client->__controlData);
+               rrs_data_destroy(client->__eventData);
+               rrs_schema_destroy(client->__controlSchema);
+               rrs_schema_destroy(client->__eventSchema);
+               delete client;
+               return false;
+       }
+
+       ClientManager::__get_instance().addResource(client->__resourceType, client);
+
+       handle = ClientManager::__get_instance().createHandle(client);
+       if (handle == ERROR_HANDLE) {
+               ERR("Error creating new client handle!");
+               delete client;
+               return false;
+       }
+
+       if (client->__foundcb != NULL)
+               client->__foundcb(RRS_ERROR_NONE, handle, client->__foundData);
+
+       return true;
+}
+
+bool ResourceClient::setControlRepresentation(iotcon_representation_h *repr)
+{
+       int ret = IOTCON_ERROR_NONE;
+       iotcon_attributes_h state = NULL;
+
+       ret = iotcon_attributes_create(&state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_attributes_create() Fail(%d)", ret);
+               return false;
+       }
+
+       IotconToRrs converter(__controlData, __controlSchema, state);
+       converter.setToIotcon();
+
+       ret = iotcon_representation_set_attributes(*repr, state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_set_attributes() Fail(%d)", ret);
+               iotcon_attributes_destroy(state);
+               return false;
+       }
+
+       iotcon_attributes_destroy(state);
+
+       return true;
+}
+
+bool ResourceClient::getControlRepresentation(const iotcon_representation_h repr)
+{
+       iotcon_attributes_h state = NULL;
+
+       const int ret = iotcon_representation_get_attributes(repr, &state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_get_attributes() Fail(%d)", ret);
+               return false;
+       }
+
+       IotconToRrs converter(__controlData, __controlSchema, state);
+
+       converter.getFromIotcon();
+
+       return true;
+}
+
+bool ResourceClient::getEventRepresentation(const iotcon_representation_h repr)
+{
+       iotcon_attributes_h state = NULL;
+
+       const int ret = iotcon_representation_get_attributes(repr, &state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_get_attributes() Fail(%d)", ret);
+               return false;
+       }
+
+       IotconToRrs converter(__eventData, __eventSchema, state);
+
+       converter.getFromIotcon();
+
+       return true;
+}
+
+bool ResourceClient::onResponseDelete(const iotcon_response_h response)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+       iotcon_response_result_e response_result;
+
+       ret = iotcon_response_get_result(response, &response_result);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_get_result() Fail(%d)", ret);
+               return false;
+       }
+
+       if (response_result != IOTCON_RESPONSE_OK && response_result != IOTCON_RESPONSE_RESOURCE_DELETED) {
+               ERR("on_response_delete Response error(%d)", response_result);
+               return false;
+       }
+
+       handle = ClientManager::__get_instance().getHandle(this);
+
+       if (__destroycb != NULL)
+               __destroycb(RRS_ERROR_NONE, handle, __destroyData);
+
+       DBG("DELETE request was successful");
+
+       return true;
+}
+
+bool ResourceClient::onResponsePut(const iotcon_response_h response)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+       iotcon_response_result_e response_result;
+
+       ret = iotcon_response_get_result(response, &response_result);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_get_result() Fail(%d)", ret);
+               return false;
+       }
+
+       if (response_result != IOTCON_RESPONSE_OK) {
+               ERR("on_response_put Response error(%d)", response_result);
+               return false;
+       }
+
+       handle = ClientManager::__get_instance().getHandle(this);
+
+       if (__sendControlcb != NULL)
+               __sendControlcb(RRS_ERROR_NONE, handle, __sendControlData);
+
+       DBG("PUT request was successful");
+
+       return true;
+}
+
+bool ResourceClient::onResponseGetEvent(const iotcon_response_h response)
+{
+       int ret = IOTCON_ERROR_NONE;
+
+       ret = iotcon_response_get_representation(response, &__eventRepr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_get_representation() Fail(%d)", ret);
+               return false;
+       }
+
+       getEventRepresentation(__eventRepr);
+
+       DBG("GET event request was successful");
+
+       return true;
+}
+
+bool ResourceClient::onResponseGetControl(const iotcon_response_h response)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+       iotcon_representation_h repr;
+
+       ret = iotcon_response_get_representation(response, &repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_get_representation() Fail(%d)", ret);
+               return false;
+       }
+
+       getControlRepresentation(repr);
+
+       handle = ClientManager::__get_instance().getHandle(this);
+
+       if (__monitorControlEnabled) {
+               if (__monitorControlcb != NULL) {
+                       __monitorControlcb(RRS_ERROR_NONE, handle, __controlData, __monitorControlData);
+                       __monitorControlEnabled = false;
+               }
+       }
+
+       if (__receiveEventEnabled) {
+               if (__receiveEventcb != NULL) {
+                       rrs_convert_control_to_event_data(__controlData, &__eventData);
+                       __receiveEventcb(RRS_ERROR_NONE, handle, __eventData, __receiveEventData);
+                       __receiveEventEnabled = false;
+               }
+       }
+
+       iotcon_representation_destroy(repr);
+
+       DBG("GET control request was successful");
+
+       return true;
+}
+
+bool ResourceClient::deleteResource(rrs_resource_destroy_cb callback, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+       int handle = ERROR_HANDLE;
+
+       INFO("Delete Resource has been initiated");
+
+       __destroycb = callback;
+       __destroyData = user_data;
+
+       ret = iotcon_remote_resource_delete(__remoteResource, ResourceClient::__on_response, NULL);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("iotcon_remote_resource_delete() Fail(%d)", ret);
+               return false;
+       }
+
+       iotcon_remote_resource_destroy(__remoteResource);
+
+       observeUnregister();
+
+       free(__hostAddress);
+
+       if (__eventData)
+               rrs_data_destroy(__eventData);
+       __eventData = NULL;
+
+       if (__controlData)
+               rrs_data_destroy(__controlData);
+       __controlData = NULL;
+
+       if (__eventSchema)
+               rrs_schema_destroy(__eventSchema);
+       __eventSchema = NULL;
+
+       if (__controlSchema)
+               rrs_schema_destroy(__controlSchema);
+       __controlSchema = NULL;
+
+       handle = ClientManager::__get_instance().getHandle(this);
+
+       if (!ClientManager::__get_instance().deleteHandle(handle)) {
+               ERR("Cannot delete handle - %d", handle);
+               return false;
+       }
+
+       if (!ClientManager::__get_instance().deleteResource(__remoteResource)) {
+               ERR("Cannot delete remote resource handle - %d", __remoteResource);
+               return false;
+       }
+
+       return true;
+}
+
+bool ResourceClient::putControlData(rrs_resource_send_control_cb callback, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+       iotcon_representation_h repr = NULL;
+
+       INFO("Put Control Data has been initiated");
+
+       __sendControlcb = callback;
+       __sendControlData = user_data;
+
+       ret = iotcon_representation_create(&repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_create() Fail(%d)", ret);
+               return false;
+       }
+
+       if (!setControlRepresentation(&repr)) {
+               ERR("set_representation failed!");
+               iotcon_representation_destroy(repr);
+               return false;
+       }
+
+       ret = iotcon_remote_resource_put(__remoteResource, repr, NULL, ResourceClient::__on_response, (void *) this);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_post() Fail(%d)", ret);
+               iotcon_representation_destroy(repr);
+               return false;
+       }
+
+       iotcon_representation_destroy(repr);
+
+       return true;
+}
+
+bool ResourceClient::getControlData(rrs_resource_monitor_control_cb callback, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+
+       INFO("Get Control Data has been initiated");
+
+       __monitorControlcb = callback;
+       __monitorControlData = user_data;
+       __monitorControlEnabled = true;
+
+       ret = iotcon_remote_resource_get(__remoteResource, NULL, ResourceClient::__on_response, (void *) this);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("iotcon_remote_resource_get() Fail(%d)", ret);
+               return false;
+       }
+
+       return true;
+}
+
+bool ResourceClient::getEventData(rrs_resource_receive_event_cb callback, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+
+       INFO("Get Event Data has been initiated");
+
+       __receiveEventcb = callback;
+       __receiveEventData = user_data;
+       __receiveEventEnabled = true;
+
+       ret = iotcon_remote_resource_get(__remoteResource, NULL, ResourceClient::__on_response, (void *) this);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("iotcon_remote_resource_get() Fail(%d)", ret);
+               return false;
+       }
+
+       return true;
+}
+
+bool ResourceClient::observeRegister(rrs_resource_observe_cb callback, void *user_data)
+{
+       int ret = IOTCON_ERROR_NONE;
+       __observecb = callback;
+       __observeData = user_data;
+
+       ret = iotcon_representation_create(&__eventRepr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_remote_resource_observe_register(__remoteResource, IOTCON_OBSERVE_IGNORE_OUT_OF_ORDER, NULL, ResourceClient::__on_observe, (void *) this);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_observe_register() Fail(%d)", ret);
+               return false;
+       }
+
+       __observeEnabled = true;
+
+       return true;
+}
+
+bool ResourceClient::observeUnregister()
+{
+       if (__observeEnabled == true) {
+               iotcon_representation_destroy(__eventRepr);
+
+               iotcon_remote_resource_observe_deregister(__remoteResource);
+               __observeEnabled = false;
+       }
+
+       return true;
+}
diff --git a/src/client/ResourceClient.h b/src/client/ResourceClient.h
new file mode 100644 (file)
index 0000000..8f48f75
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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_CLIENT_H_
+#define _RESOURCE_CLIENT_H_
+
+#include "ResourceClient.h"
+#include <iotcon.h>
+#include "rrs.h"
+#include "schema.h"
+#include "services_common.h"
+
+class ResourceClient {
+public:
+       ResourceClient();
+       virtual ~ResourceClient();
+       bool setControlRepresentation(iotcon_representation_h *repr);
+       bool getControlRepresentation(const iotcon_representation_h repr);
+       bool getEventRepresentation(const iotcon_representation_h repr);
+       bool onResponseDelete(const iotcon_response_h response);
+       bool onResponsePut(const iotcon_response_h response);
+       bool onResponseGetControl(const iotcon_response_h response);
+       bool onResponseGetEvent(const iotcon_response_h response);
+       bool deleteResource(rrs_resource_destroy_cb callback, void *user_data);
+       bool putControlData(rrs_resource_send_control_cb callback, void *user_data);
+       bool getControlData(rrs_resource_monitor_control_cb callback, void *user_data);
+       bool getEventData(rrs_resource_receive_event_cb callback, void *user_data);
+       bool observeRegister(rrs_resource_observe_cb callback, void *user_data);
+       bool observeUnregister();
+
+       static void __on_observe(iotcon_remote_resource_h resource, iotcon_error_e err, int sequence_number, iotcon_response_h response, void *user_data);
+       static void __on_response(iotcon_remote_resource_h resource, iotcon_error_e err, iotcon_request_type_e request_type, iotcon_response_h response, void *user_data);
+       static bool __found_discovery_resource(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data);
+       static bool __found_resource(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data);
+
+       rrs_resource_found_cb __foundcb;
+       rrs_resource_found_cb __foundDiscoverycb;
+       rrs_resource_observe_cb __observecb;
+       rrs_resource_send_control_cb __sendControlcb;
+       rrs_resource_monitor_control_cb __monitorControlcb;
+       rrs_resource_receive_event_cb __receiveEventcb;
+       rrs_resource_destroy_cb __destroycb;
+       iotcon_remote_resource_h __remoteResource;
+       iotcon_resource_interfaces_h __interfaces;
+       iotcon_connectivity_type_e __connectivityType;
+       iotcon_representation_h __eventRepr;
+       void *__foundData;
+       void *__foundDiscoveryData;
+       void *__observeData;
+       void *__sendControlData;
+       void *__monitorControlData;
+       void *__receiveEventData;
+       void *__destroyData;
+       rrs_h __rrs;
+       rrs_resource_e __resourceType;
+       rrs_schema_h __controlSchema;
+       rrs_schema_h __eventSchema;
+       rrs_data_h __controlData;
+       rrs_data_h __eventData;
+       bool __observeEnabled;
+       bool __monitorControlEnabled;
+       bool __receiveEventEnabled;
+       char *__type;
+       char *__hostAddress;
+};
+
+#endif /* _ResourceClient_H_ */
diff --git a/src/client/RrsManager.cpp b/src/client/RrsManager.cpp
new file mode 100644 (file)
index 0000000..29d85d2
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "RrsManager.h"
+#include <stdlib.h>
+#include <glib.h>
+#include <string>
+#include "common.h"
+
+RrsManager::RrsManager()
+{
+}
+
+RrsManager::~RrsManager()
+{
+}
+
+void RrsManager::addResource(const rrs_resource_e res, FindResourceInfo info)
+{
+       rrs_manager_map::iterator it;
+
+       it = __manager_map.find(res);
+
+       if (it != __manager_map.end())
+               __manager_map.erase (it);
+
+       __manager_map.insert(std::pair<rrs_resource_e, FindResourceInfo>(res, info));
+}
+
+bool RrsManager::deleteResource(const rrs_resource_e res)
+{
+       rrs_manager_map::iterator it;
+
+       it = __manager_map.find(res);
+
+       if (it != __manager_map.end())
+               __manager_map.erase (it);
+
+       return true;
+}
+
+FindResourceInfo *RrsManager::getResourceInfo(const rrs_resource_e res)
+{
+       rrs_manager_map::iterator it;
+
+       it = __manager_map.find(res);
+
+       if (it == __manager_map.end())
+               return NULL;
+
+       return &(it->second);
+}
+
+RrsManager& RrsManager::__get_instance()
+{
+       static RrsManager inst;
+       return inst;
+}
diff --git a/src/client/RrsManager.h b/src/client/RrsManager.h
new file mode 100644 (file)
index 0000000..6c8307c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _RRS_MANAGER_H_
+#define _RRS_MANAGER_H_
+
+#include <stdint.h>
+#include <map>
+#include "rrs.h"
+#include "FindResourceInfo.h"
+
+class RrsManager {
+public:
+       typedef std::map<rrs_resource_e, FindResourceInfo> rrs_manager_map;
+
+       static RrsManager& __get_instance();
+       void addResource(const rrs_resource_e res, FindResourceInfo info);
+       bool deleteResource(const rrs_resource_e res);
+       FindResourceInfo *getResourceInfo(const rrs_resource_e res);
+
+       rrs_manager_map __manager_map;
+private:
+       RrsManager();
+       virtual ~RrsManager();
+};
+
+#endif /* _RRS_MANAGER_H_ */
diff --git a/src/client/rrs-client.pc.in b/src/client/rrs-client.pc.in
new file mode 100644 (file)
index 0000000..6212f9b
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}/bin
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: @CLIENT@
+Description: Remote Resource Service
+Version: @FULLVER@
+Requires:
+Libs: -L${libdir} -l@CLIENT@
+Cflags: -I${includedir}
+
diff --git a/src/client/rrs_resource.cpp b/src/client/rrs_resource.cpp
new file mode 100644 (file)
index 0000000..2aa7b5a
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "rrs.h"
+#include <glib.h>
+#include <string>
+#include "schema.h"
+#include "ResourceClient.h"
+#include "ClientManager.h"
+#include "RrsManager.h"
+
+extern bool __has_iot_privilege();
+
+#define INVALID_RESOURCE_HANDLE 0
+
+static Mutex rrs_manager_mutex;
+
+void rrs_type_to_name(const rrs_resource_e type, char **resource_name)
+{
+       switch(type) {
+               case RRS_RESOURCE_DISCOVERY:
+                       *resource_name = strdup(DISCOVERY_RESOURCE_NAME);
+                       break;
+               case RRS_RESOURCE_ACCELEROMETER:
+                       *resource_name = strdup(ACCELEROMETER_RESOURCE_NAME);
+                       break;
+               case RRS_RESOURCE_PROXIMITY:
+                       *resource_name = strdup(PROXIMITY_RESOURCE_NAME);
+                       break;
+               default :
+                       ERR("Resource [%d] not supported!", type);
+                       break;
+       }
+}
+
+EXPORT_API int rrs_resource_find(const rrs_h rrs, const rrs_resource_e type, rrs_resource_found_cb callback, void *user_data)
+{
+       char *resource_name;
+       FindResourceInfo info;
+       FindResourceInfo *info_ptr = NULL;
+       int ret = IOTCON_ERROR_NONE;
+
+       /* Check if RRS handle is valid */
+       if (rrs < 1 || rrs > MAX_RRS_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if ((type < RRS_RESOURCE_NONE)
+           || (type > RRS_RESOURCE_ALL)
+           || !callback)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       rrs_type_to_name(type, &resource_name);
+
+       info.__rrs = rrs;
+       info.__resourceType = type;
+       info.__foundcb = callback;
+       info.__foundData = user_data;
+
+       {
+               AUTOLOCK(rrs_manager_mutex);
+               RrsManager::__get_instance().addResource(type, info);
+       }
+
+       info_ptr = RrsManager::__get_instance().getResourceInfo(type);
+
+       if (type == RRS_RESOURCE_DISCOVERY) {
+               /* find discovery resource */
+               ret = iotcon_find_resource(IOTCON_MULTICAST_ADDRESS, IOTCON_CONNECTIVITY_IPV4, resource_name, false, ResourceClient::__found_discovery_resource, (void *)info_ptr);
+
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_find_resource() Fail(%d)", ret);
+                       iotcon_deinitialize();
+                       return false;
+               }
+
+               DBG("Find discovery Resource has been initiated!");
+       } else {
+               /* find resources */
+               ret = iotcon_find_resource(IOTCON_MULTICAST_ADDRESS, IOTCON_CONNECTIVITY_IPV4, resource_name, false, ResourceClient::__found_resource, (void *)info_ptr);
+
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_find_resource() Fail(%d)", ret);
+                       iotcon_deinitialize();
+                       return false;
+               }
+
+               DBG("Find Resource has been initiated!");
+       }
+
+       free(resource_name);
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_foreach_resource(const rrs_h rrs, const rrs_resource_e type, rrs_foreach_resource_cb callback, void *user_data)
+{
+       /* Check if RRS handle is valid */
+       if (rrs < 1 || rrs > MAX_RRS_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if ((type < RRS_RESOURCE_NONE)
+           || (type > RRS_RESOURCE_ALL)
+           || !callback)
+               return RRS_ERROR_INVALID_TYPE;
+
+       if (!ClientManager::__get_instance().iterateForEachResource(type, callback, user_data)) {
+               ERR("Error iterating over found handles for resource [%d]!", type);
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_destroy(const rrs_resource_h handle, rrs_resource_destroy_cb callback, void *user_data)
+{
+       ResourceClient *client = NULL;
+       rrs_resource_e *type = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (!client->deleteResource(callback, user_data)) {
+               ERR("Error deleting resource!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       *type = client->__resourceType;
+
+       {
+               AUTOLOCK(rrs_manager_mutex);
+               if (!RrsManager::__get_instance().deleteResource(*type)) {
+                       ERR("Error deleting resource!");
+                       return RRS_ERROR_INVALID_OPERATION;
+               }
+       }
+
+       delete client;
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_get_count(const rrs_h rrs, const rrs_resource_e type, int *count)
+{
+       /* Check if RRS handle is valid */
+       if (rrs < 1 || rrs > MAX_RRS_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if ((type < RRS_RESOURCE_NONE)
+           || (type > RRS_RESOURCE_ALL))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       *count = ClientManager::__get_instance().getCount(type);
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_get_type(const rrs_resource_h handle, rrs_resource_e *type)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if RRS handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       *type = client->__resourceType;
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_get_device_name(const rrs_resource_h handle, char **device_name)
+{
+       ResourceClient *client = NULL;
+       char *deviceName = NULL;
+       int ret = IOTCON_ERROR_NONE;
+
+       /* Check if RRS handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       ret = iotcon_remote_resource_get_device_name(client->__remoteResource, &deviceName);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("iotcon_remote_resource_get_device_name() Fail(%d)", ret);
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+       DBG("[%s] resource device name : %s", client->__uriPath, deviceName);
+       *device_name = strdup(deviceName);
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_get_device_id(const rrs_resource_h handle, char **device_id)
+{
+       ResourceClient *client = NULL;
+       char *deviceID = NULL;
+       int ret = IOTCON_ERROR_NONE;
+
+       /* Check if RRS handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       ret = iotcon_remote_resource_get_device_id(client->__remoteResource, &deviceID);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_get_device_id() Fail(%d)", ret);
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+       DBG("[%s] resource device id : %s", handle, deviceID);
+
+       *device_id = strdup(deviceID);
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_get_uri_path(const rrs_resource_h handle, char **uri_path)
+{
+       ResourceClient *client = NULL;
+       char *uriPath = NULL;
+       int ret = IOTCON_ERROR_NONE;
+
+       /* Check if RRS handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       ret = iotcon_remote_resource_get_uri_path(client->__remoteResource, &uriPath);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_remote_resource_get_uri_path() Fail(%d)", ret);
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       *uri_path = strdup(uriPath);
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_receive_event(const rrs_resource_h handle, rrs_resource_receive_event_cb callback, void *user_data)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (!client->getEventData(callback, user_data)) {
+               ERR("Error getting event data from remote resource!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_monitor_control(const rrs_resource_h handle, rrs_resource_monitor_control_cb callback, void *user_data)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (!client->getControlData(callback, user_data)) {
+               ERR("Error getting control data from remote resource!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_send_control(const rrs_resource_h handle, const rrs_control_data_h control_data, rrs_resource_send_control_cb callback, void *user_data)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!control_data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (control_data != client->__controlData) {
+               rrs_control_data_destroy(client->__controlData);
+               rrs_control_data_clone(control_data, &(client->__controlData));
+       }
+
+       if (!client->putControlData(callback, user_data)) {
+               ERR("Error sending control data from remote resource!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_subscribe_event(const rrs_resource_h handle, rrs_resource_observe_cb callback, void *user_data)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE) {
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       /* Check if parameters are valid */
+       if (!callback) {
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (!client->observeRegister(callback, user_data)) {
+               ERR("Error registering for observe functionality!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_resource_unsubscribe_event(const rrs_resource_h handle)
+{
+       ResourceClient *client = NULL;
+
+       /* Check if resource handle is valid */
+       if (handle == INVALID_RESOURCE_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       if (!ClientManager::__get_instance().getResourceFromHandle(handle, &client))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (!client->observeUnregister()) {
+               ERR("Error unregistering observe functionality!");
+               return RRS_ERROR_INVALID_OPERATION;
+       }
+
+       return RRS_ERROR_NONE;
+}
diff --git a/src/common/BaseLock.cpp b/src/common/BaseLock.cpp
new file mode 100755 (executable)
index 0000000..27a79dd
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "BaseLock.h"
+#include <stdio.h>
+#include <pthread.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "common.h"
+
+BaseLock::BaseLock()
+{
+       __historyMutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+BaseLock::~BaseLock()
+{
+       pthread_mutex_destroy(&__historyMutex);
+}
+
+void BaseLock::lock(LockType type, const char* expr, const char *module, const char *func, int line)
+{
+       int ret = 0;
+       char m_curent_info[OWNER_INFO_LEN];
+       struct timeval sv;
+       unsigned long long lock_waiting_start_time = 0;
+       unsigned long long lock_acquired_time = 0;
+       unsigned long long waiting_time = 0;
+
+       snprintf(m_curent_info, OWNER_INFO_LEN, "%s:%s(%d)", module, func, line);
+
+       if (type == LOCK_TYPE_MUTEX)
+               ret = tryLockImpl();
+       else if (type == LOCK_TYPE_READ)
+               ret = tryReadLockImpl();
+       else if (type == LOCK_TYPE_WRITE)
+               ret = tryWriteLockImpl();
+
+       if (ret == 0) {
+               pthread_mutex_lock(&__historyMutex);
+               snprintf(__ownerInfo, OWNER_INFO_LEN, "%s", m_curent_info);
+               pthread_mutex_unlock(&__historyMutex);
+               return;
+       }
+
+       gettimeofday(&sv, NULL);
+       lock_waiting_start_time = MICROSECONDS(sv);
+
+       pthread_mutex_lock(&__historyMutex);
+       INFO("%s is waiting for getting %s(0x%x) owned in %s",
+                       m_curent_info, expr, this, __ownerInfo);
+       pthread_mutex_unlock(&__historyMutex);
+
+
+       if (type == LOCK_TYPE_MUTEX)
+               lockImpl();
+       else if (type == LOCK_TYPE_READ)
+               readLockImpl();
+       else if (type == LOCK_TYPE_WRITE)
+               writeLockImpl();
+
+       gettimeofday(&sv, NULL);
+       lock_acquired_time = MICROSECONDS(sv);
+
+       waiting_time = lock_acquired_time - lock_waiting_start_time;
+
+       pthread_mutex_lock(&__historyMutex);
+       INFO("%s acquires lock after waiting %lluus, %s(0x%x) was previously owned in %s",
+                       m_curent_info, waiting_time, expr, this, __ownerInfo);
+       snprintf(__ownerInfo, OWNER_INFO_LEN, "%s", m_curent_info);
+       pthread_mutex_unlock(&__historyMutex);
+}
+
+
+void BaseLock::lock(LockType type)
+{
+       if (type == LOCK_TYPE_MUTEX)
+               lockImpl();
+       else if (type == LOCK_TYPE_READ)
+               readLockImpl();
+       else if (type == LOCK_TYPE_WRITE)
+               writeLockImpl();
+}
+
+void BaseLock::unlock(void)
+{
+       unlockImpl();
+}
+
+int BaseLock::lockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::readLockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::writeLockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::tryLockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::tryReadLockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::tryWriteLockImpl(void)
+{
+       return 0;
+}
+
+int BaseLock::unlockImpl(void)
+{
+       return 0;
+}
+
+Autolock::Autolock(BaseLock &m, LockType type, const char* expr, const char *module, const char *func, int line)
+: __lock(m)
+{
+       __lock.lock(type, expr, module, func, line);
+}
+
+Autolock::Autolock(BaseLock &m, LockType type)
+: __lock(m)
+{
+       __lock.lock(type);
+}
+
+Autolock::~Autolock()
+{
+       __lock.unlock();
+}
diff --git a/src/common/BaseLock.h b/src/common/BaseLock.h
new file mode 100755 (executable)
index 0000000..0954a81
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * IOT_Broker_Service
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if !defined(_BASE_LOCK_H_)
+#define _BASE_LOCK_H_
+
+#include <pthread.h>
+
+enum LockType {
+       LOCK_TYPE_MUTEX,
+       LOCK_TYPE_READ,
+       LOCK_TYPE_WRITE,
+};
+
+#ifdef _LOCK_DEBUG
+#define AUTOLOCK(x) Autolock x##_autolock((x), LOCK_TYPE_MUTEX, #x, __MODULE__, __func__, __LINE__)
+#define AUTOLOCK_R(x) Autolock x##_autolock_r((x), LOCK_TYPE_READ, #x,  __MODULE__, __func__, __LINE__)
+#define AUTOLOCK_W(x) Autolock x##_autolock_w((x), LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__)
+#define LOCK(x)                (x).lock(#x, __MODULE__, __func__, __LINE__)
+#define LOCK_R(x)      (x).lock(LOCK_TYPE_READ, #x, __MODULE__, __func__, __LINE__)
+#define LOCK_W(x)      (x).lock(LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__)
+#define UNLOCK(x)      (x).unlock()
+#else
+#define AUTOLOCK(x) Autolock x##_autolock((x), LOCK_TYPE_MUTEX)
+#define AUTOLOCK_R(x) Autolock x##_autolock_r((x), LOCK_TYPE_READ)
+#define AUTOLOCK_W(x) Autolock x##_autolock_w((x), LOCK_TYPE_WRITE)
+#define LOCK(x)                (x).lock()
+#define LOCK_R(x)      (x).lock(LOCK_TYPE_READ)
+#define LOCK_W(x)      (x).lock(LOCK_TYPE_WRITE)
+#define UNLOCK(x)      (x).unlock()
+#endif
+
+
+class BaseLock {
+public:
+       BaseLock();
+       virtual ~BaseLock();
+
+       void lock(LockType type, const char* expr, const char *module, const char *func, int line);
+       void lock(LockType type);
+       void unlock(void);
+
+protected:
+       virtual int lockImpl(void);
+       virtual int readLockImpl(void);
+       virtual int writeLockImpl(void);
+
+       virtual int tryLockImpl(void);
+       virtual int tryReadLockImpl(void);
+       virtual int tryWriteLockImpl(void);
+
+       virtual int unlockImpl(void);
+private:
+       pthread_mutex_t __historyMutex;
+       static const int OWNER_INFO_LEN = 256;
+       char __ownerInfo[OWNER_INFO_LEN];
+};
+
+class Autolock {
+public:
+       Autolock(BaseLock &m, LockType type, const char* expr, const char *module, const char *func, int line);
+       Autolock(BaseLock &m, LockType type);
+       ~Autolock();
+private:
+       BaseLock& __lock;
+};
+
+#endif
+// End of a file
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..db4988b
--- /dev/null
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 2.6)
+project(rrs-common CXX)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(rrs-common-pkgs REQUIRED glib-2.0 dlog json-glib-1.0 iotcon cynara-client capi-system-info libtzplatform-config)
+
+INCLUDE_DIRECTORIES(include)
+FILE(GLOB rrs-common-srcs *.c *.cpp)
+
+FOREACH(flag ${rrs-common-pkgs_LDFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${rrs-common-pkgs_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+add_library(${PROJECT_NAME} SHARED ${rrs-common-srcs} )
+
+target_link_libraries(${PROJECT_NAME} ${rrs-common-pkgs_LDFLAGS} "-lrt -ldl -pthread")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"RRS-COMMON\"")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+
+install(TARGETS ${PROJECT_NAME} DESTINATION lib)
+
+INSTALL(FILES schemas/rrsdiscovery.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/sensorcontrol.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/accelerometer.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/proximity.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/autorotation.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/geomagneticrotationvector.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/gravity.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/gyroscope.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/gyroscoperotationvector.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/hrm.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/hrmledgreen.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/hrmledir.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/hrmledred.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/humidity.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/light.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/linearacceleration.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/magnetometer.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/orientation.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/pressure.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/rotationvector.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/temperature.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/uncalibratedgyroscope.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/uncalibratedmagnetometer.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES schemas/uv.json DESTINATION /usr/lib/rrs/schemas)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/rrs-svr-db.dat DESTINATION /usr/share/rrs)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/rrs-svr-db.dat DESTINATION /root/share/rrs/)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/rrs-svr-db.dat DESTINATION /home/owner/share/rrs/)
\ No newline at end of file
diff --git a/src/common/IotconToRrs.cpp b/src/common/IotconToRrs.cpp
new file mode 100644 (file)
index 0000000..fe679a9
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "IotconToRrs.h"
+#include <glib.h>
+#include "common.h"
+
+IotconToRrs::IotconToRrs(rrs_data_h d,
+                      rrs_schema_h sch,
+                      iotcon_attributes_h st)
+: __data(d)
+, __schema(sch)
+, __state(st)
+{
+}
+
+IotconToRrs::~IotconToRrs()
+{
+}
+
+bool IotconToRrs::__foreach_field_get_cb(int index,
+                                            int total,
+                                            const char *name,
+                                            const RrsSchemaType type,
+                                            const RrsSchemaAccess access,
+                                            const bool required,
+                                            void *value,
+                                            void *user_data)
+{
+       if (!user_data)
+               return false;
+       IotconToRrs *obj = (IotconToRrs *)user_data;
+
+       (obj->__mutex).lock();
+       switch (type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               break;
+       case RRS_SCHEMA_TYPE_BOOL: {
+               bool b = false;
+               int ret = iotcon_attributes_get_bool(obj->__state, name, &b);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_get_bool() Fail(%d)", ret);
+                       return false;
+               }
+               *((bool *)value) = b;
+               break;
+       }
+       case RRS_SCHEMA_TYPE_INT: {
+               int n = 0;
+               int ret = iotcon_attributes_get_int(obj->__state, name, &n);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_get_int() Fail(%d)", ret);
+                       return false;
+               }
+               *((int *)value) = n;
+               break;
+       }
+       case RRS_SCHEMA_TYPE_DOUBLE: {
+               double d = .0;
+               int ret = iotcon_attributes_get_double(obj->__state, name, &d);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_get_double() Fail(%d)", ret);
+                       return false;
+               }
+               *((double *)value) = d;
+               break;
+       }
+       case RRS_SCHEMA_TYPE_STR: {
+               char *c = NULL;
+               int ret = iotcon_attributes_get_str(obj->__state, name, &c);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_get_str() Fail(%d)", ret);
+                       return false;
+               }
+               rrs_data_set_string(obj->__data, name, c);
+               break;
+       }
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               INFO("Converting of complex types are not supported yet");
+               break;
+       default:
+               ERR("Unsupported type");
+               break;
+       }
+       return true;
+}
+
+bool IotconToRrs::__foreach_field_set_cb(int index,
+                                            int total,
+                                            const char *name,
+                                            const RrsSchemaType type,
+                                            const RrsSchemaAccess access,
+                                            const bool required,
+                                            void *value,
+                                            void *user_data)
+{
+       if (!user_data)
+               return false;
+       IotconToRrs *obj = (IotconToRrs *)user_data;
+
+       (obj->__mutex).lock();
+       switch (type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               break;
+       case RRS_SCHEMA_TYPE_BOOL: {
+               int ret = iotcon_attributes_add_bool(obj->__state, name, *((bool *)value));
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_add_bool() Fail(%d)", ret);
+                       iotcon_attributes_destroy(obj->__state);
+                       return false;
+               }
+               break;
+       }
+       case RRS_SCHEMA_TYPE_INT: {
+               int ret = iotcon_attributes_add_int(obj->__state, name, *((int *)value));
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_add_int() Fail(%d)", ret);
+                       iotcon_attributes_destroy(obj->__state);
+                       return false;
+               }
+               break;
+       }
+       case RRS_SCHEMA_TYPE_DOUBLE: {
+               int ret = iotcon_attributes_add_double(obj->__state, name, *((double *)value));
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_add_double() Fail(%d)", ret);
+                       iotcon_attributes_destroy(obj->__state);
+                       return false;
+               }
+               break;
+       }
+       case RRS_SCHEMA_TYPE_STR: {
+               int ret = iotcon_attributes_add_str(obj->__state, name, (char *)value);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_attributes_add_str() Fail(%d)", ret);
+                       iotcon_attributes_destroy(obj->__state);
+                       return false;
+               }
+               break;
+       }
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               INFO("Converting of complex types are not supported yet");
+               break;
+       default:
+               ERR("Unsupported type");
+               break;
+       }
+       return true;
+}
+
+void IotconToRrs::getFromIotcon()
+{
+       const int ret = rrs_data_foreach_field(__data,
+                          __schema,
+                          __foreach_field_get_cb,
+                          this);
+
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_data_foreach_field() failed");
+       }
+}
+
+void IotconToRrs::setToIotcon()
+{
+       const int ret = rrs_data_foreach_field(__data,
+                          __schema,
+                          __foreach_field_set_cb,
+                          this);
+
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_data_foreach_field() failed");
+       }
+}
diff --git a/src/common/IotconToRrs.h b/src/common/IotconToRrs.h
new file mode 100644 (file)
index 0000000..e375076
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 _IOTCON_TO_RRS_H_
+#define _IOTCON_TO_RRS_H_
+
+#include <iotcon.h>
+#include "rrs.h"
+#include "schema.h"
+#include "Mutex.h"
+
+class IotconToRrs {
+public:
+       IotconToRrs(rrs_data_h data, rrs_schema_h schema, iotcon_attributes_h state);
+       ~IotconToRrs();
+
+       void getFromIotcon();
+       void setToIotcon();
+private:
+       static bool __foreach_field_get_cb(int index,
+                                        int total,
+                                        const char *name,
+                                        const RrsSchemaType type,
+                                        const RrsSchemaAccess access,
+                                        const bool required,
+                                        void *value,
+                                        void *user_data);
+
+       static bool __foreach_field_set_cb(int index,
+                                        int total,
+                                        const char *name,
+                                        const RrsSchemaType type,
+                                        const RrsSchemaAccess access,
+                                        const bool required,
+                                        void *value,
+                                        void *user_data);
+
+       rrs_data_h __data;
+       rrs_schema_h __schema;
+       iotcon_attributes_h __state;
+       Mutex __mutex;
+};
+
+#endif /*_IOTCON_TO_RRS_H_*/
diff --git a/src/common/Json.cpp b/src/common/Json.cpp
new file mode 100644 (file)
index 0000000..72b0269
--- /dev/null
@@ -0,0 +1,996 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 "Json.h"
+#include <string>
+#include <sstream>
+#include <locale>
+#include <iomanip>
+#include <json-glib/json-glib.h>
+#include "schema_types_internal.h"
+
+#define PATH_DELIM     '.'
+#define GVAR_VALUES    "values"
+#define GVAR_TYPES     "types"
+
+static double __string_to_double(const char* in)
+{
+       IF_FAIL_RETURN_TAG(in, 0, _E, "Parameter NULL");
+
+       // Locale-independent string-to-double conversion
+       double out;
+       std::istringstream istr(in);
+       istr.imbue(std::locale("C"));
+       istr >> out;
+       return out;
+}
+
+static std::string __double_to_string(double in, int prec)
+{
+       // Locale-independent double-to-string conversion
+       std::ostringstream ostr;
+       ostr.imbue(std::locale("C"));
+       ostr << std::setprecision(prec) << std::fixed << in;
+       return ostr.str();
+}
+
+Json::Json()
+       : __jsonNode(NULL)
+{
+       JsonObject *obj = json_object_new();
+       IF_FAIL_VOID_TAG(obj, _E, "Json object construction failed");
+
+       __jsonNode = json_node_new(JSON_NODE_OBJECT);
+       if (!__jsonNode) {
+               json_object_unref(obj);
+               _E("Json object construction failed");
+       }
+
+       json_node_set_object(__jsonNode, obj);
+       json_object_unref(obj);
+}
+
+Json::Json(const Json& j)
+       : __jsonNode(NULL)
+{
+       __jsonNode = json_node_copy(j.__jsonNode);
+       IF_FAIL_VOID_TAG(__jsonNode, _E, "Json object construction failed");
+}
+
+Json::Json(const char* s)
+       : __jsonNode(NULL)
+{
+       if (s) {
+               parse(s);
+       } else {
+               parse(EMPTY_JSON_OBJECT);
+       }
+}
+
+Json::Json(const std::string& s)
+       : __jsonNode(NULL)
+{
+       if (s.empty()) {
+               parse(EMPTY_JSON_OBJECT);
+       } else {
+               parse(s.c_str());
+       }
+}
+
+Json::~Json()
+{
+       release();
+}
+
+void Json::load(const char *file)
+{
+       gboolean result;
+       JsonParser *parser = NULL;
+       JsonNode *root = NULL;
+
+       parser = json_parser_new();
+       IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed");
+
+       /*result = json_parser_load_from_data(parser, s, -1, NULL);*/
+
+       result = json_parser_load_from_file(parser, file, NULL);
+       IF_FAIL_CATCH_TAG(result, _E, "Parsing failed");
+
+       root = json_parser_get_root(parser);
+       IF_FAIL_CATCH_TAG(root, _E, "Getting root failed");
+
+       __jsonNode = json_node_copy(root);
+       IF_FAIL_CATCH_TAG(__jsonNode, _E, "Copying failed");
+
+CATCH:
+       if (parser)
+               g_object_unref(parser);
+}
+
+void Json::parse(const char* s)
+{
+       gboolean result;
+       JsonParser *parser = NULL;
+       JsonNode *root = NULL;
+
+       parser = json_parser_new();
+       IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed");
+
+       result = json_parser_load_from_data(parser, s, -1, NULL);
+       IF_FAIL_CATCH_TAG(result, _E, "Parsing failed");
+
+       root = json_parser_get_root(parser);
+       IF_FAIL_CATCH_TAG(root, _E, "Getting root failed");
+
+       __jsonNode = json_node_copy(root);
+       IF_FAIL_CATCH_TAG(__jsonNode, _E, "Copying failed");
+
+CATCH:
+       if (parser)
+               g_object_unref(parser);
+}
+
+void Json::release()
+{
+       if (__jsonNode) {
+               json_node_free(__jsonNode);
+               __jsonNode = NULL;
+       }
+}
+
+Json& Json::operator=(const Json& j)
+{
+       release();
+       __jsonNode = json_node_copy(j.__jsonNode);
+       if (!__jsonNode) {
+               _E("Json object copy failed");
+       }
+       return *this;
+}
+
+Json& Json::operator=(const char* s)
+{
+       release();
+       if (s) {
+               parse(s);
+       } else {
+               parse(EMPTY_JSON_OBJECT);
+       }
+       return *this;
+}
+
+Json& Json::operator=(const std::string& s)
+{
+       release();
+       if (s.empty()) {
+               parse(EMPTY_JSON_OBJECT);
+       } else {
+               parse(s.c_str());
+       }
+       return *this;
+}
+
+bool Json::operator==(const Json& rhs)
+               {
+       return nodeEquals(__jsonNode, rhs.__jsonNode);
+}
+
+bool Json::operator!=(const Json& rhs)
+               {
+       return !operator==(rhs);
+}
+
+/* TODO
+bool Json::contains(const Json& subset) const
+{
+       return false;
+}
+*/
+
+char* Json::dupCStr()
+{
+       IF_FAIL_RETURN_TAG(__jsonNode, NULL, _E, "Json object not initialized");
+
+       JsonGenerator *jgen = NULL;
+       char *output = NULL;
+
+       jgen = json_generator_new();
+       IF_FAIL_CATCH(jgen);
+
+       json_generator_set_root(jgen, __jsonNode);
+       output = json_generator_to_data(jgen, NULL);
+       IF_FAIL_CATCH(output);
+
+       g_object_unref(jgen);
+       return output;
+
+CATCH:
+       if (jgen) {
+               g_object_unref(jgen);
+       }
+
+       _E("Memory allocation failed");
+       return NULL;
+}
+
+std::string Json::str()
+{
+       std::string output;
+       char *_s = dupCStr();
+       IF_FAIL_RETURN(_s, output = EMPTY_JSON_OBJECT);
+
+       output = _s;
+       g_free(_s);
+
+       return output;
+}
+
+static char** __tokenize_path(const char* path, int* length)
+{
+       //TODO: Re-implement this tokenizer using C++ stuff
+       char** tokens;
+       const char* pch;
+       const char* begin;
+       int i;
+       int j;
+       int len;
+
+       if (path == NULL || strlen(path) == 0) {
+               *length = 0;
+               return NULL;
+       }
+
+       *length = 1;
+
+       for (pch = path; *pch != '\0'; pch++) {
+               if (*pch == PATH_DELIM) {
+                       *length = *length + 1;
+               }
+       }
+
+       tokens = static_cast<char**>(g_malloc((*length) * sizeof(char*)));
+       IF_FAIL_RETURN_TAG(tokens, NULL, _E, "Memory allocation failed");
+
+       begin = path;
+       i = 0;
+
+       for (pch = path; ; pch++) {
+               if (*pch == PATH_DELIM || *pch == '\0') {
+                       len = pch - begin;
+                       tokens[i] = static_cast<char*>(g_malloc((len+1) * sizeof(char)));
+                       IF_FAIL_CATCH_TAG(tokens[i], _E, "Memory allocation failed");
+                       strncpy(tokens[i], begin, len);
+                       tokens[i][len] = '\0';
+                       i++;
+                       begin = pch + 1;
+               }
+
+               if (*pch == '\0') {
+                       break;
+               }
+       }
+
+       return tokens;
+
+CATCH:
+       for (j=0; j < i; j++) {
+               g_free(tokens[j]);
+       }
+       g_free(tokens);
+       return NULL;
+}
+
+static void __free_tokenized_path(int length, char** tokens)
+{
+       int i;
+       if (tokens) {
+               for (i=0; i < length; i++) {
+                       g_free(tokens[i]);
+               }
+               g_free(tokens);
+       }
+}
+
+static JsonObject* __traverse(JsonNode* jnode, const char* path, bool force)
+{
+       IF_FAIL_RETURN_TAG(jnode, NULL, _E, "Invalid parameter");
+
+       int length = 0;
+       int depth = 0;
+       char **path_token = NULL;
+       JsonObject *jobj = NULL;
+       JsonObject *child_obj = NULL;
+       JsonNode *child_node = NULL;
+
+       jobj = json_node_get_object(jnode);
+       IF_FAIL_RETURN(jobj, NULL);
+
+       if (path) {
+               path_token = __tokenize_path(path, &length);
+               IF_FAIL_RETURN_TAG(path_token, NULL, _E, "Invalid path");
+       }
+
+       for (depth=0; depth < length; depth++) {
+               if (!json_object_has_member(jobj, path_token[depth])) {
+                       if (force) {
+                               child_obj = json_object_new();
+                               IF_FAIL_CATCH_TAG(child_obj, _E, "Memory allocation failed");
+                               json_object_set_object_member(jobj, path_token[depth], child_obj);
+                       } else {
+                               goto CATCH;
+                       }
+               }
+               child_node = json_object_get_member(jobj, path_token[depth]);
+               IF_FAIL_CATCH(child_node && json_node_get_node_type(child_node) == JSON_NODE_OBJECT);
+
+               jobj = json_node_get_object(child_node);
+               IF_FAIL_CATCH(jobj);
+       }
+
+       __free_tokenized_path(length, path_token);
+       return jobj;
+
+CATCH:
+       __free_tokenized_path(length, path_token);
+       return NULL;
+}
+
+bool Json::set(const char* path, const char* key, Json& val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter");
+
+       JsonObject *jobj = __traverse(__jsonNode, path, true);
+       IF_FAIL_RETURN(jobj, false);
+
+       if (json_object_has_member(jobj, key))
+               json_object_remove_member(jobj, key);
+
+       json_object_set_member(jobj, key, val.__jsonNode);
+       val.__jsonNode = NULL;
+       val = Json();
+
+       return true;
+}
+
+bool Json::set(const char* path, const char* key, int val)
+{
+       return set(path, key, static_cast<int64_t>(val));
+}
+
+bool Json::set(const char* path, const char* key, int64_t val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonObject *jobj = __traverse(__jsonNode, path, true);
+       IF_FAIL_RETURN(jobj, false);
+
+       if (json_object_has_member(jobj, key))
+               json_object_remove_member(jobj, key);
+
+       json_object_set_int_member(jobj, key, val);
+       return true;
+}
+
+bool Json::set(const char* path, const char* key, double val, int prec)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonObject *jobj = __traverse(__jsonNode, path, true);
+       IF_FAIL_RETURN(jobj, false);
+
+       if (json_object_has_member(jobj, key)) {
+               json_object_remove_member(jobj, key);
+       }
+
+       //NOTE: Json-glib causes a precision issue while handling double values
+       json_object_set_string_member(jobj, key, __double_to_string(val, prec).c_str());
+       return true;
+}
+
+bool Json::set(const char* path, const char* key, std::string val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonObject *jobj = __traverse(__jsonNode, path, true);
+       IF_FAIL_RETURN(jobj, false);
+
+       if (json_object_has_member(jobj, key)) {
+               json_object_remove_member(jobj, key);
+       }
+
+       json_object_set_string_member(jobj, key, val.c_str());
+       return true;
+}
+
+bool Json::set(const char* path, const char* key, GVariant *val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       const gchar *type_str = g_variant_get_type_string(val);
+       IF_FAIL_RETURN_TAG(type_str, false, _E, "GVariant manipulation failed");
+
+       json_node_t *node = json_gvariant_serialize(val);
+       IF_FAIL_RETURN_TAG(node, false, _E, "GVariant manipulation failed");
+
+       Json gvar_json;
+       gvar_json.set(NULL, GVAR_TYPES, type_str);
+       json_object_set_member(json_node_get_object(gvar_json.__jsonNode), GVAR_VALUES, node);
+
+       return set(path, key, gvar_json);
+}
+
+bool Json::get(const char* path, const char* key, Json* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       JsonObject *jobj = NULL;
+       JsonNode *node = NULL;
+
+       jobj = __traverse(__jsonNode, path, false);
+       IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), false);
+
+       node = json_object_dup_member(jobj, key);
+       IF_FAIL_RETURN_TAG(node, false, _E, "Memory allocation failed");
+
+       if (val->__jsonNode) {
+               json_node_free(val->__jsonNode);
+       }
+       val->__jsonNode = node;
+
+       return true;
+}
+
+static JsonNode* __search_value_node(JsonNode* jnode, const char* path, const char* key)
+{
+       JsonNode *node = NULL;
+       JsonObject *jobj = NULL;
+       JsonNodeType ntype;
+
+       jobj = __traverse(jnode, path, false);
+       IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), NULL);
+
+       node = json_object_get_member(jobj, key);
+       ntype = json_node_get_node_type(node);
+       IF_FAIL_RETURN(ntype == JSON_NODE_VALUE, NULL);
+
+       return node;
+}
+
+bool Json::get(const char* path, const char* key, int* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       int64_t v;
+
+       if (get(path, key, &v)) {
+               *val = v;
+               return true;
+       }
+
+       return false;
+}
+
+bool Json::get(const char* path, const char* key, int64_t* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_value_node(__jsonNode, path, key);
+       IF_FAIL_RETURN(node, false);
+
+       GType vtype = json_node_get_value_type(node);
+       if (vtype == G_TYPE_INT64) {
+               *val = json_node_get_int(node);
+       } else if (vtype == G_TYPE_STRING) {
+               //TODO: if the string is not a number?
+               *val = static_cast<int64_t>(__string_to_double(json_node_get_string(node)));
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+bool Json::get(const char* path, const char* key, double* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_value_node(__jsonNode, path, key);
+       IF_FAIL_RETURN(node, false);
+
+       GType vtype = json_node_get_value_type(node);
+       if (vtype == G_TYPE_DOUBLE) {
+               *val = json_node_get_double(node);
+       } else if (vtype == G_TYPE_INT64) {
+               *val = json_node_get_int(node);
+       } else if (vtype == G_TYPE_STRING) {
+               //NOTE: Json-glib causes a precision issue while handling double values
+               *val = __string_to_double(json_node_get_string(node));
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+bool Json::get(const char* path, const char* key, std::string* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_value_node(__jsonNode, path, key);
+       IF_FAIL_RETURN(node, false);
+
+       GType vtype = json_node_get_value_type(node);
+       IF_FAIL_RETURN(vtype == G_TYPE_STRING, false);
+
+       const char *str_val = json_node_get_string(node);
+       IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed");
+
+       *val = str_val;
+       return true;
+}
+
+bool Json::get(const char* path, const char* key, GVariant **val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter");
+
+       bool ret;
+       Json gvar_json;
+       ret = get(path, key, &gvar_json);
+       IF_FAIL_RETURN(ret, false);
+
+       std::string gvar_types;
+       ret = gvar_json.get(NULL, GVAR_TYPES, &gvar_types);
+       IF_FAIL_RETURN(ret, false);
+
+       Json gvar_values;
+       ret = gvar_json.get(NULL, GVAR_VALUES, &gvar_values);
+       IF_FAIL_RETURN(ret, false);
+
+       GError *gerr = NULL;
+       *val = json_gvariant_deserialize(gvar_values.__jsonNode, gvar_types.c_str(), &gerr);
+       HANDLE_GERROR(gerr);
+       IF_FAIL_RETURN(*val, false);
+
+       return true;
+}
+
+static JsonArray* __search_array(JsonNode* jnode, const char* path, const char* key, bool force)
+{
+       JsonNode *node = NULL;
+       JsonArray *arr = NULL;
+       JsonObject *jobj = NULL;
+
+       jobj = __traverse(jnode, path, force);
+       IF_FAIL_RETURN(jobj, NULL);
+
+       if (!json_object_has_member(jobj, key)) {
+               if (force) {
+                       arr = json_array_new();
+                       IF_FAIL_RETURN_TAG(arr, NULL, _E, "Memory allocation failed");
+                       json_object_set_array_member(jobj, key, arr);
+               } else {
+                       return NULL;
+               }
+       }
+       node = json_object_get_member(jobj, key);
+       IF_FAIL_RETURN_TAG(node && json_node_get_node_type(node) == JSON_NODE_ARRAY,
+                       NULL, _W, "Type mismatched: %s", key);
+
+       return json_node_get_array(node);
+}
+
+int Json::arrayGetSize(const char* path, const char* key)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, -1, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, -1, _E, "Invalid parameter");
+
+       JsonArray *jarr = __search_array(__jsonNode, path, key, false);
+       IF_FAIL_RETURN_TAG(jarr, -1, _D, "Mismatched data type");
+
+       return json_array_get_length(jarr);
+}
+
+bool Json::arrayAppend(const char* path, const char* key, Json& val) {
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter");
+
+       JsonArray *arr = __search_array(__jsonNode, path, key, true);
+       IF_FAIL_RETURN(arr, false);
+
+       json_array_add_element(arr, val.__jsonNode);
+       val.__jsonNode = NULL;
+       val = Json();
+
+       return true;
+}
+
+bool Json::arrayAppend(const char* path, const char* key, int val)
+{
+       return arrayAppend(path, key, static_cast<int64_t>(val));
+}
+
+bool Json::arrayAppend(const char* path, const char* key, int64_t val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonArray *arr = __search_array(__jsonNode, path, key, true);
+       IF_FAIL_RETURN(arr, false);
+
+       json_array_add_int_element(arr, val);
+       return true;
+}
+
+bool Json::arrayAppend(const char* path, const char* key, double val, int prec)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonArray *arr = __search_array(__jsonNode, path, key, true);
+       IF_FAIL_RETURN(arr, false);
+
+       //NOTE: Json-glib causes a precision issue while handling double values
+       json_array_add_string_element(arr, __double_to_string(val, prec).c_str());
+       return true;
+}
+
+bool Json::arrayAppend(const char* path, const char* key, std::string val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter");
+
+       JsonArray *arr = __search_array(__jsonNode, path, key, true);
+       IF_FAIL_RETURN(arr, false);
+
+       json_array_add_string_element(arr, val.c_str());
+       return true;
+}
+
+static JsonNode* __search_array_elem(JsonNode* jnode, const char* path, const char* key, int index)
+{
+       JsonArray *jarr = __search_array(jnode, path, key, false);
+       IF_FAIL_RETURN_TAG(jarr, NULL, _W, "Mismatched data type");
+
+       int size = json_array_get_length(jarr);
+       IF_FAIL_RETURN(size > index, NULL);
+
+       JsonNode *node = json_array_get_element(jarr, index);
+       IF_FAIL_RETURN_TAG(node, NULL, _E, "Failed to get an array element");
+
+       return node;
+}
+
+bool Json::arraySetAt(const char* path, const char* key, int index, Json& val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(val.__jsonNode && key && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN_TAG(node, false, _W, "Out of range");
+
+       JsonObject *obj = json_node_get_object(val.__jsonNode);
+       IF_FAIL_RETURN_TAG(obj, false, _E, "Getting object failed");
+
+       json_node_set_object(node, obj);
+       json_node_free(val.__jsonNode);
+       val.__jsonNode = NULL;
+       val = Json();
+
+       return true;
+}
+
+bool Json::arraySetAt(const char* path, const char* key, int index, int val)
+{
+       return arraySetAt(path, key, index, static_cast<int64_t>(val));
+}
+
+bool Json::arraySetAt(const char* path, const char* key, int index, int64_t val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN_TAG(node, false, _W, "Out of range");
+       IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index);
+
+       json_node_set_int(node, val);
+       return true;
+}
+
+bool Json::arraySetAt(const char* path, const char* key, int index, double val, int prec)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN_TAG(node, false, _W, "Out of range");
+       IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index);
+
+       json_node_set_string(node, __double_to_string(val, prec).c_str());
+       return true;
+}
+
+bool Json::arraySetAt(const char* path, const char* key, int index, std::string val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN_TAG(node, false, _W, "Out of range");
+       IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index);
+
+       json_node_set_string(node, val.c_str());
+       return true;
+}
+
+bool Json::getArrayElem(const char* path, const char* key, int index, Json* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN(node, false);
+
+       JsonNode *node_copy = json_node_copy(node);
+       IF_FAIL_RETURN_TAG(node_copy, false, _E, "Memory allocation failed");
+
+       if (val->__jsonNode) {
+               json_node_free(val->__jsonNode);
+       }
+       val->__jsonNode = node_copy;
+
+       return true;
+}
+
+bool Json::getArrayElem(const char* path, const char* key, int index, int* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter");
+
+       int64_t v;
+       if (getArrayElem(path, key, index, &v)) {
+               *val = v;
+               return true;
+       }
+
+       return false;
+}
+
+bool Json::getArrayElem(const char* path, const char* key, int index, int64_t* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN(node, false);
+
+       JsonNodeType ntype = json_node_get_node_type(node);
+       IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key);
+
+       GType vtype = json_node_get_value_type(node);
+       if (vtype == G_TYPE_INT64) {
+               *val = json_node_get_int(node);
+       } else if (vtype == G_TYPE_STRING) {
+               *val = static_cast<int64_t>(__string_to_double(json_node_get_string(node)));
+       } else {
+               _E("Type mismatched: %s", key);
+               return false;
+       }
+
+       return true;
+}
+
+bool Json::getArrayElem(const char* path, const char* key, int index, double* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN(node, false);
+
+       JsonNodeType ntype = json_node_get_node_type(node);
+       IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key);
+
+       GType vtype = json_node_get_value_type(node);
+       if (vtype == G_TYPE_DOUBLE) {
+               *val = json_node_get_double(node);
+       } else if (vtype == G_TYPE_INT64) {
+               *val = json_node_get_int(node);
+       } else if (vtype == G_TYPE_STRING) {
+               //NOTE: Json-glib causes a precision issue while handling double values
+               *val = __string_to_double(json_node_get_string(node));
+       } else {
+               _E("Type mismatched: %s", key);
+               return false;
+       }
+
+       return true;
+}
+
+bool Json::getArrayElem(const char* path, const char* key, int index, std::string* val)
+{
+       IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized");
+       IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter");
+
+       JsonNode *node = __search_array_elem(__jsonNode, path, key, index);
+       IF_FAIL_RETURN(node, false);
+
+       JsonNodeType ntype = json_node_get_node_type(node);
+       IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key);
+
+       GType vtype = json_node_get_value_type(node);
+       IF_FAIL_RETURN_TAG(vtype == G_TYPE_STRING, false, _E, "Type mismatched: %s", key);
+
+       const char *str_val = json_node_get_string(node);
+       IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed");
+
+       *val = str_val;
+       return true;
+}
+
+bool Json::getMemberList(json_node_t* node, std::list<std::string>& list)
+{
+       IF_FAIL_RETURN(node, false);
+       list.clear();
+
+       JsonObject *jobj = json_node_get_object(node);
+       IF_FAIL_RETURN_TAG(jobj, false, _E, "Getting Json object failed");
+
+       GList *members = json_object_get_members(jobj);
+       IF_FAIL_RETURN(members, true);
+
+       for (GList *it = g_list_first(members); it; it = g_list_next(it)) {
+               const char *key = static_cast<const char*>(it->data);
+               if (!key) {
+                       list.clear();
+                       g_list_free(members);
+                       _E("Member list extraction failed");
+                       return false;
+               }
+
+               list.push_back(key);
+       }
+
+       g_list_free(members);
+       return true;
+}
+
+bool Json::getKeys(std::list<std::string>* list)
+{
+       IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter");
+       return getMemberList(__jsonNode, *list);
+}
+
+bool Json::nodeEquals(json_node_t* lhs, json_node_t* rhs)
+{
+       IF_FAIL_RETURN(lhs && rhs, false);
+
+       JsonNodeType ltype = json_node_get_node_type(lhs);
+       JsonNodeType rtype = json_node_get_node_type(rhs);
+       IF_FAIL_RETURN(ltype == rtype, false);
+
+       switch (ltype) {
+               case JSON_NODE_VALUE:
+                       IF_FAIL_RETURN(valueEquals(lhs, rhs), false);
+                       break;
+               case JSON_NODE_OBJECT:
+                       IF_FAIL_RETURN(objectEquals(lhs, rhs), false);
+                       break;
+               case JSON_NODE_ARRAY:
+                       IF_FAIL_RETURN(arrayEquals(lhs, rhs), false);
+                       break;
+               default:
+                       _W("Unsupported type");
+                       return false;
+       }
+
+       return true;
+}
+
+bool Json::valueEquals(json_node_t* lhs, json_node_t* rhs)
+{
+       GType ltype = json_node_get_value_type(lhs);
+       GType rtype = json_node_get_value_type(rhs);
+       IF_FAIL_RETURN(ltype == rtype, false);
+
+       switch (ltype) {
+               case G_TYPE_INT64:
+                       return json_node_get_int(lhs) == json_node_get_int(rhs);
+               case G_TYPE_DOUBLE:
+                       return json_node_get_double(lhs) == json_node_get_double(rhs);
+               case G_TYPE_STRING:
+                       return STR_EQ(json_node_get_string(lhs), json_node_get_string(rhs));
+               default:
+                       _W("Unsupported type");
+                       return false;
+       }
+}
+
+bool Json::objectEquals(json_node_t* lhs, json_node_t* rhs)
+{
+       std::list<std::string> lm, rm;
+       IF_FAIL_RETURN(getMemberList(lhs, lm), false);
+       IF_FAIL_RETURN(getMemberList(rhs, rm), false);
+       IF_FAIL_RETURN(lm.size() == rm.size(), false);
+
+       lm.sort();
+       rm.sort();
+
+       std::list<std::string>::iterator lit, rit;
+       lit = lm.begin();
+       rit = rm.begin();
+
+       while (lit != lm.end()) {
+               IF_FAIL_RETURN(*lit == *rit, false);
+
+               json_node_t *lhs_child = json_object_get_member(json_node_get_object(lhs), (*lit).c_str());
+               json_node_t *rhs_child = json_object_get_member(json_node_get_object(rhs), (*rit).c_str());
+               IF_FAIL_RETURN(nodeEquals(lhs_child, rhs_child), false);
+
+               ++lit;
+               ++rit;
+       }
+
+       return true;
+}
+
+bool Json::arrayEquals(json_node_t* lhs, json_node_t* rhs)
+{
+       JsonArray *larr = json_node_get_array(lhs);
+       JsonArray *rarr = json_node_get_array(rhs);
+
+       int size = json_array_get_length(larr);
+       IF_FAIL_RETURN(size == static_cast<int>(json_array_get_length(rarr)), false);
+
+       for (int i=0; i < size; ++i) {
+               json_node_t *lhs_child = json_array_get_element(larr, i);
+               json_node_t *rhs_child = json_array_get_element(rarr, i);
+               IF_FAIL_RETURN(nodeEquals(lhs_child, rhs_child), false);
+       }
+
+       return true;
+}
+
+std::string Json::getStr(const char *key)
+{
+       if(!key)
+               return "";
+       std::string str_temp;
+       get(NULL, key, &str_temp);
+       return str_temp;
+}
+
+Json *Json::getJson(const char* key)
+{
+       if(!key)
+               return NULL;
+       Json *j = new Json();
+       if(get(NULL, key, j))
+               return j;
+       delete j;
+       return NULL;
+}
diff --git a/src/common/Json.h b/src/common/Json.h
new file mode 100644 (file)
index 0000000..ca9d244
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __RRS_JSON_H__
+#define __RRS_JSON_H__
+
+#include <sys/types.h>
+#include <glib.h>
+#include <string>
+#include <list>
+
+#define _J(cmt, jobj) \
+do { \
+       _SD("%s: %s", (cmt), jobj.str().c_str()); \
+} while (0)
+
+#define EMPTY_JSON_OBJECT      "{}"
+#define DEFAULT_PRECISION      3
+
+
+class Json {
+public:
+       Json();
+       Json(const char* s);
+       Json(const std::string& s);
+
+       /* This Json(const Json& j) only copies the reference to the underlying Json node.
+       * Therefore, changes applied to a Json object affect the other.
+       * If you need to create a 'real' copy of a Json, which can be manipulated separately,
+       * utilize the str() function, e.g., ctx::Json copy(original.str());
+        */
+       Json(const Json& j);
+
+       ~Json();
+
+       Json& operator=(const char* s);
+       Json& operator=(const std::string& s);
+
+       /* This operator=(const Json& j) only copies the reference to the underlying Json node.
+       * Therefore, changes applied to a Json object affect the other.
+       * If you need to create a 'real' copy of a Json, which can be manipulated separately,
+       * utilize the str() function, e.g., ctx::Json copy = original.str();
+        */
+       Json& operator=(const Json& j);
+
+       bool operator==(const Json& rhs);
+       bool operator!=(const Json& rhs);
+
+       void load(const char *file);
+
+       char* dupCStr();
+       std::string str();
+
+       bool getKeys(std::list<std::string>* list);
+
+       bool set(const char* path, const char* key, Json& val);
+       bool set(const char* path, const char* key, int val);
+       bool set(const char* path, const char* key, int64_t val);
+       bool set(const char* path, const char* key, double val, int prec = DEFAULT_PRECISION);
+       bool set(const char* path, const char* key, std::string val);
+       bool set(const char* path, const char* key, GVariant *val);
+
+       bool get(const char* path, const char* key, Json* val);
+       bool get(const char* path, const char* key, int* val);
+       bool get(const char* path, const char* key, int64_t* val);
+       bool get(const char* path, const char* key, double* val);
+       bool get(const char* path, const char* key, std::string* val);
+       bool get(const char* path, const char* key, GVariant **val);
+
+       int arrayGetSize(const char* path, const char* key);
+
+       bool arrayAppend(const char* path, const char* key, Json& val);
+       bool arrayAppend(const char* path, const char* key, int val);
+       bool arrayAppend(const char* path, const char* key, int64_t val);
+       bool arrayAppend(const char* path, const char* key, double val, int prec = DEFAULT_PRECISION);
+       bool arrayAppend(const char* path, const char* key, std::string val);
+
+       bool arraySetAt(const char* path, const char* key, int index, Json& val);
+       bool arraySetAt(const char* path, const char* key, int index, int val);
+       bool arraySetAt(const char* path, const char* key, int index, int64_t val);
+       bool arraySetAt(const char* path, const char* key, int index, double val, int prec = DEFAULT_PRECISION);
+       bool arraySetAt(const char* path, const char* key, int index, std::string val);
+
+       bool getArrayElem(const char* path, const char* key, int index, Json* val);
+       bool getArrayElem(const char* path, const char* key, int index, int* val);
+       bool getArrayElem(const char* path, const char* key, int index, int64_t* val);
+       bool getArrayElem(const char* path, const char* key, int index, double* val);
+       bool getArrayElem(const char* path, const char* key, int index, std::string* val);
+
+       std::string getStr(const char* key);
+       Json *getJson(const char* key);
+private:
+       typedef struct _JsonNode json_node_t;
+       json_node_t *__jsonNode;
+
+       void parse(const char* s);
+       void release();
+
+       /* For Json vs Json comparison */
+       bool getMemberList(json_node_t* node, std::list<std::string>& list);
+       bool nodeEquals(json_node_t* lhs, json_node_t* rhs);
+       bool valueEquals(json_node_t* lhs, json_node_t* rhs);
+       bool objectEquals(json_node_t* lhs, json_node_t* rhs);
+       bool arrayEquals(json_node_t* lhs, json_node_t* rhs);
+};
+
+
+#endif // __RRS_JSON_H__
+
diff --git a/src/common/Mutex.cpp b/src/common/Mutex.cpp
new file mode 100755 (executable)
index 0000000..268f803
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "Mutex.h"
+#include "common.h"
+
+Mutex::Mutex()
+{
+       pthread_mutexattr_t mutex_attr;
+       pthread_mutexattr_init(&mutex_attr);
+       pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
+       pthread_mutex_init(&__mutex, &mutex_attr);
+       pthread_mutexattr_destroy(&mutex_attr);
+}
+
+Mutex::~Mutex()
+{
+       pthread_mutex_destroy(&__mutex);
+}
+
+void Mutex::lock()
+{
+#ifdef _LOCK_DEBUG
+       BaseLock::lock(LOCK_TYPE_MUTEX, "mutex", __MODULE__, __func__, __LINE__);
+#else
+       BaseLock::lock(LOCK_TYPE_MUTEX);
+#endif
+}
+
+void Mutex::lock(const char* expr, const char *module, const char *func, int line)
+{
+       BaseLock::lock(LOCK_TYPE_MUTEX, expr, module, func, line);
+}
+
+int Mutex::lockImpl(void)
+{
+       return pthread_mutex_lock(&__mutex);
+}
+
+int Mutex::tryLockImpl(void)
+{
+       return pthread_mutex_trylock(&__mutex);
+}
+
+int Mutex::unlockImpl()
+{
+       return pthread_mutex_unlock(&__mutex);
+}
diff --git a/src/common/Mutex.h b/src/common/Mutex.h
new file mode 100755 (executable)
index 0000000..04f0154
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * IOT_Broker_Service
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if !defined(_RRS_MUTEX_H_)
+#define _RRS_MUTEX_H_
+
+#include "BaseLock.h"
+
+class Mutex : public BaseLock {
+public:
+       Mutex();
+       virtual ~Mutex();
+
+       void lock(void);
+       void lock(const char* expr, const char *module, const char *func, int line);
+
+protected:
+       int lockImpl(void);
+       int tryLockImpl(void);
+       int unlockImpl();
+private:
+       pthread_mutex_t __mutex;
+};
+
+#endif
diff --git a/src/common/common.cpp b/src/common/common.cpp
new file mode 100755 (executable)
index 0000000..fc5850d
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <dlog.h>
+#include "common.h"
+
+#ifndef EXTAPI
+#define EXTAPI __attribute__((visibility("default")))
+#endif
+
+#define IOT_SERVER_MSG_LOG_FILE                "/var/log/messages"
+#define FILE_LENGTH 255
+
+static int iot_debug_file_fd;
+static char iot_debug_file_buf[FILE_LENGTH];
+
+EXTAPI void iot_log(int type , int priority , const char *tag , const char *fmt , ...)
+{
+       va_list ap;
+       ssize_t len;
+       ssize_t total_sent_size = 0;
+       va_start(ap, fmt);
+
+       switch (type) {
+       case IOT_LOG_PRINT_FILE:
+               iot_debug_file_fd = open(IOT_SERVER_MSG_LOG_FILE, O_WRONLY|O_CREAT|O_APPEND, 0644);
+               if (iot_debug_file_fd != -1) {
+                       vsnprintf(iot_debug_file_buf, 255, fmt , ap);
+                       do {
+                               len = write(iot_debug_file_fd, iot_debug_file_buf, strlen(iot_debug_file_buf));
+                               if (len >= 0) {
+                                       total_sent_size += len;
+                               }
+                       } while (total_sent_size < FILE_LENGTH);
+
+                       close(iot_debug_file_fd);
+               }
+               break;
+
+       case IOT_LOG_SYSLOG:
+               int syslog_prio;
+               switch (priority) {
+               case IOT_LOG_ERR:
+                       syslog_prio = LOG_ERR|LOG_DAEMON;
+                       break;
+
+               case IOT_LOG_WARN:
+                       syslog_prio = LOG_WARNING|LOG_DAEMON;
+                       break;
+
+               case IOT_LOG_DBG:
+                       syslog_prio = LOG_DEBUG|LOG_DAEMON;
+                       break;
+
+               case IOT_LOG_INFO:
+                       syslog_prio = LOG_INFO|LOG_DAEMON;
+                       break;
+
+               default:
+                       syslog_prio = priority;
+                       break;
+               }
+
+               vsyslog(syslog_prio, fmt, ap);
+               break;
+
+       case IOT_LOG_DLOG:
+               if (tag) {
+                       switch (priority) {
+                       case IOT_LOG_ERR:
+                               SLOG_VA(LOG_ERROR, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap);
+                               break;
+
+                       case IOT_LOG_WARN:
+                               SLOG_VA(LOG_WARN, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap);
+                               break;
+
+                       case IOT_LOG_DBG:
+                               SLOG_VA(LOG_DEBUG, tag ? tag : "NULL", fmt ? fmt : "NULL" , ap);
+                               break;
+
+                       case IOT_LOG_INFO:
+                               SLOG_VA(LOG_INFO, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap);
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+
+       va_end(ap);
+}
+
+bool get_proc_name(pid_t pid, char *process_name)
+{
+       FILE *fp;
+       char buf[NAME_MAX];
+       char filename[PATH_MAX];
+
+       sprintf(filename, "/proc/%d/stat", pid);
+       fp = fopen(filename, "r");
+
+       if (fp == NULL)
+               return false;
+
+       if (fscanf(fp, "%*s (%[^)]", buf) < 1) {
+               fclose(fp);
+               return false;
+       }
+
+       strncpy(process_name, buf, NAME_MAX-1);
+       process_name[NAME_MAX-1] = '\0';
+       fclose(fp);
+
+       return true;
+}
+
+const char* get_client_name(void)
+{
+       const int pid_string_size = 10;
+       static pid_t pid = -1;
+       static char client_name[NAME_MAX + pid_string_size];
+       char proc_name[NAME_MAX];
+
+       if (pid == -1) {
+               pid = getpid();
+               get_proc_name(pid, proc_name);
+               snprintf(client_name, sizeof(client_name), "%s(%d)", proc_name, pid);
+       }
+
+       return client_name;
+}
diff --git a/src/common/common.h b/src/common/common.h
new file mode 100755 (executable)
index 0000000..1147636
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * IOT_Broker_Service
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if !defined(_COMMON_H_)
+#define _COMMON_H_
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif /* !__cplusplus */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#define MAX_RRS_HANDLE 1000
+
+/**
+ * @brief URI prefix for discovery resource
+ * @since_tizen 3.0
+ */
+#define DISCOVERY_RESOURCE_URI_PREFIX "/rrsdiscovery"
+
+/**
+ * @brief Name of discovery resource
+ * @since_tizen 3.0
+ */
+
+#define DISCOVERY_RESOURCE_NAME "x.org.tizen.rrsdiscovery"
+
+/**
+ * @brief URI prefix for accelerometer sensor
+ * @since_tizen 3.0
+ */
+#define ACCELEROMETER_RESOURCE_URI_PREFIX "/accelerometer"
+
+/**
+ * @brief Type of accelerometer sensor resource
+ * @since_tizen 3.0
+ */
+#define ACCELEROMETER_RESOURCE_NAME "x.org.tizen.accelerometer"
+
+/**
+ * @brief URI prefix for proximity sensor
+ * @since_tizen 3.0
+ */
+#define PROXIMITY_RESOURCE_URI_PREFIX "/proximity"
+
+/**
+ * @brief Type of proximity sensor resource
+ * @since_tizen 3.0
+ */
+#define PROXIMITY_RESOURCE_NAME "x.org.tizen.proximity"
+
+
+#if !defined(PATH_MAX)
+#define PATH_MAX 256
+#endif
+
+#if !defined(NAME_MAX)
+#define NAME_MAX 256
+#endif
+
+enum IotLogType {
+       IOT_LOG_PRINT_FILE              = 1,
+       IOT_LOG_SYSLOG                  = 2,
+       IOT_LOG_DLOG                    = 3,
+};
+
+enum IotPriorityType {
+       IOT_LOG_ERR                     = 1,
+       IOT_LOG_DBG                     = 2,
+       IOT_LOG_INFO                    = 3,
+       IOT_LOG_WARN                    = 4,
+};
+
+void iot_log(int type , int priority , const char *tag , const char *fmt , ...);
+
+#define MICROSECONDS(tv)        ((tv.tv_sec * 1000000ll) + tv.tv_usec)
+
+#ifndef __MODULE__
+#include <string.h>
+#define __MODULE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#endif
+
+//for new log system - dlog
+#ifdef LOG_TAG
+       #undef LOG_TAG
+#endif
+#define LOG_TAG        "REMOTE_RESOURCE_SERVICE"
+
+#if defined(_DEBUG) || defined(USE_FILE_DEBUG)
+
+#define DbgPrint(fmt, arg...)   do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , " [IOT_MSG_PRT][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+
+#endif
+
+#if defined(USE_SYSLOG_DEBUG)
+
+#define ERR(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define WARN(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define INFO(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define DBG(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+
+#define _E(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _W(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _I(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _D(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _T(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+
+
+#elif defined(_DEBUG) || defined(USE_DLOG_DEBUG)
+
+#define ERR(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define WARN(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define INFO(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define DBG(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+
+#define _E(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _W(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _I(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _D(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _T(fmt, arg...) do { iot_log(IOT_LOG_SYSLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+
+#elif defined(USE_FILE_DEBUG)
+
+#define ERR(fmt, arg...)       do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG, "[IOT_MSG_ERR][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define WARN(fmt, arg...)      do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG, "[IOT_MSG_WARN][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define DBG(fmt, arg...)       do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG, "[IOT_MSG_DBG][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define INFO(fmt, arg...)      do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG, "[IOT_MSG_INFO][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+
+#define _E(fmt, arg...)        do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , "[IOT_MSG_ERR][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define _W(fmt, arg...)        do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , "[IOT_MSG_WARN][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define _I(fmt, arg...)        do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , "[IOT_MSG_INFO][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define _D(fmt, arg...)        do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , "[IOT_MSG_DBG][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+#define _T(fmt, arg...)        do { iot_log(IOT_LOG_PRINT_FILE, 0, LOG_TAG , "[IOT_MSG_TEMP][%s:%d] " fmt"\n", __MODULE__, __LINE__, ##arg); } while (0)
+
+#elif defined(USE_DLOG_LOG)
+
+#define ERR(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define WARN(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define INFO(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+
+#define DBG(...) do {} while (0)
+#define DbgPrint(...) do {} while (0)
+
+
+#define _E(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _W(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _I(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _D(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _T(...)
+
+#else
+#define ERR(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define WARN(...) do {} while (0)
+#define DbgPrint(...) do {} while (0)
+#define DBG(...) do {} while (0)
+#define INFO(...) do {} while (0)
+
+#define _E(fmt, arg...) do { iot_log(IOT_LOG_DLOG, IOT_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while (0)
+#define _W(...) do {} while (0)
+#define _I(...) do {} while (0)
+#define _D(...) do {} while (0)
+#define _T(...) do {} while (0)
+
+#endif
+
+
+#if defined(_DEBUG)
+#  define WARN_IF(expr, fmt, arg...) do { \
+               if(expr) { \
+                       DBG("(%s) -> " fmt, #expr, ##arg); \
+               } \
+       } while (0)
+#  define RET_IF(expr) do { \
+               if(expr) { \
+                       DBG("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return; \
+               } \
+       } while (0)
+#  define RETV_IF(expr, val) do { \
+               if(expr) { \
+                       DBG("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return (val); \
+               } \
+       } while (0)
+#  define RETM_IF(expr, fmt, arg...) do { \
+               if(expr) { \
+                       ERR(fmt, ##arg); \
+                       DBG("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return; \
+               } \
+       } while (0)
+#  define RETVM_IF(expr, val, fmt, arg...) do { \
+               if(expr) { \
+                       ERR(fmt, ##arg); \
+                       DBG("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return (val); \
+               } \
+       } while (0)
+
+#else
+#  define WARN_IF(expr, fmt, arg...) do { \
+               if(expr) { \
+                       ERR(fmt, ##arg); \
+               } \
+       } while (0)
+#  define RET_IF(expr) do { \
+               if(expr) { \
+                       return; \
+               } \
+       } while (0)
+#  define RETV_IF(expr, val) do { \
+               if(expr) { \
+                       return (val); \
+               } \
+       } while (0)
+#  define RETM_IF(expr, fmt, arg...) do { \
+               if(expr) { \
+                       ERR(fmt, ##arg); \
+                       return; \
+               } \
+       } while (0)
+#  define RETVM_IF(expr, val, fmt, arg...) do { \
+               if(expr) { \
+                       ERR(fmt, ##arg); \
+                       return (val); \
+               } \
+       } while (0)
+
+#endif
+
+const char* get_client_name(void);
+bool get_proc_name(pid_t pid, char *process_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/common/rrs-svr-db.dat b/src/common/rrs-svr-db.dat
new file mode 100644 (file)
index 0000000..80088b2
Binary files /dev/null and b/src/common/rrs-svr-db.dat differ
diff --git a/src/common/rrs.cpp b/src/common/rrs.cpp
new file mode 100644 (file)
index 0000000..8b55a2c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 <glib.h>
+#include "rrs.h"
+#include "Mutex.h"
+#include "common.h"
+#include "tzplatform_config.h"
+
+extern bool __has_iot_privilege();
+
+static bool handle_array[MAX_RRS_HANDLE] = {false};
+static Mutex m_mutex;
+
+#define RRS_SECURITY_FILEPATH tzplatform_mkpath(TZ_USER_SHARE, "rrs/rrs-svr-db.dat")
+
+EXPORT_API int rrs_create(rrs_h *rrs)
+{
+       int ret;
+       int value = 1;
+
+       /* Check if parameters are valid */
+       if (!rrs)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       {
+               AUTOLOCK(m_mutex);
+               while (handle_array[value] == true)
+                       value++;
+
+               *rrs = value;
+               handle_array[value] = true;
+       }
+
+       if (*rrs > MAX_RRS_HANDLE) {
+               ERR("Maximum limit for RRS handles reached");
+               return RRS_ERROR_SERVICE_NOT_AVAILABLE;
+       }
+
+       INFO("Path: %s", RRS_SECURITY_FILEPATH);
+
+       /* connect iotcon */
+       ret = iotcon_initialize(RRS_SECURITY_FILEPATH);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_initialize() Fail(%d)", ret);
+               return RRS_ERROR_SERVICE_NOT_AVAILABLE;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_destroy(const rrs_h rrs)
+{
+       /* Check if RRS handle is valid */
+       if (rrs < 1 || rrs > MAX_RRS_HANDLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if privileges enough */
+       if (!__has_iot_privilege())
+               return RRS_ERROR_PERMISSION_DENIED;
+
+       {
+               AUTOLOCK(m_mutex);
+               handle_array[rrs] = false;
+       }
+
+       /* disconnect iotcon */
+       iotcon_deinitialize();
+
+       return RRS_ERROR_NONE;
+}
diff --git a/src/common/rrs_common.cpp b/src/common/rrs_common.cpp
new file mode 100644 (file)
index 0000000..efef886
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 <glib.h>
+#include <string>
+#include "rrs.h"
+#include <cynara-client.h>
+#include <cynara-error.h>
+
+#define SMACK_LABEL_LEN 255
+static const char *RRS_PRIVILEGE_HEALTH_INFO = "http://tizen.org/privilege/healthinfo";
+
+bool __has_iot_privilege()
+{
+       static int has_health_info_permission = -1;
+
+       if (has_health_info_permission == -1) {
+               int ret;
+               char smack_label[SMACK_LABEL_LEN + 1] = {0};
+               char uid[10];
+               FILE *fd;
+               cynara *cynara_h;
+
+               ret = cynara_initialize(&cynara_h, NULL);
+               if (CYNARA_API_SUCCESS != ret) {
+                        ERR("cynara_initialize() Fail(%d)", ret);
+                        return false;
+               }
+
+               fd = fopen("/proc/self/attr/current", "r");
+               if (NULL == fd) {
+                        ERR("fopen() Fail(%d)", errno);
+                        return false;
+               }
+
+               ret = fread(smack_label, sizeof(smack_label), 1, fd);
+               fclose(fd);
+               if (ret < 0) {
+                        ERR("fread() Fail(%d)", ret);
+                        return 0;
+               }
+
+               snprintf(uid, sizeof(uid), "%d", getuid());
+
+               ret = cynara_check(cynara_h, smack_label, "", uid, RRS_PRIVILEGE_HEALTH_INFO);
+               if (CYNARA_API_ACCESS_ALLOWED == ret)
+                       has_health_info_permission = 1;
+               else
+                       has_health_info_permission = 0;
+
+               cynara_finish(cynara_h);
+       }
+
+       if (has_health_info_permission != 1) {
+               ERR("Don't have http://tizen.org/privilege/healthinfo");
+               return false;
+       }
+
+       return true;
+}
+
+std::string _rrs_get_schema_system_folder()
+{
+       return "/usr/lib/rrs/schemas/";
+}
+
+void _rrs_get_discovery_schema_system_path(const rrs_resource_e resource_id, std::string &discovery_schema)
+{
+       static std::string base_path = _rrs_get_schema_system_folder();
+       switch(resource_id) {
+       case RRS_RESOURCE_DISCOVERY:
+               discovery_schema = base_path + "rrsdiscovery.json";
+               break;
+       default: /* TODO */
+               discovery_schema = "";
+       }
+}
+
+void _rrs_get_schema_system_path(const rrs_resource_e resource_id, std::string &service_schema, std::string &resource_schema)
+{
+       static std::string base_path = _rrs_get_schema_system_folder();
+       switch(resource_id) {
+       case RRS_RESOURCE_ACCELEROMETER:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "accelerometer.json";
+               break;
+       case RRS_RESOURCE_PROXIMITY:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "proximity.json";
+               break;
+       case RRS_RESOURCE_AUTO_ROTATION:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "autorotation.json";
+               break;
+       case RRS_RESOURCE_HRM:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "hrm.json";
+               break;
+       case RRS_RESOURCE_HRM_LED_GREEN:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "hrmledgreen.json";
+               break;
+       case RRS_RESOURCE_HRM_LED_RED:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "hrmledred.json";
+               break;
+       case RRS_RESOURCE_HRM_LED_IR:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "hrmledir.json";
+               break;
+       case RRS_RESOURCE_GYROSCOPE:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "gyroscope.json";
+               break;
+       case RRS_RESOURCE_MAGNETOMETER:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "magnetometer.json";
+               break;
+       case RRS_RESOURCE_LIGHT:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "light.json";
+               break;
+       case RRS_RESOURCE_PRESSURE:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "pressure.json";
+               break;
+       case RRS_RESOURCE_TEMPERATURE:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "temperature.json";
+               break;
+       case RRS_RESOURCE_HUMIDITY:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "humidity.json";
+               break;
+       case RRS_RESOURCE_UV:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "uv.json";
+               break;
+       case RRS_RESOURCE_ORIENTATION:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "orientation.json";
+               break;
+       case RRS_RESOURCE_GRAVITY:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "gravity.json";
+               break;
+       case RRS_RESOURCE_LINEAR_ACCELERATION:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "linearacceleration.json";
+               break;
+       case RRS_RESOURCE_ROTATION_VECTOR:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "rotationvector.json";
+               break;
+       case RRS_RESOURCE_GYROSCOPE_ROTATION_VECTOR:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "gyroscoperotationvector.json";
+               break;
+       case RRS_RESOURCE_GEOMAGNETIC_ROTATION_VECTOR:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "geomagneticrotationvector.json";
+               break;
+       case RRS_RESOURCE_UNCALIBRATED_GYROSCOPE:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "uncalibratedgyroscope.json";
+               break;
+       case RRS_RESOURCE_UNCALIBRATED_MAGNETOMETER:
+               service_schema = base_path + "sensorcontrol.json";
+               resource_schema = base_path + "uncalibratedmagnetometer.json";
+               break;
+       default:
+               service_schema = "";
+               resource_schema = "";
+       }
+}
+
+std::string _rrs_get_schema_custom_path(const char *schema_name)
+{
+       static std::string base_path = _rrs_get_schema_system_folder();
+       return base_path + schema_name;
+}
diff --git a/src/common/rrs_control_data.cpp b/src/common/rrs_control_data.cpp
new file mode 100644 (file)
index 0000000..2319972
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "rrs.h"
+#include <glib.h>
+#include <unordered_map>
+#include <memory>
+#include "schema.h"
+#include "Json.h"
+
+EXPORT_API int rrs_control_data_create(const rrs_resource_e type,
+                                     rrs_control_data_h *data)
+{
+       rrs_schema_h control_schema;
+       if (type != RRS_RESOURCE_DISCOVERY) {
+               rrs_schema_h event_schema;
+               if (rrs_schema_load(type, &control_schema, &event_schema) != RRS_ERROR_NONE) {
+                       ERR("rrs_schema_load() failed");
+                       return RRS_ERROR_INVALID_TYPE;
+               }
+
+               if (rrs_schema_destroy(event_schema)) {
+                       ERR("rrs_schema_destroy() Fail(%d)");
+                       return RRS_ERROR_INVALID_PARAMETER;
+               }
+       } else {
+               if (rrs_discovery_schema_load(type, &control_schema) != RRS_ERROR_NONE) {
+                       ERR("rrs_discovery_schema_load() failed");
+                       return RRS_ERROR_INVALID_TYPE;
+               }
+       }
+
+       if (rrs_schema_create_data(control_schema, data) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() Fail(%d)");
+               rrs_schema_destroy(control_schema);
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (rrs_schema_destroy(control_schema)) {
+               ERR("rrs_schema_destroy() Fail(%d)");
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_destroy(rrs_control_data_h data)
+{
+       /* Check if data handle is valid */
+       if (data)
+               rrs_data_destroy(data);
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_clone(const rrs_control_data_h origin, rrs_control_data_h *cloned)
+{
+       if (rrs_data_clone(origin, cloned) != RRS_ERROR_NONE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_set_bool(rrs_control_data_h data, const char *name, const bool value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_bool(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_control_data_set_int(rrs_control_data_h data, const char *name, const int value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_int(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_set_double(rrs_control_data_h data, const char *name, const double value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_double(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_set_string(rrs_control_data_h data, const char *name, const char *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_string(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_get_bool(rrs_control_data_h data, const char *name, bool *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_bool(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_get_int(rrs_control_data_h data, const char *name, int *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_int(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_get_double(rrs_control_data_h data, const char *name, double *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_double(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_control_data_get_string(rrs_control_data_h data, const char *name, char **value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_string(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
diff --git a/src/common/rrs_event_data.cpp b/src/common/rrs_event_data.cpp
new file mode 100644 (file)
index 0000000..b58f270
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 "rrs.h"
+#include <glib.h>
+#include <unordered_map>
+#include <memory>
+#include "schema.h"
+#include "Json.h"
+
+EXPORT_API int rrs_event_data_create(const rrs_resource_e type,
+                                     rrs_event_data_h *data)
+{
+       rrs_schema_h control_schema = NULL;
+       rrs_schema_h event_schema = NULL;
+
+       if (rrs_schema_load(type, &control_schema, &event_schema) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_load() failed");
+               return RRS_ERROR_INVALID_TYPE;
+       }
+
+       if (rrs_schema_create_data(event_schema, data) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() Fail(%d)");
+               rrs_schema_destroy(event_schema);
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (rrs_schema_destroy(control_schema)) {
+               ERR("rrs_schema_destroy() Fail(%d)");
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (rrs_schema_destroy(event_schema)) {
+               ERR("rrs_schema_destroy() Fail(%d)");
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_destroy(rrs_event_data_h data)
+{
+       /* Check if data handle is valid */
+       if (data)
+               rrs_data_destroy(data);
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_clone(const rrs_event_data_h origin, rrs_event_data_h *cloned)
+{
+       if (rrs_data_clone(origin, cloned) != RRS_ERROR_NONE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_set_bool(rrs_event_data_h data, const char *name, const bool value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_bool(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+EXPORT_API int rrs_event_data_set_int(rrs_event_data_h data, const char *name, const int value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_int(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_set_double(rrs_event_data_h data, const char *name, const double value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_double(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_set_string(rrs_event_data_h data, const char *name, const char *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_set_string(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_get_bool(rrs_event_data_h data, const char *name, bool *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_bool(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_get_int(rrs_event_data_h data, const char *name, int *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_int(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_get_double(rrs_event_data_h data, const char *name, double *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_double(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
+
+
+EXPORT_API int rrs_event_data_get_string(rrs_event_data_h data, const char *name, char **value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       if (rrs_data_get_string(data, name, value))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       return RRS_ERROR_NONE;
+}
diff --git a/src/common/schema.cpp b/src/common/schema.cpp
new file mode 100644 (file)
index 0000000..220d3e6
--- /dev/null
@@ -0,0 +1,1292 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd 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 <glib.h>
+#include <unordered_map>
+#include <memory>
+#include "rrs.h"
+#include "schema.h"
+#include "Json.h"
+
+extern bool __has_iot_privilege();
+
+extern void _rrs_get_schema_system_path(const rrs_resource_e resource_id, std::string &service_schema, std::string &resource_schema);
+extern void _rrs_get_discovery_schema_system_path(const rrs_resource_e resource_id, std::string &discovery_schema);
+extern std::string _rrs_get_schema_custom_path(const char *schema_name);
+static int _rrs_schema_clone(const rrs_schema_h origin, rrs_schema_h *cloned);
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct _rrs_schema_field_s {
+       RrsSchemaType type;
+       RrsSchemaAccess access;
+       bool required;
+       rrs_schema_h complex_schema;
+} rrs_schema_field_s;
+
+static rrs_schema_field_s *__rrs_schema_field_create()
+{
+       return g_new0(rrs_schema_field_s, 1);
+}
+
+static void __rrs_schema_field_destroy(gpointer data)
+{
+       rrs_schema_field_s *f = (rrs_schema_field_s *)data;
+       if(f && f->complex_schema)
+               rrs_schema_destroy(f->complex_schema);
+       g_free(data);
+}
+
+static rrs_schema_field_s *__rrs_schema_field_create_complete(
+                                             RrsSchemaType type,
+                                             RrsSchemaAccess access,
+                                             bool required,
+                                             rrs_schema_h complex_schema)
+{
+       rrs_schema_field_s *f = __rrs_schema_field_create();
+       f->type = type;
+       f->access = access;
+       f->required = required;
+       f->complex_schema = complex_schema;
+       return f;
+}
+
+static rrs_schema_field_s *__rrs_schema_field_clone(rrs_schema_field_s *origin)
+{
+       if (!origin)
+               return NULL;
+       rrs_schema_h complex_schema = NULL;
+       if(origin->complex_schema)
+               _rrs_schema_clone(origin->complex_schema, &complex_schema);
+       return __rrs_schema_field_create_complete(origin->type,
+                                                 origin->access,
+                                                 origin->required,
+                                                 complex_schema);
+}
+
+static GHashTable *__rrs_create_schema_field_table()
+{
+       return g_hash_table_new_full(g_str_hash,
+                                    g_str_equal,
+                                    g_free,
+                                    __rrs_schema_field_destroy);
+}
+
+static void __rrs_destroy_schema_field_table(GHashTable *t)
+{
+       g_hash_table_unref(t);
+}
+
+static void __rrs_clone_schema_field_table(GHashTable *origin,
+                                          GHashTable **cloned)
+{
+       if(!origin || !cloned)
+               return;
+
+       if(*cloned)
+               __rrs_destroy_schema_field_table(*cloned);
+       *cloned = __rrs_create_schema_field_table();
+
+       GHashTableIter iter;
+       gpointer key = NULL;
+       gpointer value = NULL;
+       g_hash_table_iter_init(&iter, origin);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (!value)
+                       continue;
+               g_hash_table_insert(*cloned, g_strdup((char*)key),
+                       __rrs_schema_field_clone((rrs_schema_field_s *)value));
+       }
+}
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct _rrs_value_item_s {
+       RrsSchemaType type;
+       void *item;
+} rrs_value_item_s;
+
+static rrs_value_item_s *__rrs_value_item_create(const RrsSchemaType type,
+                                                void *item);
+static void  __rrs_value_item_destroy(gpointer data);
+
+static void *__rrs_value_alloc(const RrsSchemaType type)
+{
+       switch (type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               return NULL;
+       case RRS_SCHEMA_TYPE_BOOL:
+               return g_slice_new0(bool);
+       case RRS_SCHEMA_TYPE_INT:
+               return g_slice_new0(int);
+       case RRS_SCHEMA_TYPE_DOUBLE:
+               return g_slice_new0(double);
+       case RRS_SCHEMA_TYPE_STR:
+               return g_slice_new0(char *);
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               return __rrs_value_item_create(type, NULL); /* TODO: add hierarchy */
+       default:
+               return NULL;
+       }
+}
+
+static void __rrs_value_free(const RrsSchemaType type, void *ptr)
+{
+       switch (type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               break;
+       case RRS_SCHEMA_TYPE_BOOL:
+               g_slice_free(bool, ptr);
+               break;
+       case RRS_SCHEMA_TYPE_INT:
+               g_slice_free(int, ptr);
+               break;
+       case RRS_SCHEMA_TYPE_DOUBLE:
+               g_slice_free(double, ptr);
+               break;
+       case RRS_SCHEMA_TYPE_STR:
+               g_slice_free(char *, ptr);
+               break;
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               __rrs_value_item_destroy(ptr);
+               break;
+       default:
+               break;
+       }
+}
+
+static rrs_value_item_s *__rrs_value_item_create(const RrsSchemaType type,
+                                                void *item)
+{
+       rrs_value_item_s *i = g_new0(rrs_value_item_s, 1);
+       i->type = type;
+       i->item = item;
+       return i;
+}
+
+static void  __rrs_value_item_destroy(gpointer data)
+{
+       rrs_value_item_s *i = (rrs_value_item_s *)data;
+       if (i && i->item) {
+               if(i->type == RRS_SCHEMA_TYPE_COMPLEX)
+                       __rrs_value_item_destroy(i->item);
+               else
+                       __rrs_value_free(i->type, i->item);
+       }
+       g_free(i);
+}
+
+static rrs_value_item_s *__rrs_value_item_clone(rrs_value_item_s *origin)
+{
+       if (!origin)
+               return NULL;
+
+       rrs_value_item_s *clone = __rrs_value_item_create(origin->type,
+                                       __rrs_value_alloc(origin->type));
+       switch(origin->type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               break;
+       case RRS_SCHEMA_TYPE_BOOL:
+               *((bool *)clone->item) = *((bool *)origin->item);
+               break;
+       case RRS_SCHEMA_TYPE_INT:
+               *((int *)clone->item) = *((int *)origin->item);
+               break;
+       case RRS_SCHEMA_TYPE_DOUBLE:
+               *((double *)clone->item) = *((double *)origin->item);
+               break;
+       case RRS_SCHEMA_TYPE_STR:
+               clone->item = g_strdup((char *)origin->item);
+               break;
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               /* TODO: support complex hierarchical type */
+               break;
+       default:
+               ERR("Undefined type while clonning");
+               break;
+       }
+       return clone;
+}
+
+static GHashTable *__rrs_create_value_table()
+{
+       return g_hash_table_new_full(g_str_hash,
+                                    g_str_equal,
+                                    g_free,
+                                    __rrs_value_item_destroy);
+}
+
+static void __rrs_destroy_value_table(GHashTable *t)
+{
+       g_hash_table_unref(t);
+}
+
+static bool __rrs_value_has_field(rrs_data_h data,
+                                 const char *field_name)
+{
+       GHashTable *t = (GHashTable *)data;
+       return g_hash_table_contains(t, field_name);
+}
+
+static rrs_value_item_s *__rrs_value_lookup_field(rrs_data_h data,
+                                                 const char *field_name)
+{
+       GHashTable *t = (GHashTable *)data;
+       return (rrs_value_item_s *)g_hash_table_lookup(t, field_name);
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+typedef struct _rrs_schema_s {
+       rrs_resource_e resource;
+       char *name;
+       char *title;
+       char *file;
+       GHashTable *fields;
+} rrs_schema_s;
+
+const gsize _RRS_SCHEMA_NAME_MAX_LENGTH = 128;
+const gsize _RRS_SCHEMA_TITLE_MAX_LENGTH = 128;
+const gsize _RRS_SCHEMA_FILE_MAX_LENGTH = 128;
+
+
+
+RrsSchemaType _rrs_schema_get_type(const std::string &t)
+{
+       if(t == "bool")
+               return RRS_SCHEMA_TYPE_BOOL;
+       if(t == "integer")
+               return RRS_SCHEMA_TYPE_INT;
+       if(t == "double")
+               return RRS_SCHEMA_TYPE_DOUBLE;
+       if(t == "string")
+               return RRS_SCHEMA_TYPE_STR;
+       if(t == "object")
+               return RRS_SCHEMA_TYPE_COMPLEX;
+
+       /* TODO: WARNING: unsupported type */
+       /*_E("Unknown schema field type");*/
+       return RRS_SCHEMA_TYPE_NONE;
+}
+
+RrsSchemaAccess _rrs_schema_get_access(const std::string &a)
+{
+       if(a == "R")
+               return RRS_SCHEMA_ACCESS_READ;
+       if(a == "W")
+               return RRS_SCHEMA_ACCESS_WRITE;
+       if(a == "RW")
+               return RRS_SCHEMA_ACCESS_READ_WRITE;
+
+       /* TODO: WARNING: unsupported access */
+       /*_E("Unknown schema field access");*/
+       return RRS_SCHEMA_ACCESS_NONE;
+}
+
+/*--------------------------------------------------------------------------=-*/
+
+static bool __rrs_schema_trace_foreach_field_cb(int index,
+                                            int total,
+                                            const char *name,
+                                            const RrsSchemaType type,
+                                            const RrsSchemaAccess access,
+                                            const bool required,
+                                            const rrs_schema_h schema,
+                                            void *user_data)
+{
+       std::string s_type;
+       switch(type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               s_type = "NONE";
+               break;
+       case RRS_SCHEMA_TYPE_BOOL:
+               s_type = "BOOL";
+               break;
+       case RRS_SCHEMA_TYPE_INT:
+               s_type = "INT";
+               break;
+       case RRS_SCHEMA_TYPE_DOUBLE:
+               s_type = "DOUBLE";
+               break;
+       case RRS_SCHEMA_TYPE_STR:
+               s_type = "STR";
+               break;
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               s_type = "COMPLEX";
+               break;
+       default:
+               s_type = "UNKNOWN";
+               break;
+       }
+
+       std::string s_access;
+       switch(access) {
+       case RRS_SCHEMA_ACCESS_NONE:
+               s_access = "NONE";
+               break;
+       case RRS_SCHEMA_ACCESS_READ:
+               s_access = "R";
+               break;
+       case RRS_SCHEMA_ACCESS_WRITE:
+               s_access = "W";
+               break;
+       case RRS_SCHEMA_ACCESS_READ_WRITE:
+               s_access = "RW";
+               break;
+       default:
+               s_access = "UNKNOWN";
+               break;
+       }
+
+       std::string s_required = (required) ? "required" : "not required";
+
+       _I("[%d/%d] %s:%s:%s:%s", index, total,
+          name, s_type.c_str(), s_access.c_str(), s_required.c_str());
+       return true;
+}
+
+void _dbg_trace_schema(const rrs_schema_h schema)
+{
+       _I("\n\nTracing schema %p [idx/total] name:type:access:required\n\n",
+          schema);
+       rrs_schema_foreach_field(schema,
+                                __rrs_schema_trace_foreach_field_cb,
+                                NULL);
+       _I("\n---------------------------------------\n\n");
+}
+
+static bool __rrs_data_trace_foreach_field_cb(int index,
+                                          int total,
+                                          const char *name,
+                                          const RrsSchemaType type,
+                                          const RrsSchemaAccess access,
+                                          const bool required,
+                                          void *value,
+                                          void *user_data)
+{
+       switch(type) {
+       case RRS_SCHEMA_TYPE_NONE:
+               _I("[%d/%d] %s:NONE:NONE", index, total, name);
+               break;
+       case RRS_SCHEMA_TYPE_BOOL: {
+               bool *b = (bool *)value;
+               std::string s = (*b) ? "true" : "false";
+               _I("[%d/%d] %s:BOOL:%s", index, total, name, s.c_str());
+               break;
+               }
+       case RRS_SCHEMA_TYPE_INT: {
+               int *i = (int *)value;
+               char *s = g_strdup_printf("%i", *i);
+               _I("[%d/%d] %s:INT:%s", index, total, name, s);
+               free(s);
+               break;
+               }
+       case RRS_SCHEMA_TYPE_DOUBLE: {
+               double *d = (double *)value;
+               char *s = g_strdup_printf("%f", *d);
+               _I("[%d/%d] %s:DOUBLE:%s", index, total, name, s);
+               free(s);
+               break;
+               }
+       case RRS_SCHEMA_TYPE_STR: {
+               char *s = (char *)value;
+               _I("[%d/%d] %s:STRING:%s", index, total, name, s);
+               break;
+               }
+       case RRS_SCHEMA_TYPE_COMPLEX:
+               _I("[%d/%d] %s:COMPLEX:%p", index, total, name, value);
+               break;
+       default:
+               _I("[%d/%d] %s:UNKNOWN:%p", index, total, name, value);
+               break;
+       }
+
+       return true;
+}
+
+void _dbg_trace_data(const rrs_data_h data, const rrs_schema_h schema)
+{
+       _I("\n\nTracing data %p [idx/total] name:type:value\n\n",
+          data);
+       rrs_data_foreach_field(data,
+                                schema,
+                                __rrs_data_trace_foreach_field_cb,
+                                NULL);
+       _I("\n---------------------------------------\n\n");
+}
+
+void _dbg_trace_data_content(const rrs_data_h data)
+{
+       GHashTable *t = (GHashTable *)data;
+       GHashTableIter iter;
+       gpointer key = NULL;
+       gpointer value = NULL;
+       const int total = g_hash_table_size(t);
+       int index = 0;
+       g_hash_table_iter_init(&iter, t);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (!key || !value)
+                       continue;
+
+               const char *fld_name = (const char *)key;
+               rrs_schema_field_s *field = (rrs_schema_field_s *)value;
+
+               if (!__rrs_value_has_field(data, fld_name))
+                       continue;
+
+               rrs_value_item_s *i = __rrs_value_lookup_field(data, fld_name);
+               if (!i)
+                       continue;
+               _I("%d/%d: %s, %d, %d, %d, %p",
+                  index ++, total,
+                  fld_name,
+                  field->type,
+                  field->access,
+                  field->required,
+                  i->item);
+       }
+}
+/*--------------------------------------------------------------------------=-*/
+
+int rrs_schema_create(const char *name,
+                                rrs_schema_h *schema)
+{
+       /* Check if parameters are valid */
+       if (!schema || !name)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       *schema = (rrs_schema_h) g_slice_new0(rrs_schema_s);
+
+       if (*schema == NULL) {
+               ERR("Out of memory");
+               return RRS_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Initialize schema data */
+       rrs_schema_s *s = (rrs_schema_s *)(*schema);
+       s->resource = RRS_RESOURCE_NONE;
+       s->name = g_strndup(name, _RRS_SCHEMA_NAME_MAX_LENGTH);
+       s->fields = __rrs_create_schema_field_table();
+
+       /* TODO: register in RRS */
+
+       return RRS_ERROR_NONE;
+}
+
+
+rrs_schema_h _rrs_schema_init_from_json(Json *j)
+{
+       /* Instantiate schema */
+       /* TODO: check if schema with this ID already exists */
+       rrs_schema_h schema = NULL;
+       rrs_schema_create(j->getStr("id").c_str(), &schema);
+       rrs_schema_s *s = (rrs_schema_s *)schema;
+       if(!s)
+               return NULL;
+
+       do {
+               /* Get json-schema ver */
+               if(j->getStr("$schema").empty())
+                       break;
+
+               /* Get the resource schema title */
+               s->title = g_strdup(j->getStr("title").c_str());
+
+               /* Get names of required fields */
+               const int req_amount = j->arrayGetSize(NULL, "required");
+               std::unordered_map<std::string, bool> req_fields;
+               for(int i = 0; i < req_amount; i ++) {
+                       std::string fld_name;
+                       j->getArrayElem(NULL, "required", i, &fld_name);
+                       req_fields[fld_name] = true;
+               }
+
+
+               /* Get field definitions */
+               std::unique_ptr<Json> defs(j->getJson("definitions"));
+               if(!defs)
+                       break;
+               std::list<std::string> def_list;
+               defs->getKeys(&def_list);
+
+               for(std::list<std::string>::iterator it = def_list.begin();
+                   it != def_list.end(); it++) {
+                       const std::string def_name = *it;
+                       std::unique_ptr<Json> def(
+                                       defs->getJson(def_name.c_str()));
+                       if(!def)
+                               continue;
+
+                       /* TODO: Can it be something else, not object? */
+                       if(def->getStr("type") != "object")
+                               break;
+
+                       std::unique_ptr<Json> props(
+                                       def->getJson("properties"));
+                       if(!props)
+                               break;
+
+                       std::list<std::string> prop_list;
+                       props->getKeys(&prop_list);
+
+                       /* Get fields */
+                       for(std::list<std::string>::iterator pit =
+                           prop_list.begin(); pit != prop_list.end(); ++pit) {
+                               std::string fld_name = *pit;
+                               std::unique_ptr<Json> f(
+                                       props->getJson(fld_name.c_str()));
+                               if(!f)
+                                       continue;
+
+                               /* TODO: add description to the field struct */
+                               /*std::string fld_descr =
+                                       f->get_str("description");*/
+
+                               rrs_schema_add_field(schema,
+                                  fld_name.c_str(),
+                                  _rrs_schema_get_type(f->getStr("type")),
+                                  _rrs_schema_get_access(f->getStr("access")),
+                                  req_fields[fld_name], NULL);
+                               /* TODO: hierarchical fields */
+                       }
+               }
+
+               /* Trace loaded schema */
+               /*_dbg_trace_schema(schema);*/
+
+               return schema;
+       } while (false);
+
+       /* Failed to init the schema */
+       rrs_schema_destroy(schema);
+       return NULL;
+}
+
+
+int rrs_schema_create_from_json(const char *json_schema,
+                                          rrs_schema_h *schema)
+{
+       /* Check if parameters are valid */
+       if (!json_schema || !schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Parse the schema */
+       std::unique_ptr<Json> j(new Json(json_schema));
+       *schema = _rrs_schema_init_from_json(j.get());
+
+       return ((*schema) ? RRS_ERROR_NONE : RRS_ERROR_INVALID_PARAMETER);
+}
+
+
+int rrs_schema_create_from_simple_json(const char *schema_name,
+                                                 const char *json_simplified,
+                                                 rrs_schema_h *schema)
+{
+       /* Check if schema handle is valid */
+
+       /* Check if parameters are valid */
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_schema_data_create_from_json(const char *schema_name,
+                                               const char *json_simplified,
+                                               rrs_schema_h *schema,
+                                               rrs_data_h *data)
+{
+       /* Check if schema handle is valid */
+
+       /* Check if parameters are valid */
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_schema_load(const rrs_resource_e resource_id,
+                              rrs_schema_h *control_schema,
+                              rrs_schema_h *event_schema)
+{
+       std::string service_schema_name, resource_schema_name;
+
+       /* Check if parameters are valid */
+       if ((resource_id < RRS_RESOURCE_NONE)
+           || (resource_id > RRS_RESOURCE_ALL)
+           || !event_schema || !control_schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Parse the schema */
+       std::unique_ptr<Json> control_json(new Json);
+       std::unique_ptr<Json> event_json(new Json);
+
+       _rrs_get_schema_system_path(resource_id, service_schema_name, resource_schema_name);
+
+       event_json->load(resource_schema_name.c_str());
+       control_json->load(service_schema_name.c_str());
+
+       *control_schema = _rrs_schema_init_from_json(control_json.get());
+       *event_schema = _rrs_schema_init_from_json(event_json.get());
+
+
+       if (*control_schema == NULL || *event_schema == NULL)
+               return RRS_ERROR_INVALID_PARAMETER;
+       else
+               return RRS_ERROR_NONE;
+}
+
+int rrs_discovery_schema_load(const rrs_resource_e resource_id,
+                              rrs_schema_h *control_schema)
+{
+       std::string discovery_schema_name;
+
+       /* Check if parameters are valid */
+       if ((resource_id < RRS_RESOURCE_NONE)
+           || (resource_id > RRS_RESOURCE_ALL)
+           || !control_schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Parse the schema */
+       std::unique_ptr<Json> control_json(new Json);
+
+       _rrs_get_discovery_schema_system_path(resource_id, discovery_schema_name);
+
+       control_json->load(discovery_schema_name.c_str());
+
+       *control_schema = _rrs_schema_init_from_json(control_json.get());
+
+       if (*control_schema == NULL)
+               return RRS_ERROR_INVALID_PARAMETER;
+       else
+               return RRS_ERROR_NONE;
+}
+
+int rrs_schema_load_custom(const char *schema_name,
+                                     rrs_schema_h *schema)
+{
+       /* Check if parameters are valid */
+       if (!schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Parse the schema */
+       std::unique_ptr<Json> j(new Json);
+       j->load(_rrs_get_schema_custom_path(schema_name).c_str());
+       *schema = _rrs_schema_init_from_json(j.get());
+
+       return (*schema) ? RRS_ERROR_NONE : RRS_ERROR_INVALID_PARAMETER;
+}
+
+
+int rrs_schema_save_to_storage(const rrs_schema_h schema)
+{
+       /* Check if schema handle is valid */
+
+       /* Check if parameters are valid */
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_schema_delete_from_storage(const char *schema_name)
+{
+       /* Check if schema handle is valid */
+
+       /* Check if parameters are valid */
+
+       return RRS_ERROR_NONE;
+}
+
+
+static int _rrs_schema_clone(const rrs_schema_h origin, rrs_schema_h *cloned)
+{
+       /* Check if schema handle is valid */
+       if (!origin)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if(!cloned)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Clonning the schema */
+       int error = RRS_ERROR_NONE;
+       do {
+               rrs_schema_s *s = (rrs_schema_s *) origin;
+
+               error = rrs_schema_create(s->name, cloned);
+               if (!(*cloned) || (error != RRS_ERROR_NONE))
+                       break;
+
+               /* Cloning data */
+               rrs_schema_s *cl = (rrs_schema_s *) (*cloned);
+
+               cl->resource = s->resource;
+
+               if (s->title) {
+                       cl->title = g_strndup(s->title,
+                                             _RRS_SCHEMA_TITLE_MAX_LENGTH);
+                       error = (cl->title) ? error : RRS_ERROR_OUT_OF_MEMORY;
+                       if (error != RRS_ERROR_NONE)
+                               break;
+               }
+
+               if (s->file) {
+                       cl->file = g_strndup(s->file,
+                                            _RRS_SCHEMA_FILE_MAX_LENGTH);
+                       error = (cl->file) ? error : RRS_ERROR_OUT_OF_MEMORY;
+                       if (error != RRS_ERROR_NONE)
+                               break;
+               }
+               if (s->fields)
+                       __rrs_clone_schema_field_table(s->fields, &cl->fields);
+
+               return RRS_ERROR_NONE;
+       } while (false);
+
+       rrs_schema_destroy(*cloned);
+       *cloned = NULL;
+       return error;
+}
+
+int rrs_schema_destroy(rrs_schema_h schema)
+{
+       /* Check if schema handle is valid */
+       if (!schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Release schema data */
+       rrs_schema_s *s = (rrs_schema_s *)schema;
+       if(s->name)
+               g_free(s->name);
+       if(s->title)
+               g_free(s->title);
+       if(s->file)
+               g_free(s->file);
+       __rrs_destroy_schema_field_table(s->fields);
+
+       /* TODO: de-register in RRS */
+
+
+       g_slice_free(rrs_schema_s, s);
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_schema_add_field(rrs_schema_h schema,
+                                   const char *name,
+                                   const RrsSchemaType type,
+                                   const RrsSchemaAccess access,
+                                   const bool required,
+                                   const rrs_schema_h complex_schema)
+{
+       /* Check if schema handle is valid */
+       if (!schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if this API feature available */
+
+       /* Check if parameters are valid */
+       if (!name
+           || (type < RRS_SCHEMA_TYPE_NONE)
+           || (type > RRS_SCHEMA_TYPE_COMPLEX)
+           || (access < RRS_SCHEMA_ACCESS_NONE)
+           || (access > RRS_SCHEMA_ACCESS_READ_WRITE))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Add field */
+       rrs_schema_s *s = (rrs_schema_s *)schema;
+       if (g_hash_table_contains(s->fields, name))
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       g_hash_table_insert(s->fields, g_strdup(name),
+                           __rrs_schema_field_create_complete(
+                                      type, access, required, complex_schema));
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_schema_foreach_field(rrs_schema_h schema,
+                                       rrs_schema_foreach_field_cb callback,
+                                       void *user_data)
+{
+       /* Check if schema handle is valid */
+       if (!schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!callback)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Iterate through all fields */
+       rrs_schema_s *s = (rrs_schema_s *)schema;
+
+       GHashTableIter iter;
+       gpointer key, value;
+       const int total = g_hash_table_size(s->fields);
+       int index = 0;
+       g_hash_table_iter_init(&iter, s->fields);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (!value)
+                       continue;
+
+               rrs_schema_field_s *f = (rrs_schema_field_s *)value;
+
+               if (!callback(index++, total,
+                             (char *)key, f->type, f->access, f->required,
+                             f->complex_schema, user_data))
+                       break;
+       }
+
+       return RRS_ERROR_NONE;
+}
+
+static bool __rrs_schema_create_data_cb(int index,
+                                       int total,
+                                       const char *name,
+                                       const RrsSchemaType type,
+                                       const RrsSchemaAccess access,
+                                       const bool required,
+                                       const rrs_schema_h schema,
+                                       void *user_data)
+{
+       rrs_data_h data = (rrs_data_h) user_data;
+       GHashTable *t = (GHashTable *)data;
+
+       /* Check if the field doesn't exist yet */
+       if (g_hash_table_contains(t, name))
+               return true;
+
+       /* Add new field */
+       g_hash_table_insert(t, g_strdup(name),
+                           __rrs_value_item_create(type,
+                                                   __rrs_value_alloc(type)));
+
+       return true;
+}
+
+
+int rrs_schema_create_data(const rrs_schema_h schema,
+                                     rrs_data_h *data)
+{
+       /* Check if schema handle is valid */
+       if (!schema)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       *data = __rrs_create_value_table();
+       if (!data) {
+               ERR("Out of memory");
+               return RRS_ERROR_OUT_OF_MEMORY;
+       }
+
+       rrs_schema_foreach_field(schema, __rrs_schema_create_data_cb, *data);
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_destroy(rrs_data_h data)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       __rrs_destroy_value_table((GHashTable *)data);
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_clone(const rrs_data_h origin, rrs_data_h *cloned)
+{
+       /* Check if schema handle is valid */
+       if (!origin)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if(!cloned)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+
+       /* Clonning the schema */
+       int error = RRS_ERROR_NONE;
+       do {
+               *cloned = __rrs_create_value_table();
+               if (!(*cloned)) {
+                       ERR("Out of memory");
+                       error = RRS_ERROR_OUT_OF_MEMORY;
+                       break;
+               }
+
+               /* Cloning data */
+               GHashTable *t = (GHashTable *)origin;
+               GHashTable *t_cl = (GHashTable *)(*cloned);
+
+               GHashTableIter iter;
+               gpointer key, value;
+               g_hash_table_iter_init(&iter, t);
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       if (!value)
+                               continue;
+
+                       rrs_value_item_s *i = (rrs_value_item_s *)value;
+                       g_hash_table_insert(t_cl, g_strdup((char *)key),
+                                          __rrs_value_item_clone(i));
+               }
+
+               return RRS_ERROR_NONE;
+       } while (false);
+
+       rrs_data_destroy(*cloned);
+       *cloned = NULL;
+       return error;
+}
+
+int rrs_convert_control_to_event_data(const rrs_data_h control_data, rrs_data_h *event_data)
+{
+       /* Check if schema handle is valid */
+       if (!control_data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if(!event_data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+
+       int error = RRS_ERROR_NONE;
+       do {
+               GHashTable *t_ev = (GHashTable *)(*event_data);
+
+               GHashTableIter iter;
+               gpointer key, value;
+               g_hash_table_iter_init(&iter, t_ev);
+               while (g_hash_table_iter_next(&iter, &key, &value)) {
+                       rrs_value_item_s *i = __rrs_value_lookup_field(control_data, (char *)key);
+                       g_hash_table_insert(t_ev, g_strdup((char *)key), __rrs_value_item_clone(i));
+               }
+
+               return RRS_ERROR_NONE;
+       } while (false);
+
+       return error;
+}
+
+int rrs_data_set_bool(rrs_data_h data,
+                                      const char *name,
+                                      const bool value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_BOOL)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* TODO: check if access is WRITE or READ_WRITE */
+
+       /* Update field value */
+       bool *ptr = (bool *)i->item;
+       *ptr = value;
+
+       return RRS_ERROR_NONE;
+}
+
+int rrs_data_set_int(rrs_data_h data,
+                                     const char *name,
+                                     const int value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_INT)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       int *ptr = (int *)i->item;
+       *ptr = value;
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_set_double(rrs_data_h data,
+                                        const char *name,
+                                        const double value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_DOUBLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       double *ptr = (double *)i->item;
+       *ptr = value;
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_set_string(rrs_data_h data,
+                                        const char *name,
+                                        const char *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_STR)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       char *ptr = (char *)i->item;
+       g_stpcpy(ptr, value);
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_get_bool(const rrs_data_h data,
+                                      const char *name,
+                                      bool *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_BOOL)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       bool *ptr = (bool *)i->item;
+       *value = *ptr;
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_get_int(const rrs_data_h data,
+                                     const char *name,
+                                     int *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_INT)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       int *ptr = (int *)i->item;
+       *value = *ptr;
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_get_double(const rrs_data_h data,
+                                        const char *name,
+                                        double *value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_DOUBLE)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       double *ptr = (double *)i->item;
+       *value = *ptr;
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_get_string(const rrs_data_h data,
+                                        const char *name,
+                                        char **value)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!name || !value)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Look up for the field */
+       if (!__rrs_value_has_field(data, name))
+               return RRS_ERROR_NOT_FOUND;
+
+       rrs_value_item_s *i = __rrs_value_lookup_field(data, name);
+       if(!i)
+               return RRS_ERROR_NOT_FOUND;
+
+       /* Check field type */
+       if(i->type != RRS_SCHEMA_TYPE_STR)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Update field value */
+       char *ptr = (char *)i->item;
+       *value = g_strdup(ptr);
+
+       return RRS_ERROR_NONE;
+}
+
+
+int rrs_data_foreach_field(const rrs_data_h data,
+                                     const rrs_schema_h schema,
+                                     rrs_data_foreach_field_cb callback,
+                                     void *user_data)
+{
+       /* Check if data handle is valid */
+       if (!data)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       /* Check if parameters are valid */
+       if (!schema || !callback)
+               return RRS_ERROR_INVALID_PARAMETER;
+
+       rrs_schema_s *s = (rrs_schema_s *)schema;
+       GHashTableIter iter;
+       gpointer key = NULL;
+       gpointer value = NULL;
+       const int total = g_hash_table_size(s->fields);
+       int index = 0;
+       g_hash_table_iter_init(&iter, s->fields);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               if (!key || !value)
+                       continue;
+
+               const char *fld_name = (const char *)key;
+               rrs_schema_field_s *field = (rrs_schema_field_s *)value;
+
+               if (!__rrs_value_has_field(data, fld_name))
+                       continue;
+
+               rrs_value_item_s *i = __rrs_value_lookup_field(data, fld_name);
+               if (!i)
+                       continue;
+
+               if (!callback (index ++, total,
+                              fld_name,
+                              field->type,
+                              field->access,
+                              field->required,
+                              i->item,
+                              user_data))
+                       break;
+       }
+
+       return RRS_ERROR_NONE;
+}
diff --git a/src/common/schema.h b/src/common/schema.h
new file mode 100644 (file)
index 0000000..987bf24
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SCHEMA_H_
+#define _SCHEMA_H_
+
+#include "rrs_error.h"
+#include "rrs_main.h"
+
+/**
+ * @ingroup    CAPI_RRS_MODULE
+ * @defgroup   CAPI_RRS_SCHEMA_MODULE Schema and data
+ *
+ * @file rrs_schema.h
+ * @brief This file contains the RRS Schema API
+ * @addtogroup CAPI_RRS_SCHEMA_MODULE
+ * @{
+ * @brief This provides APIs related to resource schema and data
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief      Handle of the resource schema.
+ * @details The schema handle can be created or loaded from the schema storage.
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_schema_destroy().
+ *
+ * @par Example
+ * @code
+ * @endcode
+ *
+ * @see rrs_schema_create()
+ * @see rrs_schema_create_from_json()
+ * @see rrs_schema_create_from_simple_json()
+ * @see rrs_schema_data_create_from_json()
+ * @see rrs_schema_load()
+ * @see rrs_schema_load_custom()
+ */
+typedef void *rrs_schema_h;
+
+
+/**
+ * @brief      Handle of the resource schema.
+ * @details The schema handle can be created or loaded from the schema storage.
+ * @since_tizen 3.0
+ *
+ * @remarks To release the handle use rrs_schema_destroy().
+ *
+ * @par Example
+ * @code
+ * @endcode
+ *
+ * @see rrs_schema_create_data()
+ * @see rrs_data_destroy()
+ */
+typedef void *rrs_data_h;
+
+
+/**
+ * @brief      Enumerations of schemas field types, supported by RRS
+ * @since_tizen 3.0
+ */
+typedef enum _rrs_schema_type_e {
+       RRS_SCHEMA_TYPE_NONE,   /**< Indicates no type */
+       RRS_SCHEMA_TYPE_BOOL,   /**< Indicates boolean type */
+       RRS_SCHEMA_TYPE_INT,    /**< Indicates integer type */
+       RRS_SCHEMA_TYPE_DOUBLE, /**< Indicates floating point type */
+       RRS_SCHEMA_TYPE_STR,    /**< Indicates string type */
+       RRS_SCHEMA_TYPE_COMPLEX /**< Indicates complex type */
+} RrsSchemaType;
+
+
+/**
+ * @brief      Enumerations of schema field access types, supported by RRS
+ * @since_tizen 3.0
+ */
+typedef enum _rrs_schema_access_e {
+       RRS_SCHEMA_ACCESS_NONE = 0,                     /**< Indicates no access */
+       RRS_SCHEMA_ACCESS_READ = 1,                     /**< Indicates read only access */
+       RRS_SCHEMA_ACCESS_WRITE = 2,            /**< Indicates write only acccess */
+       RRS_SCHEMA_ACCESS_READ_WRITE = 4,       /**< Indicates read-write access */
+       RRS_SCHEMA_ACCESS_ALL = 8                       /**< Indicates all access */
+} RrsSchemaAccess;
+
+
+
+/**
+ * @brief      Called when requesting fields of schema.
+ * @details This callback is invoked while iterating through the list of
+ * fields of the schema.
+ * @since_tizen 3.0
+ *
+ * @remarks @a name must not be released using free().
+ *
+ * @param[in]  index           The current index of the field
+ * @param[in]  total           The total amount of the fields
+ * @param[in]  name            The name of the field
+ * @param[in]  type            The type of the field
+ * @param[in]  access          The type of the field access, read, write,
+ * read-write
+ * @param[in]  required        The value is required
+ * @param[in]  user_data       The user data passed from
+ * rrs_schema_foreach_field()
+ * @return     @c true to continue with the next iteration of the loop, \n @c
+ * false to break out of the loop
+ *
+ * @pre rrs_schema_foreach_field() will invoke this callback.
+ *
+ * @see rrs_schema_foreach_field()
+ */
+typedef bool (*rrs_schema_foreach_field_cb) (int index,
+                                            int total,
+                                            const char *name,
+                                            const RrsSchemaType type,
+                                            const RrsSchemaAccess access,
+                                            const bool required,
+                                            const rrs_schema_h schema,
+                                            void *user_data);
+
+
+/**
+ * @brief      Called when requesting fields of data.
+ * @details This callback is invoked while iterating through the list of
+ * fields of the data.
+ * @since_tizen 3.0
+ *
+ * @remarks @a name must not be released using free().
+ * \n @a field must be released using free().
+ *
+ * @param[in]  index           The current index of the field
+ * @param[in]  total           The total amount of the fields
+ * @param[in]  name            The name of the field
+ * @param[in]  type            The type of the field
+ * @param[in]  access          The type of the field access, read, write,
+ * read-write
+ * @param[in]  required        The value is required
+ * @param[in]  v               The value the field
+ * @param[in]  user_data       The user data passed from
+ * rrs_data_foreach_field()
+ * @return     @c true to continue with the next iteration of the loop, \n @c
+ * false to break out of the loop
+ *
+ * @pre rrs_data_foreach_field() will invoke this callback.
+ *
+ * @see rrs_data_foreach_field()
+ */
+typedef bool (*rrs_data_foreach_field_cb) (int index,
+                                          int total,
+                                          const char *name,
+                                          const RrsSchemaType type,
+                                          const RrsSchemaAccess access,
+                                          const bool required,
+                                          void *v,
+                                          void *user_data);
+
+
+/**
+ * @brief      Creates an empty resource schema.
+ * @details This function creates an empty resource schema and issues a new
+ * handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  name            The schema name
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_create(const char *name, rrs_schema_h *schema);
+
+
+/**
+ * @brief      Creates a resource schema handle from complete Json string.
+ * @details This function creates a resource schema from a complete Json schema
+ * definition and issues a new handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  json_schema     The complete OIC-compatible json-formatted
+ * definition of schema
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_create_from_json(const char *json_schema, rrs_schema_h *schema);
+
+
+/**
+ * @brief      Creates a resource schema from simplified json string.
+ * @details This function creates a resource schema from simplified json string
+ * and issues a new handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  schema_name     The schema name
+ * @param[in]  json_simplified The simplified json-formatted
+ * definition of schema
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_create_from_simple_json(const char *schema_name,
+                                      const char *json_simplified,
+                                      rrs_schema_h *schema);
+
+
+/**
+ * @brief      Creates both resource schema and data from simplified json
+ * string.
+ * @details This function creates both resource schema and data from simplified
+ * json-formatted string and issues new handles for results.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  schema_name     The schema name
+ * @param[in]  json_simplified The simplified json-formatted
+ * definition of schema
+ * @param[out] schema          The handle of the newly created schema
+ * @param[out] data            The handle of the newly created data
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_data_create_from_json(const char *schema_name,
+                                    const char *json_simplified,
+                                    rrs_schema_h *schema,
+                                    rrs_data_h *data);
+
+
+/**
+ * @brief      Loads a resource schema by specified schema id.
+ * @details This function loads a resource schema by specified schema id and
+ * issues a new handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  resource_id     The predefined resource id
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_load(const rrs_resource_e resource_id,
+                   rrs_schema_h *control_schema,
+                   rrs_schema_h *event_schema);
+
+
+/**
+ * @brief      Loads a resource schema by specified schema id.
+ * @details This function loads a resource schema by specified schema id and
+ * issues a new handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  resource_id     The predefined resource id
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_discovery_schema_load(const rrs_resource_e resource_id,
+                   rrs_schema_h *control_schema);
+
+/**
+ * @brief      Loads a custom resource schema by schema name.
+ * @details This function loads a custom resource schema by specified schema
+ * name and issues a new handle for it.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  rrs             The RRS handle
+ * @param[in]  schema_name     The custom schema name
+ * @param[out] schema          The handle of the newly created schema
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_load_custom(const char *schema_name,
+                          rrs_schema_h *schema);
+
+
+/**
+ * @brief      Saves a custom resource schema in permanent schema storage.
+ * @details This function saves a custom resource schema in a permanent
+ * system-wide schema storage.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  schema          The custom schema handle
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_save_to_storage(const rrs_schema_h schema);
+
+
+/**
+ * @brief      Removes a custom resource schema from permanent schema storage.
+ * @details This function removes a custom resource schema from a permanent
+ * system-wide schema storage.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @remarks @a schema handle must be released using rrs_schema_destroy().
+ *
+ * @param[in]  schema_name     The custom schema name
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_schema_destroy()
+ */
+int rrs_schema_delete_from_storage(const char *schema_name);
+
+
+
+/**
+ * @brief      Destroys the schema handle.
+ * @details This function releases the resource schema handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  schema          The resource schema handle to destroy
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a schema handle is created with one of create or load functions.
+ *
+ * @see rrs_schema_create()
+ */
+int rrs_schema_destroy(rrs_schema_h schema);
+
+
+/**
+ * @brief      Adds new field to the schema.
+ * @details This function adds a new field to the schema.
+ * @since_tizen 3.0
+ *
+ * @param[in]  schema          The schema handle
+ * @param[in]  name            The name of the added field
+ * @param[in]  type            The type of the added field
+ * @param[in]  access          The type of the field access, read, write,
+ * read-write
+ * @param[in]  required        The value is required
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a schema handle is created with one of create or load functions.
+ *
+ * @see rrs_schema_create()
+ * @see #RrsSchemaType
+ */
+int rrs_schema_add_field(rrs_schema_h schema,
+                        const char *name,
+                        const RrsSchemaType type,
+                        const RrsSchemaAccess access,
+                        const bool required,
+                        const rrs_schema_h complex_schema);
+
+
+/**
+ * @brief      Retrieves all fields in schema.
+ * @details This function retrieves all fields in the schema.
+ * @since_tizen 3.0
+ * @remarks The fields will be delivered via rrs_schema_foreach_field_cb().
+ *
+ * @param[in]  schema          The schema handle
+ * @param[in]  callback        The callback function to retrieve fields
+ * @param[in]  user_data       The user data to be passed to the
+ * callback function
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @post This function invokes rrs_schema_foreach_field_cb()
+ * repeatedly to retrieve each field.
+ *
+ * @see rrs_schema_foreach_field_cb()
+ */
+int rrs_schema_foreach_field(rrs_schema_h schema,
+                            rrs_schema_foreach_field_cb callback,
+                            void *user_data);
+
+
+/**
+ * @brief      Creates an instance of structured resource data.
+ * @details This function creates an instance of structured resource data and
+ * issues a new handle for it.
+ * @since_tizen 3.0
+ *
+ * @remarks @a data handle must be released using rrs_data_destroy().
+ *
+ * @param[in]  schema          The handle of schema, defining the data
+ * @param[out] data            The handle of newly created data instance
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_PERMISSION_DENIED Permission Denied
+ *
+ * @see rrs_data_destroy()
+ */
+int rrs_schema_create_data(const rrs_schema_h schema, rrs_data_h *data);
+
+
+/**
+ * @brief      Destroys the data handle.
+ * @details This function releases the data handle.
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/healthinfo
+ *
+ * @param[in]  data            The data handle to destroy
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_destroy(rrs_data_h data);
+
+
+/**
+ * @brief      Clones the data handle.
+ * @details This function clones the structured data handle @a origin.
+ * @since_tizen 3.0
+ *
+ * @remarks @a cloned must be released using rrs_data_destroy().
+ *
+ * @param[in]  origin          The original data handle
+ * @param[out] cloned          A cloned data handle
+ * @return     0 on success, otherwise a negative error data
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see rrs_data_destroy()
+ */
+int rrs_data_clone(const rrs_data_h origin, rrs_data_h *cloned);
+
+
+/**
+ * @brief      Extracts event data from resource state data.
+ * @details This function extracts the event data from the remote resource state data.
+ * @since_tizen 3.0
+ */
+int rrs_convert_control_to_event_data(const rrs_data_h control_data, rrs_data_h *event_data);
+
+
+/**
+ * @brief      Set boolean field value.
+ * @details This function set the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_set_bool(rrs_data_h data,
+                           const char *name,
+                           const bool v);
+
+
+/**
+ * @brief      Set integer field value.
+ * @details This function set the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_set_int(rrs_data_h data,
+                          const char *name,
+                          const int v);
+
+
+/**
+ * @brief      Set floating point field value.
+ * @details This function set the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_set_double(rrs_data_h data,
+                             const char *name,
+                             const double v);
+
+
+/**
+ * @brief      Set string field value.
+ * @details This function set the string field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_set_string(rrs_data_h data,
+                             const char *name,
+                             const char *v);
+
+
+/**
+ * @brief      Get boolean field value.
+ * @details This function get the boolean field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The pointer to bool in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_get_bool(const rrs_data_h data,
+                           const char *name,
+                           bool *v);
+
+
+/**
+ * @brief      Get integer field value.
+ * @details This function get the integer field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The pointer to int in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_get_int(const rrs_data_h data,
+                          const char *name,
+                          int *v);
+
+
+/**
+ * @brief      Get floating point field value.
+ * @details This function get the floating point field value.
+ * @since_tizen 3.0
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The pointer to double in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_get_double(const rrs_data_h data,
+                             const char *name,
+                             double *v);
+
+
+/**
+ * @brief      Get string field value.
+ * @details This function get the sting field value.
+ * @since_tizen 3.0
+ *
+ * @remarks Release the value @a v using free.
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  name            The name of the field
+ * @param[in]  v               The pointer to char * in which to store the
+ * value of the field
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre @a data handle is created with rrs_schema_create_data() functions.
+ *
+ * @see rrs_schema_create_data()
+ */
+int rrs_data_get_string(const rrs_data_h data,
+                             const char *name,
+                             char **v);
+
+
+/**
+ * @brief      Retrieves all fields of structured data.
+ * @details This function retrieves all fields of the structured data.
+ * @since_tizen 3.0
+ *
+ * @remarks The fields will be delivered via rrs_data_foreach_field_cb().
+ *
+ * @param[in]  data            The data handle
+ * @param[in]  callback        The callback function to retrieve fields
+ * @param[in]  user_data       The user data to be passed to the
+ * callback function
+ * @return     0 on success, otherwise a negative error value
+ * @retval     #RRS_ERROR_NONE Successful
+ * @retval     #RRS_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval     #RRS_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @post This function invokes rrs_data_foreach_field_cb()
+ * repeatedly to retrieve each field.
+ *
+ * @see rrs_data_foreach_field_cb()
+ */
+int rrs_data_foreach_field(const rrs_data_h data,
+                          const rrs_schema_h schema,
+                          rrs_data_foreach_field_cb callback,
+                          void *user_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+#endif /* _SCHEMA_H_ */
diff --git a/src/common/schema_types_internal.h b/src/common/schema_types_internal.h
new file mode 100644 (file)
index 0000000..1046967
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __SCHEMA_TYPES_INTERNAL_H__
+#define __SCHEMA_TYPES_INTERNAL_H__
+
+#include <tizen_error.h>
+#include <dlog.h>
+#include "common.h"
+
+/* Color code for dlog */
+#define RED(X)         "\033[0;31m" X "\033[0m"
+#define GREEN(X)       "\033[0;32m" X "\033[0m"
+#define YELLOW(X)      "\033[0;33m" X "\033[0m"
+#define BLUE(X)                "\033[0;34m" X "\033[0m"
+#define PURPLE(X)      "\033[0;35m" X "\033[0m"
+#define CYAN(X)                "\033[0;36m" X "\033[0m"
+
+#define REPLACE_NULL(X) ((X) ? (X) : "")
+#define STR_EQ(X, Y) (g_strcmp0((X), (Y)) == 0)
+
+#define IF_FAIL_RETURN_TAG(cond, ret, tag, fmt, arg...) \
+       do { if (!(cond)) { tag(fmt, ##arg); return ret; } } while (0)
+
+#define IF_FAIL_RETURN(cond, ret) \
+       do { if (!(cond)) { return ret; } } while (0)
+
+#define IF_FAIL_VOID_TAG(cond, tag, fmt, arg...) \
+       do { if (!(cond)) { tag(fmt, ##arg); return; } } while (0)
+
+#define IF_FAIL_VOID(cond) \
+       do { if (!(cond)) { return; } } while (0)
+
+#define IF_FAIL_CATCH_TAG(cond, tag, fmt, arg...) \
+       do { if (!(cond)) { tag(fmt, ##arg); goto CATCH; } } while (0)
+
+#define IF_FAIL_CATCH(cond) \
+       do { if (!(cond)) { goto CATCH; } } while (0)
+
+#define IS_FAILED(X) ((X) != ERR_NONE)
+
+#define ASSERT_ALLOC(X)                IF_FAIL_RETURN_TAG(X, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed")
+#define ASSERT_NOT_NULL(X)     IF_FAIL_RETURN_TAG(X, ERR_INVALID_PARAMETER, _E, "Parameter null")
+
+#define HANDLE_GERROR(Err) \
+       do { if ((Err)) { _E("GError: %s", Err->message); g_error_free(Err); Err = NULL; } } while (0)
+
+#endif /* __SCHEMA_TYPES_INTERNAL_H__ */
diff --git a/src/common/schemas/accelerometer.json b/src/common/schemas/accelerometer.json
new file mode 100644 (file)
index 0000000..2d5faf4
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.accelerometer",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"Accelerometer",
+   "definitions":{
+      "x.org.tizen.accelerometer":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.accelerometer"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/autorotation.json b/src/common/schemas/autorotation.json
new file mode 100644 (file)
index 0000000..141445d
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.autorotation",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"autorotation",
+   "definitions":{
+      "x.org.tizen.autorotation":{
+         "type":"object",
+         "properties":{
+            "state":{
+               "type":"integer",
+               "description":"auto rotation state",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.autorotation"
+      }
+   ],
+   "required":["state"]
+}
+
+
diff --git a/src/common/schemas/geomagneticrotationvector.json b/src/common/schemas/geomagneticrotationvector.json
new file mode 100644 (file)
index 0000000..4641528
--- /dev/null
@@ -0,0 +1,47 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.geomagneticrotationvector",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"geomagneticrotationvector",
+   "definitions":{
+      "x.org.tizen.geomagneticrotationvector":{
+         "type":"object",
+         "properties":{
+            "w":{
+               "type":"double",
+               "description":"W-axis component",
+               "access":"R"
+            },
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.geomagneticrotationvector"
+      }
+   ],
+   "required":["w", "x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/gravity.json b/src/common/schemas/gravity.json
new file mode 100644 (file)
index 0000000..98c25c7
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.gravity",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"gravity",
+   "definitions":{
+      "x.org.tizen.gravity":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.gravity"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/gyroscope.json b/src/common/schemas/gyroscope.json
new file mode 100644 (file)
index 0000000..e0c85bc
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.gyroscope",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"gyroscope",
+   "definitions":{
+      "x.org.tizen.gyroscope":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.gyroscope"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/gyroscoperotationvector.json b/src/common/schemas/gyroscoperotationvector.json
new file mode 100644 (file)
index 0000000..b607985
--- /dev/null
@@ -0,0 +1,47 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.gyroscoperotationvector",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"gyroscoperotationvector",
+   "definitions":{
+      "x.org.tizen.gyroscoperotationvector":{
+         "type":"object",
+         "properties":{
+            "w":{
+               "type":"double",
+               "description":"W-axis component",
+               "access":"R"
+            },
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.gyroscoperotationvector"
+      }
+   ],
+   "required":["w", "x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/hrm.json b/src/common/schemas/hrm.json
new file mode 100644 (file)
index 0000000..33f68f0
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.hrm",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"hrm",
+   "definitions":{
+      "x.org.tizen.hrm":{
+         "type":"object",
+         "properties":{
+            "beats":{
+               "type":"integer",
+               "description":"heart beats per minute",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.hrm"
+      }
+   ],
+   "required":["beats"]
+}
+
+
diff --git a/src/common/schemas/hrmledgreen.json b/src/common/schemas/hrmledgreen.json
new file mode 100644 (file)
index 0000000..ea30ccc
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.hrmledgreen",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"hrmledgreen",
+   "definitions":{
+      "x.org.tizen.hrmledgreen":{
+         "type":"object",
+         "properties":{
+            "value":{
+               "type":"integer",
+               "description":"Amount of green light reflected from persons blood vessel",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.hrmledgreen"
+      }
+   ],
+   "required":["value"]
+}
+
+
diff --git a/src/common/schemas/hrmledir.json b/src/common/schemas/hrmledir.json
new file mode 100644 (file)
index 0000000..0c5641c
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.hrmledir",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"hrmledir",
+   "definitions":{
+      "x.org.tizen.hrmledir":{
+         "type":"object",
+         "properties":{
+            "value":{
+               "type":"integer",
+               "description":"Amount of Infra-red light reflected from persons blood vessel",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.hrmledir"
+      }
+   ],
+   "required":["value"]
+}
+
+
diff --git a/src/common/schemas/hrmledred.json b/src/common/schemas/hrmledred.json
new file mode 100644 (file)
index 0000000..25cf21f
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.hrmledred",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"hrmledred",
+   "definitions":{
+      "x.org.tizen.hrmledred":{
+         "type":"object",
+         "properties":{
+            "value":{
+               "type":"integer",
+               "description":"Amount of red light reflected from persons blood vessel",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.hrmledred"
+      }
+   ],
+   "required":["value"]
+}
+
+
diff --git a/src/common/schemas/humidity.json b/src/common/schemas/humidity.json
new file mode 100644 (file)
index 0000000..2a6f4fd
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.humidity",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"humidity",
+   "definitions":{
+      "x.org.tizen.humidity":{
+         "type":"object",
+         "properties":{
+            "humidity":{
+               "type":"integer",
+               "description":"Ambient room humidity in %",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.humidity"
+      }
+   ],
+   "required":["humidity"]
+}
+
+
diff --git a/src/common/schemas/light.json b/src/common/schemas/light.json
new file mode 100644 (file)
index 0000000..04169fd
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.light",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"light",
+   "definitions":{
+      "x.org.tizen.light":{
+         "type":"object",
+         "properties":{
+            "brightness":{
+               "type":"integer",
+               "description":"brightness of measured light in Lux",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.light"
+      }
+   ],
+   "required":["brightness"]
+}
+
+
diff --git a/src/common/schemas/linearacceleration.json b/src/common/schemas/linearacceleration.json
new file mode 100644 (file)
index 0000000..b01d565
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.linearacceleration",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"linearacceleration",
+   "definitions":{
+      "x.org.tizen.linearacceleration":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.linearacceleration"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/magnetometer.json b/src/common/schemas/magnetometer.json
new file mode 100644 (file)
index 0000000..a5dfdf2
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.magnetometer",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"magnetometer",
+   "definitions":{
+      "x.org.tizen.magnetometer":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.magnetometer"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/orientation.json b/src/common/schemas/orientation.json
new file mode 100644 (file)
index 0000000..8b880be
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.orientation",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"orientation",
+   "definitions":{
+      "x.org.tizen.orientation":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis coordinate",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis coordinate",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis coordinate",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.orientation"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/pressure.json b/src/common/schemas/pressure.json
new file mode 100644 (file)
index 0000000..22f244e
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.pressure",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"pressure",
+   "definitions":{
+      "x.org.tizen.pressure":{
+         "type":"object",
+         "properties":{
+            "pressure":{
+               "type":"integer",
+               "description":"Atmospheric Pressure in  hPa",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.pressure"
+      }
+   ],
+   "required":["pressure"]
+}
+
+
diff --git a/src/common/schemas/proximity.json b/src/common/schemas/proximity.json
new file mode 100644 (file)
index 0000000..cc36743
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.proximity",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"proximity",
+   "definitions":{
+      "x.org.tizen.proximity":{
+         "type":"object",
+         "properties":{
+            "state":{
+               "type":"integer",
+               "description":"Proximity State",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.proximity"
+      }
+   ],
+   "required":["state"]
+}
+
+
diff --git a/src/common/schemas/rotationvector.json b/src/common/schemas/rotationvector.json
new file mode 100644 (file)
index 0000000..8f863f0
--- /dev/null
@@ -0,0 +1,47 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.rotationvector",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"rotationvector",
+   "definitions":{
+      "x.org.tizen.rotationvector":{
+         "type":"object",
+         "properties":{
+            "w":{
+               "type":"double",
+               "description":"W-axis component",
+               "access":"R"
+            },
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.rotationvector"
+      }
+   ],
+   "required":["w", "x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/rrsdiscovery.json b/src/common/schemas/rrsdiscovery.json
new file mode 100644 (file)
index 0000000..43a3f86
--- /dev/null
@@ -0,0 +1,35 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.rrsdiscovery",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"rrsdiscovery",
+   "definitions":{
+      "x.org.tizen.rrsdiscovery":{
+         "type":"object",
+         "properties":{
+            "accelerometer":{
+               "type":"integer",
+               "description":"count of accelerometer sensors",
+               "access":"RW"
+            },
+            "proximity":{
+               "type":"integer",
+               "description":"count of proximity sensors",
+               "access":"RW"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.rrsdiscovery"
+      }
+   ],
+   "required":["accelerometer", "proximity"]
+}
diff --git a/src/common/schemas/sensorcontrol.json b/src/common/schemas/sensorcontrol.json
new file mode 100644 (file)
index 0000000..e64c64b
--- /dev/null
@@ -0,0 +1,62 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.sensorcontrol",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"sensorcontrol",
+   "definitions":{
+      "x.org.tizen.sensorcontrol":{
+         "type":"object",
+         "properties":{
+            "connect_sensor":{
+               "type":"bool",
+               "description":"Connect sensor",
+               "access":"RW"
+            },
+            "disconnect_sensor":{
+               "type":"bool",
+               "description":"Disconnect sensor",
+               "access":"RW"
+            },
+            "interval":{
+               "type":"integer",
+               "description":"Interval",
+               "access":"RW"
+            },
+            "max_batch_latency":{
+               "type":"integer",
+               "description":"Max batch latency",
+               "access":"RW"
+            },
+            "register_event":{
+               "type":"bool",
+               "description":"Register event",
+               "access":"RW"
+            },
+            "unregister_event":{
+               "type":"bool",
+               "description":"Unregister event",
+               "access":"RW"
+            },
+            "get_data":{
+               "type":"bool",
+               "description":"Get data",
+               "access":"RW"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.sensorcontrol"
+      }
+   ],
+   "required":["connect_sensor", "disconnect_sensor", "interval", "max_batch_latency", "register_event", "unregister_event", "get_data"]
+}
+
+
diff --git a/src/common/schemas/temperature.json b/src/common/schemas/temperature.json
new file mode 100644 (file)
index 0000000..a7e6654
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.temperature",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"temperature",
+   "definitions":{
+      "x.org.tizen.temperature":{
+         "type":"object",
+         "properties":{
+            "temperature":{
+               "type":"integer",
+               "description":"Ambient temperature",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.temperature"
+      }
+   ],
+   "required":["temperature"]
+}
+
+
diff --git a/src/common/schemas/uncalibratedgyroscope.json b/src/common/schemas/uncalibratedgyroscope.json
new file mode 100644 (file)
index 0000000..8294701
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.uncalibratedgyroscope",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"uncalibratedgyroscope",
+   "definitions":{
+      "x.org.tizen.uncalibratedgyroscope":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.uncalibratedgyroscope"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/uncalibratedmagnetometer.json b/src/common/schemas/uncalibratedmagnetometer.json
new file mode 100644 (file)
index 0000000..fb3acef
--- /dev/null
@@ -0,0 +1,42 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.uncalibratedmagnetometer",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"uncalibratedmagnetometer",
+   "definitions":{
+      "x.org.tizen.uncalibratedmagnetometer":{
+         "type":"object",
+         "properties":{
+            "x":{
+               "type":"double",
+               "description":"X-axis component",
+               "access":"R"
+            },
+            "y":{
+               "type":"double",
+               "description":"Y-axis component",
+               "access":"R"
+            },
+            "z":{
+               "type":"double",
+               "description":"Z-axis component",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.uncalibratedmagnetometer"
+      }
+   ],
+   "required":["x", "y", "z"]
+}
+
+
diff --git a/src/common/schemas/uv.json b/src/common/schemas/uv.json
new file mode 100644 (file)
index 0000000..8f6a9e8
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   "id":"http://openinterconnect.org/schemas/x.org.tizen.uv",
+   "$schema":"http://json-schema.org/draft-04/schema#",
+   "title":"uv",
+   "definitions":{
+      "x.org.tizen.uv":{
+         "type":"object",
+         "properties":{
+            "index":{
+               "type":"integer",
+               "description":"Uv index of uv rays being exposed on device",
+               "access":"R"
+            }
+         }
+      }
+   },
+   "type":"object",
+   "allOf":[
+      {
+         "$ref":"oic.core.json#/definitions/oic.core"
+      },
+      {
+         "$ref":"oic.baseResource.json#/definitions/oic.r.baseresource"
+      },
+      {
+         "$ref":"#/definitions/x.org.tizen.uv"
+      }
+   ],
+   "required":["index"]
+}
+
+
diff --git a/src/common/services_common.h b/src/common/services_common.h
new file mode 100644 (file)
index 0000000..71b2e63
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SERVICES_COMMON_H_
+#define _SERVICES_COMMON_H_
+
+#include <vector>
+#include "rrs_main.h"
+#include "Mutex.h"
+
+#define MAX_HANDLE 100
+#define MAX_HANDLE_REACHED -1
+
+#define MODULE_OFFSET 24
+#define RESOURCE_OFFSET 14
+#define EVENT_OFFSET  0
+#define COMMAND_OFFSET  0
+
+#define MODULE_TYPE_MASK (0xFF << MODULE_OFFSET)
+#define RESOURCE_TYPE_MASK (0xFF << RESOURCE_OFFSET)
+#define EVENT_TYPE_MASK (0xFF << EVENT_OFFSET)
+#define COMMAND_TYPE_MASK (0xFF << COMMAND_OFFSET)
+
+#define SUCCESS true
+#define FAILURE false
+
+typedef enum _rrs_service_e {
+       ALL_SERVICES = -1,
+       UNKNOWN_SERVICE = 0,
+       SENSOR_FRAMEWORK
+} RrsService;
+
+typedef struct IotTizenModule {
+       std::vector<void*> modules;
+} IotTizenModule;
+
+typedef IotTizenModule* (*create_t)(void);
+
+typedef struct BrokerResource {
+       RrsService service_type;
+       rrs_resource_e resource_type;
+       unsigned char resource_index;
+       int handle;
+       void *data;
+} BrokerResource;
+
+#endif /* _SERVICES_COMMON_H_ */
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
new file mode 100644 (file)
index 0000000..83ffa85
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(daemon)
\ No newline at end of file
diff --git a/src/server/daemon/CMakeLists.txt b/src/server/daemon/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..694951b
--- /dev/null
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 2.6)
+project(rrs-server CXX)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(rrs-server-pkgs REQUIRED vconf glib-2.0 dlog sensor iotcon)
+
+add_definitions(${rrs-server-defs})
+
+INCLUDE_DIRECTORIES(include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+FILE(GLOB rrs-server-srcs *.c *.cpp)
+
+FOREACH(flag ${rrs-server-pkgs_LDFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${rrs-server-pkgs_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_SOURCE_DIR}/src/common)
+include_directories(${CMAKE_SOURCE_DIR}/src/brokers/sensor_framework)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrt -ldl -pthread -fPIE")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
+
+add_executable(${PROJECT_NAME} ${rrs-server-srcs})
+
+target_link_libraries(${PROJECT_NAME} ${rrs-server-pkgs_LDFLAGS}
+       "rrs-common"
+       "sensor-framework-broker"
+       )
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS ${CMAKE_CXX_FLAGS})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"RRS-SERVER\"")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+
+INSTALL(FILES ../../../packaging/remote-resource-service.service DESTINATION /usr/lib/systemd/system)
+INSTALL(TARGETS ${PROJECT_NAME}
+    RUNTIME DESTINATION bin
+    LIBRARY DESTINATION lib/rrs
+)
diff --git a/src/server/daemon/PluginLoader.cpp b/src/server/daemon/PluginLoader.cpp
new file mode 100755 (executable)
index 0000000..af017da
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "PluginLoader.h"
+#include <dlfcn.h>
+#include <dirent.h>
+#include <unordered_set>
+#include <algorithm>
+#include "ServiceManager.h"
+#include "common.h"
+
+using std::make_pair;
+using std::equal;
+using std::unordered_set;
+using std::pair;
+using std::vector;
+using std::string;
+using std::shared_ptr;
+using std::static_pointer_cast;
+
+#define ROOT_ELEMENT "SERVICE"
+#define PATH_ATTR "path"
+
+#define SENSOR_BROKER_DIR_PATH "/usr/lib/rrs/libsensor-framework-broker.so"
+
+PluginLoader::PluginLoader()
+{
+}
+
+PluginLoader::~PluginLoader()
+{
+}
+
+PluginLoader& PluginLoader::__get_instance()
+{
+       static PluginLoader inst;
+       return inst;
+}
+
+bool PluginLoader::loadModule(const string &path, vector<void*> &tizen_modules, void* &handle)
+{
+       void *_handle = dlopen(path.c_str(), RTLD_NOW);
+
+       if (!_handle) {
+               ERR("Failed to dlopen(%s), dlerror : %s", path.c_str(), dlerror());
+               return false;
+       }
+
+       dlerror();
+
+       create_t create_module = (create_t) dlsym(_handle, "create");
+
+       if (!create_module) {
+               ERR("Failed to find symbols in %s", path.c_str());
+               dlclose(_handle);
+               return false;
+       }
+
+       IotTizenModule *plugin = create_module();
+
+       if (!plugin) {
+               ERR("Failed to create module, path is %s\n", path.c_str());
+               dlclose(_handle);
+               return false;
+       }
+
+       tizen_modules.clear();
+       tizen_modules.swap(plugin->modules);
+
+       delete plugin;
+       handle = _handle;
+
+       return true;
+}
+
+bool PluginLoader::insertModule(const string &path)
+{
+       DBG("Insert Service Brokers [%s]", path.c_str());
+
+       std::vector<void *> tizen_modules;
+       void *handle;
+
+       if (!loadModule(path, tizen_modules, handle))
+               return false;
+
+       shared_ptr<ServiceManager> tizen_module;
+
+       for (unsigned int i = 0; i < tizen_modules.size(); ++i) {
+               tizen_module.reset(static_cast<ServiceManager *>(tizen_modules[i]));
+               RrsService service_type = tizen_module->getType();
+               __services.insert(make_pair(service_type, tizen_module));
+       }
+
+       if (!tizen_module->init()) {
+               ERR("Failed to init [%s] module\n", tizen_module->getName());
+       }
+
+       tizen_module->start();
+
+       return true;
+}
+
+bool PluginLoader::loadPlugins(void)
+{
+       insertModule(SENSOR_BROKER_DIR_PATH);
+
+       showTizenModuleInfo();
+
+       return true;
+}
+
+void PluginLoader::showTizenModuleInfo(void)
+{
+       INFO("========== Successfully Loaded Tizen Modules ==========\n");
+
+       int index = 0;
+
+       auto it = __services.begin();
+
+       while (it != __services.end()) {
+               shared_ptr<ServiceManager> tizen_module = it->second;
+               INFO("No:%d [%s]\n", ++index, tizen_module->getName());
+               it++;
+       }
+
+       INFO("========================================================\n");
+}
+
+ServiceManager* PluginLoader::getTizenModule(RrsService type)
+{
+       auto it_plugins = __services.find(type);
+
+       if (it_plugins == __services.end())
+               return NULL;
+
+       return it_plugins->second.get();
+}
+
+
diff --git a/src/server/daemon/PluginLoader.h b/src/server/daemon/PluginLoader.h
new file mode 100755 (executable)
index 0000000..0031161
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ *
+ */
+
+#if !defined(_PLUGIN_LOADER_H_)
+#define _PLUGIN_LOADER_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+#include "services_common.h"
+#include "ServiceManager.h"
+
+class PluginLoader {
+public:
+       static PluginLoader& __get_instance();
+       bool loadPlugins(void);
+       ServiceManager* getTizenModule(RrsService type);
+       bool destroy();
+private:
+       typedef std::multimap<RrsService, std::shared_ptr<ServiceManager>> tizen_services;
+
+       PluginLoader();
+       virtual ~PluginLoader();
+       bool loadModule(const std::string &path, std::vector<void*> &tizen_modules, void* &handle);
+       bool insertModule(const std::string &path);
+       void showTizenModuleInfo(void);
+       bool getPathsFromDir(const std::string &dir_path, std::vector<std::string> &tizen_module_paths);
+       bool getPathsFromConfig(const std::string &config_path, std::vector<std::string> &tizen_module_paths);
+
+       tizen_services __services;
+};
+#endif /* _PLUGIN_LOADER_H_ */
diff --git a/src/server/daemon/ResourceQueue.cpp b/src/server/daemon/ResourceQueue.cpp
new file mode 100755 (executable)
index 0000000..84cb678
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "ResourceQueue.h"
+#include "common.h"
+
+ResourceQueue::ResourceQueue()
+{
+}
+
+ResourceQueue::~ResourceQueue()
+{
+}
+
+ResourceQueue& ResourceQueue::__transmit_control_instance()
+{
+       static ResourceQueue transmit_control_inst;
+       return transmit_control_inst;
+}
+
+ResourceQueue& ResourceQueue::__receive_control_instance()
+{
+       static ResourceQueue receive_control_inst;
+       return receive_control_inst;
+}
+
+ResourceQueue& ResourceQueue::__receive_event_instance()
+{
+       static ResourceQueue receive_event_inst;
+       return receive_event_inst;
+}
+void ResourceQueue::push(BrokerResource const &cmd)
+{
+       BrokerResource *new_cmd = new(std::nothrow) BrokerResource;
+       RETM_IF(!new_cmd, "Failed to allocate memory");
+       *new_cmd = cmd;
+
+       pushInternal(new_cmd);
+}
+
+void ResourceQueue::pushInternal(void *cmd)
+{
+       lock l(__mutex);
+       bool wake = __queue.empty();
+
+       if (__queue.size() >= QUEUE_FULL_SIZE) {
+               ERR("Queue is full, drop it!");
+               delete (BrokerResource *)cmd;
+       } else {
+               __queue.push(cmd);
+       }
+
+       if (wake)
+               __condVar.notify_one();
+}
+
+void* ResourceQueue::pop(void)
+{
+       ulock u(__mutex);
+
+       while (__queue.empty())
+               __condVar.wait(u);
+
+       void* cmd = __queue.front();
+       __queue.pop();
+
+       return cmd;
+}
+
diff --git a/src/server/daemon/ResourceQueue.h b/src/server/daemon/ResourceQueue.h
new file mode 100755 (executable)
index 0000000..5a6f2f3
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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_QUEUE_H_
+#define _RESOURCE_QUEUE_H_
+#include <queue>
+#include <mutex>
+#include <condition_variable>
+#include "services_common.h"
+
+class ResourceQueue {
+public:
+       ResourceQueue();
+       ~ResourceQueue();
+       ResourceQueue(const ResourceQueue &) {};
+       ResourceQueue& operator=(const ResourceQueue &);
+       void push(BrokerResource const &cmd);
+       void* pop(void);
+
+       static ResourceQueue& __transmit_control_instance();
+       static ResourceQueue& __receive_control_instance();
+       static ResourceQueue& __receive_event_instance();
+private:
+       void pushInternal(void *event);
+
+       static const unsigned int QUEUE_FULL_SIZE = 1000;
+
+       std::queue<void*> __queue;
+       std::mutex __mutex;
+       std::condition_variable __condVar;
+
+       typedef std::lock_guard<std::mutex> lock;
+       typedef std::unique_lock<std::mutex> ulock;
+};
+
+#endif
diff --git a/src/server/daemon/ResourceServer.cpp b/src/server/daemon/ResourceServer.cpp
new file mode 100644 (file)
index 0000000..51c6f15
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "ResourceServer.h"
+#include <string>
+#include "common.h"
+#include "SensorFrameworkBroker.h"
+#include "Server.h"
+#include "IotconToRrs.h"
+
+using std::string;
+
+ResourceServer::ResourceServer()
+: __rrs()
+, __controlSchema(NULL)
+, __eventSchema(NULL)
+, __controlData(NULL)
+, __eventData(NULL)
+, __resourceType(RRS_RESOURCE_NONE)
+, __serviceType(UNKNOWN_SERVICE)
+, __resourceIndex(0)
+, __uriPath(NULL)
+, __name(NULL)
+, __interfaces(NULL)
+, __properties(0)
+, __handle(NULL)
+, __observers(NULL)
+{
+}
+
+ResourceServer::~ResourceServer()
+{
+       if (__controlData)
+               rrs_data_destroy(__controlData);
+       __controlData = NULL;
+
+       if (__eventData)
+               rrs_data_destroy(__eventData);
+       __eventData = NULL;
+
+       if (__controlSchema)
+               rrs_schema_destroy(__controlSchema);
+       __controlSchema = NULL;
+
+       if (__eventSchema)
+               rrs_schema_destroy(__eventSchema);
+       __eventSchema = NULL;
+}
+
+void *ResourceServer::__notify_observers(void *user_data)
+{
+       int ret;
+       iotcon_representation_h repr;
+       ResourceServer *res_inst;
+       Server *server_main = (Server *) user_data;
+
+       ret = iotcon_representation_create(&repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_create() Fail(%d)", ret);
+               return false;
+       }
+
+       INFO("Started function to notify server resource observers");
+
+       do {
+               BrokerResource *broker_resource = (BrokerResource *) ResourceQueue::__receive_event_instance().pop();
+
+               res_inst = server_main->getResourceInfo(broker_resource->resource_type, broker_resource->resource_index);
+
+               if (broker_resource->resource_type == res_inst->__resourceType) {
+                       rrs_data_destroy(res_inst->__eventData);
+                       if (rrs_event_data_clone(broker_resource->data, &(res_inst->__eventData)) != RRS_ERROR_NONE) {
+                               ERR("rrs_data_clone() failed");
+                               return false;
+                       }
+
+                       rrs_data_destroy(broker_resource->data);
+
+                       res_inst->setEventRepresentation(&repr);
+
+                       ret = iotcon_resource_notify(res_inst->__handle, repr, res_inst->__observers, IOTCON_QOS_HIGH);
+                       if (ret != IOTCON_ERROR_NONE) {
+                               INFO("No More observers, stopping notifications");
+                               iotcon_representation_destroy(repr);
+                               return NULL;
+                       }
+               }
+       } while (res_inst->__observers != NULL);
+
+       iotcon_representation_destroy(repr);
+       return NULL;
+}
+
+void ResourceServer::__request_handler(const iotcon_resource_h resource, const iotcon_request_h request, void *user_data)
+{
+       Server *server_main = (Server *) user_data;
+       int ret, observe_id;
+       bool retval = true;
+       iotcon_request_type_e type;
+       iotcon_observe_type_e observe_type;
+       char *host_address;
+       BrokerResource broker_resource;
+       ResourceServer *res_inst;
+       iotcon_connectivity_type_e connectivity_type;
+
+       res_inst = server_main->getResourceInfo(resource);
+
+       broker_resource.service_type = res_inst->__serviceType;
+       broker_resource.resource_type = res_inst->__resourceType;
+       broker_resource.resource_index = res_inst->__resourceIndex;
+
+       ret = iotcon_request_get_host_address(request, &host_address);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_host_address() Fail(%d)", ret);
+               res_inst->sendResponse(request, NULL, IOTCON_RESPONSE_ERROR);
+               return;
+       }
+
+       INFO("Handling Resource Client with host_address : %s", host_address);
+
+       ret = iotcon_request_get_connectivity_type(request, &connectivity_type);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_connectivity_type() Fail(%d)", ret);
+               res_inst->sendResponse(request, NULL, IOTCON_RESPONSE_ERROR);
+               return;
+       }
+
+       INFO("Handling Resource Client with connectivity type : %d", connectivity_type);
+
+       ret = iotcon_request_get_request_type(request, &type);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_types() Fail(%d)", ret);
+               res_inst->sendResponse(request, NULL, IOTCON_RESPONSE_ERROR);
+               return;
+       }
+
+       if (type == IOTCON_REQUEST_GET) {
+               retval = res_inst->requestHandlerGet(request);
+       } else if (type == IOTCON_REQUEST_PUT) {
+               retval = res_inst->requestHandlerPut(request, broker_resource);
+       } else if (type == IOTCON_REQUEST_DELETE) {
+               retval = res_inst->requestHandlerDelete(request);
+       }
+       if (!retval) {
+               res_inst->sendResponse(request, NULL, IOTCON_RESPONSE_ERROR);
+               return;
+       }
+
+       ret = iotcon_request_get_observe_type(request, &observe_type);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_observe_type() Fail(%d)", ret);
+               return;
+       }
+
+       if (observe_type == IOTCON_OBSERVE_REGISTER) {
+               ret = iotcon_request_get_observe_id(request, &observe_id);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_request_get_observe_id() Fail(%d)", ret);
+                       return;
+               }
+
+               ret = iotcon_observers_add(res_inst->__observers, observe_id);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_observers_add() Fail(%d)", ret);
+                       return;
+               }
+
+           pthread_t threadId;
+
+               pthread_create(&threadId, NULL, __notify_observers, user_data);
+
+               INFO("Client with host_address : %s, added as observer", host_address);
+
+       } else if (observe_type == IOTCON_OBSERVE_DEREGISTER) {
+               ret = iotcon_request_get_observe_id(request, &observe_id);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_request_get_observe_id() Fail(%d)", ret);
+                       return;
+               }
+               ret = iotcon_observers_remove(res_inst->__observers, observe_id);
+               if (ret != IOTCON_ERROR_NONE) {
+                       ERR("iotcon_observers_remove() Fail(%d)", ret);
+                       return;
+               }
+
+               INFO("Client with host_address : %s, removed as observer", host_address);
+       }
+
+    return;
+}
+
+ResourceServer::ResourceServer(const ResourceServer &obj)
+{
+       __rrs = obj.__rrs;
+       __controlSchema = obj.__controlSchema;
+       __eventSchema = obj.__eventSchema;
+       __controlData = obj.__controlData;
+       __eventData = obj.__eventData;
+       __resourceType = obj.__resourceType;
+       __serviceType = obj.__serviceType;
+       __resourceIndex = obj.__resourceIndex;
+       __uriPath = obj.__uriPath;
+       __name = obj.__name;
+       __interfaces = obj.__interfaces;
+       __properties = obj.__properties;
+       __handle = obj.__handle;
+       __observers = obj.__observers;
+}
+
+ResourceServer& ResourceServer::operator= (const ResourceServer &obj)
+{
+       if (this != &obj) {
+               __rrs = obj.__rrs;
+               __controlSchema = obj.__controlSchema;
+               __eventSchema = obj.__eventSchema;
+               __controlData = obj.__controlData;
+               __eventData = obj.__eventData;
+               __resourceType = obj.__resourceType;
+               __serviceType = obj.__serviceType;
+               __resourceIndex = obj.__resourceIndex;
+               __uriPath = obj.__uriPath;
+               __name = obj.__name;
+               __interfaces = obj.__interfaces;
+               __properties = obj.__properties;
+               __handle = obj.__handle;
+               __observers = obj.__observers;
+       }
+
+    return *this;
+}
+
+bool ResourceServer::setControlRepresentation(iotcon_representation_h *repr)
+{
+       int ret = RRS_ERROR_NONE;
+       iotcon_attributes_h state;
+
+       ret = iotcon_attributes_create(&state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_attributes_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_representation_set_uri_path(*repr, __uriPath);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_set_uri_path() Fail(%d)", ret);
+               iotcon_attributes_destroy(state);
+               return false;
+       }
+
+       IotconToRrs converter(__controlData, __controlSchema, state);
+       converter.setToIotcon();
+
+       ret = iotcon_representation_set_attributes(*repr, state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_set_attributes() Fail(%d)", ret);
+               iotcon_attributes_destroy(state);
+               return false;
+       }
+
+       iotcon_attributes_destroy(state);
+
+       return true;
+}
+
+bool ResourceServer::setEventRepresentation(iotcon_representation_h *repr)
+{
+       int ret = RRS_ERROR_NONE;
+       iotcon_attributes_h state = NULL;
+
+       ret = iotcon_attributes_create(&state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_attributes_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_representation_set_uri_path(*repr, __uriPath);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_set_uri_path() Fail(%d)", ret);
+               iotcon_attributes_destroy(state);
+               return false;
+       }
+
+       IotconToRrs converter(__eventData, __eventSchema, state);
+       converter.setToIotcon();
+
+       ret = iotcon_representation_set_attributes(*repr, state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_set_attributes() Fail(%d)", ret);
+               iotcon_attributes_destroy(state);
+               return false;
+       }
+
+       iotcon_attributes_destroy(state);
+
+       return true;
+}
+
+bool ResourceServer::getControlRepresentation(const iotcon_representation_h repr)
+{
+       iotcon_attributes_h state = NULL;
+
+       const int ret = iotcon_representation_get_attributes(repr, &state);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_get_attributes() Fail(%d)", ret);
+               return false;
+       }
+
+       IotconToRrs converter(__controlData, __controlSchema, state);
+       converter.getFromIotcon();
+
+       return true;
+}
+
+bool ResourceServer::sendResponse(const iotcon_request_h request, const iotcon_representation_h repr, const iotcon_response_result_e result)
+{
+       int ret;
+       iotcon_response_h response;
+
+       ret = iotcon_response_create(request, &response);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_response_set_result(response, result);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_set_result() Fail(%d)", ret);
+               iotcon_response_destroy(response);
+               return false;
+       }
+
+       ret = iotcon_response_set_representation(response, repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_set_representation() Fail(%d)", ret);
+               iotcon_response_destroy(response);
+               return false;
+       }
+
+       ret = iotcon_response_send(response);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_response_send() Fail(%d)", ret);
+               iotcon_response_destroy(response);
+               return false;
+       }
+
+       iotcon_response_destroy(response);
+
+       return true;
+}
+
+bool ResourceServer::createDiscoveryResource(const char *uri, const unsigned char index, const char *resource_name, void *user_data)
+{
+       int ret;
+       iotcon_resource_types_h resource_types;
+       char index_char = (char)index + '0';
+       __resourceIndex = index;
+
+       string uri_temp = string(uri) + "/" + index_char;
+
+       INFO("\n uri_temp = %s", uri_temp.c_str());
+
+       if (rrs_discovery_schema_load(__resourceType, &__controlSchema) != RRS_ERROR_NONE) {
+               ERR("rrs_discovery_schema_load() failed");
+               return false;
+       }
+
+       if (rrs_schema_create_data(__controlSchema, &__controlData) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() failed");
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_create(&__interfaces);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_add(__interfaces, IOTCON_INTERFACE_DEFAULT);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_add() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_add(__interfaces, IOTCON_INTERFACE_BATCH);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_add() Fail(%d)", ret);
+               return false;
+       }
+
+       __properties = IOTCON_RESOURCE_DISCOVERABLE;
+       __properties |= IOTCON_RESOURCE_OBSERVABLE;
+
+       ret = iotcon_resource_types_create(&resource_types);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_types_create() Fail(%d)", ret);
+               free(__uriPath);
+               return false;
+       }
+
+       ret = iotcon_resource_types_add(resource_types, resource_name);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_types_add() Fail(%d)", ret);
+               iotcon_resource_types_destroy(resource_types);
+               free(__uriPath);
+               return false;
+       }
+
+       __uriPath = strdup(uri_temp.c_str());
+       if (__uriPath == NULL) {
+               ERR("strdup(%s) Fail", uri);
+               return false;
+       }
+
+       __name = strdup(resource_name);
+       if (__name == NULL) {
+               ERR("strdup(%s) Fail", __name);
+               return false;
+       }
+
+       INFO("%s Discovery Resource Creation initiated!", __uriPath);
+
+       ret = iotcon_resource_create(__uriPath, resource_types, __interfaces, __properties, __request_handler, user_data, &__handle);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_create() Fail");
+               free(__uriPath);
+               iotcon_resource_types_destroy(resource_types);
+               return false;
+       }
+
+       iotcon_resource_types_destroy(resource_types);
+
+       return true;
+}
+
+bool ResourceServer::createResource(const char *uri, const unsigned char index, const char *resource_name, void *user_data)
+{
+       int ret;
+       iotcon_resource_types_h resource_types;
+       char index_char = (char)index + '0';
+       __resourceIndex = index;
+
+       string uri_temp = string(uri) + "/" + index_char;
+
+       INFO("\n uri_temp = %s", uri_temp.c_str());
+
+       if (rrs_schema_load(__resourceType, &__controlSchema, &__eventSchema) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_load() failed");
+               return false;
+       }
+
+       if (rrs_schema_create_data(__controlSchema, &__controlData) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() failed");
+               return false;
+       }
+
+       if (rrs_schema_create_data(__eventSchema, &__eventData) != RRS_ERROR_NONE) {
+               ERR("rrs_schema_create_data() failed");
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_create(&__interfaces);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_add(__interfaces, IOTCON_INTERFACE_DEFAULT);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_add() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_resource_interfaces_add(__interfaces, IOTCON_INTERFACE_BATCH);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_interfaces_add() Fail(%d)", ret);
+               return false;
+       }
+
+       __properties = IOTCON_RESOURCE_DISCOVERABLE;
+       __properties |= IOTCON_RESOURCE_OBSERVABLE;
+
+       ret = iotcon_observers_create(&__observers);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_observers_create() Fail");
+               return false;
+       }
+
+       ret = iotcon_resource_types_create(&resource_types);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_types_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_resource_types_add(resource_types, resource_name);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_types_add() Fail(%d)", ret);
+               iotcon_resource_types_destroy(resource_types);
+               return false;
+       }
+
+       __uriPath = strdup(uri_temp.c_str());
+       if (__uriPath == NULL) {
+               ERR("strdup(%s) Fail", uri);
+               return false;
+       }
+
+       __name = strdup(resource_name);
+       if (__name == NULL) {
+               ERR("strdup(%s) Fail", __name);
+               free(__uriPath);
+               return false;
+       }
+
+       INFO("%s Resource Creation initiated!", __uriPath);
+
+       ret = iotcon_resource_create(__uriPath, resource_types, __interfaces, __properties, __request_handler, user_data, &__handle);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_resource_create() Fail");
+               free(__uriPath);
+               free(__name);
+               iotcon_resource_types_destroy(resource_types);
+               return false;
+       }
+
+       iotcon_resource_types_destroy(resource_types);
+
+       return true;
+}
+
+void ResourceServer::freeResource()
+{
+       iotcon_observers_destroy(__observers);
+       iotcon_resource_interfaces_destroy(__interfaces);
+       free(__name);
+       free(__uriPath);
+}
+
+bool ResourceServer::requestHandlerGet(const iotcon_request_h request)
+{
+       iotcon_representation_h repr;
+
+       DBG("Handling a GET Control request");
+
+       if (iotcon_representation_create(&repr) != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_create() Fail");
+               return false;
+       }
+
+       rrs_control_data_set_int(__controlData, "accelerometer", Server::__get_instance().getResourceCount(RRS_RESOURCE_ACCELEROMETER));
+       rrs_control_data_set_int(__controlData, "proximity", Server::__get_instance().getResourceCount(RRS_RESOURCE_PROXIMITY));
+
+       setControlRepresentation(&repr);
+       if (repr == NULL) {
+               ERR("set_representation() Fail");
+               return false;
+       }
+
+       if (!sendResponse(request, repr, IOTCON_RESPONSE_OK)) {
+               ERR("send_response() Fail");
+               iotcon_representation_destroy(repr);
+               return false;
+       }
+
+       iotcon_representation_destroy(repr);
+
+       return true;
+}
+
+bool ResourceServer::requestHandlerPut(const iotcon_request_h request, BrokerResource &broker_resource)
+{
+       int ret;
+       iotcon_representation_h repr;
+
+       DBG("Handling a PUT control request");
+
+       ret = iotcon_representation_create(&repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_representation_create() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_request_get_representation(request, &repr);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_representation() Fail(%d)", ret);
+               return false;
+       }
+
+       if (!getControlRepresentation(repr)) {
+               ERR("get_representation() Fail(%d)", ret);
+               return false;
+       }
+
+       rrs_data_clone(__controlData, &(broker_resource.data));
+
+       ResourceQueue::__transmit_control_instance().push(broker_resource);
+
+       if (!sendResponse(request, repr, IOTCON_RESPONSE_OK)) {
+               ERR("send_response() Fail(%d)", ret);
+               return false;
+       }
+
+       iotcon_representation_destroy(repr);
+
+       return true;
+}
+
+bool ResourceServer::requestHandlerDelete(const iotcon_request_h request)
+{
+       int ret, observe_id;
+       DBG("Handling a DELETE request");
+
+       // Remove only observers when resource client is deleted. Deleting static Tizen resources in not allowed
+       ret = iotcon_request_get_observe_id(request, &observe_id);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_request_get_observe_id() Fail(%d)", ret);
+               return false;
+       }
+
+       ret = iotcon_observers_remove(__observers, observe_id);
+       if (ret != IOTCON_ERROR_NONE) {
+               ERR("iotcon_observers_remove() Fail(%d)", ret);
+               return false;
+       }
+
+       if (!sendResponse(request, NULL, IOTCON_RESPONSE_RESOURCE_DELETED)) {
+               ERR("send_response() Fail(%d)", ret);
+               return false;
+       }
+
+       return true;
+}
diff --git a/src/server/daemon/ResourceServer.h b/src/server/daemon/ResourceServer.h
new file mode 100644 (file)
index 0000000..583f905
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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_SERVER_H_
+#define _RESOURCE_SERVER_H_
+
+#include "rrs.h"
+#include "services_common.h"
+#include "schema.h"
+
+class ResourceServer {
+public:
+       ResourceServer();
+       virtual ~ResourceServer();
+       ResourceServer(const ResourceServer &obj);
+       ResourceServer& operator= (const ResourceServer &obj);
+       bool createDiscoveryResource(const char *uri, const unsigned char index, const char *type, void *user_data);
+       bool createResource(const char *uri, const unsigned char index, const char *type, void *user_data);
+       void freeResource();
+       bool sendResponse(const iotcon_request_h request, const iotcon_representation_h repr, const iotcon_response_result_e result);
+       bool setControlRepresentation(iotcon_representation_h *repr);
+       bool setEventRepresentation(iotcon_representation_h *repr);
+       bool getControlRepresentation(const iotcon_representation_h repr);
+       bool requestHandlerGet(const iotcon_request_h request);
+       bool requestHandlerPut(const iotcon_request_h request, BrokerResource &broker_resource);
+       bool requestHandlerDelete(const iotcon_request_h request);
+
+       static void __request_handler(const iotcon_resource_h resource, const iotcon_request_h request, void *user_data);
+       static void *__notify_observers(void *param);
+
+       rrs_h __rrs;
+       rrs_schema_h __controlSchema;
+       rrs_schema_h __eventSchema;
+       rrs_data_h __controlData;
+       rrs_data_h __eventData;
+       rrs_resource_e __resourceType;
+       RrsService __serviceType;
+       unsigned char __resourceIndex;
+       char *__uriPath;
+       char *__name;
+       iotcon_resource_interfaces_h __interfaces;
+       int __properties;
+       iotcon_resource_h __handle;
+       iotcon_observers_h __observers;
+};
+
+
+#endif
diff --git a/src/server/daemon/Server.cpp b/src/server/daemon/Server.cpp
new file mode 100755 (executable)
index 0000000..a8cd0ef
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "Server.h"
+#include <thread>
+#include <vconf.h>
+#include "rrs.h"
+#include "ResourceServer.h"
+#include "common.h"
+
+
+using std::thread;
+
+Server::Server()
+{
+       __mainLoop = NULL;
+       /* Create RRS */
+       int ret = rrs_create(&__rrs);
+       if (ret != RRS_ERROR_NONE) {
+               ERR("rrs_create() Fail(%d)", ret);
+               return;
+       }
+}
+
+Server::~Server()
+{
+       stop();
+       rrs_destroy(__rrs);
+}
+
+std::string Server::get_device_name()
+{
+       static std::string g_device_name;
+
+       if(g_device_name.empty()) {
+               char* device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
+               if (device_name == NULL) {
+                       g_device_name = "Tizen";
+               } else {
+                       g_device_name = device_name;
+               }
+               DBG("device_name: %s", g_device_name.c_str());
+       }
+
+       return g_device_name;
+}
+
+void Server::run(void)
+{
+       GMainLoop *loop;
+       ResourceServer server_temp;
+       ResourceServer *discovery = NULL, *accel = NULL, *proxi = NULL;
+
+       loop = g_main_loop_new(NULL, FALSE);
+
+       discovery = new ResourceServer;
+       accel = new ResourceServer;
+       proxi = new ResourceServer;
+
+       if (rrs_create(&(discovery->__rrs)) != RRS_ERROR_NONE) {
+               ERR("Error Creating RRS Handle!\n");
+               return;
+       }
+
+       if (rrs_create(&(accel->__rrs)) != RRS_ERROR_NONE) {
+               ERR("Error Creating RRS Handle!\n");
+               return;
+       }
+
+       if (rrs_create(&(proxi->__rrs)) != RRS_ERROR_NONE) {
+               ERR("Error Creating RRS Handle!\n");
+               return;
+       }
+
+       iotcon_set_device_name(get_device_name().c_str());
+
+       proxi->__serviceType = SENSOR_FRAMEWORK;
+       proxi->__resourceType = RRS_RESOURCE_PROXIMITY;
+       proxi->__resourceIndex = 1;
+
+       __serverInfo.insert(std::make_pair(proxi->__resourceType, proxi));
+
+       if (!proxi->createResource(PROXIMITY_RESOURCE_URI_PREFIX, proxi->__resourceIndex, PROXIMITY_RESOURCE_NAME, (void *) this)) {
+               ERR("Error Creating Resource!\n");
+               return;
+       }
+
+       accel->__serviceType = SENSOR_FRAMEWORK;
+       accel->__resourceType = RRS_RESOURCE_ACCELEROMETER;
+       accel->__resourceIndex = 1;
+
+       __serverInfo.insert(std::make_pair(accel->__resourceType, accel));
+
+       if (!accel->createResource(ACCELEROMETER_RESOURCE_URI_PREFIX, accel->__resourceIndex, ACCELEROMETER_RESOURCE_NAME, (void *) this)) {
+               ERR("Error creating resource!\n");
+               return;
+       }
+
+       discovery->__serviceType = ALL_SERVICES;
+       discovery->__resourceType = RRS_RESOURCE_DISCOVERY;
+       discovery->__resourceIndex = 1;
+
+       __serverInfo.insert(std::make_pair(discovery->__resourceType, discovery));
+
+       if (!discovery->createDiscoveryResource(DISCOVERY_RESOURCE_URI_PREFIX, discovery->__resourceIndex, DISCOVERY_RESOURCE_NAME, (void *) this)) {
+               ERR("Error Creating Resource!\n");
+               return;
+       }
+
+       g_main_loop_run(loop);
+       g_main_loop_unref(loop);
+
+       discovery->freeResource();
+       iotcon_resource_destroy(discovery->__handle);
+       deleteResource(RRS_RESOURCE_DISCOVERY, 1);
+
+       accel->freeResource();
+       iotcon_resource_destroy(accel->__handle);
+       deleteResource(RRS_RESOURCE_ACCELEROMETER, 1);
+
+       proxi->freeResource();
+       iotcon_resource_destroy(proxi->__handle);
+       deleteResource(RRS_RESOURCE_PROXIMITY, 1);
+
+       if (rrs_destroy(discovery->__rrs) != RRS_ERROR_NONE) {
+               ERR("Error Destroying RRS Handle!\n");
+       }
+
+       if (rrs_destroy(accel->__rrs) != RRS_ERROR_NONE) {
+               ERR("Error Destroying RRS Handle!\n");
+       }
+
+       if (rrs_destroy(proxi->__rrs) != RRS_ERROR_NONE) {
+               ERR("Error Destroying RRS Handle!\n");
+       }
+
+       delete discovery;
+       delete accel;
+       delete proxi;
+
+       return;
+}
+
+void Server::stop(void)
+{
+}
+
+void Server::addResource(const rrs_resource_e resource_type, ResourceServer *info)
+{
+       __serverInfo.insert(std::pair<unsigned int, ResourceServer *>((unsigned int)resource_type, info));
+}
+
+bool Server::deleteResource(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       server_info_iterator it = __serverInfo.find(resource_type);
+
+       if (it == __serverInfo.end()) {
+               ERR("Resource[%d] with index [%d] is not found", resource_type, resource_index);
+               return false;
+       }
+
+       for (it = __serverInfo.begin(); it != __serverInfo.end(); ++it) {
+               if ((it->second)->__resourceIndex == resource_index) {
+                       __serverInfo.erase(it);
+               }
+       }
+
+       return true;
+}
+
+ResourceServer *Server::getResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       server_info_iterator it;
+
+       for (it = __serverInfo.begin(); it != __serverInfo.end(); ++it) {
+               if ((it->second)->__resourceType == resource_type) {
+                       if ((it->second)->__resourceIndex == resource_index) {
+                               return it->second;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+int Server::getResourceCount(const rrs_resource_e resource_type)
+{
+       int count = 0;
+       server_info_iterator it;
+
+       for (it = __serverInfo.begin(); it != __serverInfo.end(); ++it) {
+               if ((it->second)->__resourceType == resource_type) {
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+ResourceServer *Server::getResourceInfo(const iotcon_resource_h handle)
+{
+       server_info_iterator it;
+
+       for (it = __serverInfo.begin(); it != __serverInfo.end(); ++it) {
+               if ((it->second)->__handle == handle) {
+                               return it->second;
+               }
+       }
+
+       return NULL;
+}
+
+
+Server& Server::__get_instance()
+{
+       static Server inst;
+       return inst;
+}
diff --git a/src/server/daemon/Server.h b/src/server/daemon/Server.h
new file mode 100755 (executable)
index 0000000..68f7a8d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SERVER_H_
+#define _SERVER_H_
+
+#include <glib.h>
+#include <map>
+#include <string>
+#include "rrs.h"
+#include "ResourceServer.h"
+
+typedef std::multimap<unsigned int, ResourceServer *> server_info_map;
+typedef server_info_map::iterator server_info_iterator;
+
+class Server {
+public:
+       void run(void);
+       void stop(void);
+       static Server& __get_instance(void);
+
+       // resource_index is used in case there are multiple resources of same type on a device
+       void addResource(const rrs_resource_e resource_type, ResourceServer *info);
+       bool deleteResource(const rrs_resource_e resource_type, const unsigned char resource_index);
+       ResourceServer *getResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index);
+       int getResourceCount(const rrs_resource_e resource_type);
+       ResourceServer *getResourceInfo(const iotcon_resource_h handle);
+       std::string get_device_name(void);
+private:
+       Server();
+       ~Server();
+       bool createResource(const unsigned int resource);
+
+       GMainLoop *__mainLoop;
+       server_info_map __serverInfo;
+       rrs_h __rrs;
+};
+
+#endif
diff --git a/src/server/daemon/ServiceManager.cpp b/src/server/daemon/ServiceManager.cpp
new file mode 100755 (executable)
index 0000000..5fb1eed
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "ServiceManager.h"
+#include <algorithm>
+#include "common.h"
+
+ServiceManager::ServiceManager()
+: __client(0)
+, __started(false)
+{
+}
+
+ServiceManager::~ServiceManager()
+{
+}
+
+bool ServiceManager::start()
+{
+       AUTOLOCK(__mutex);
+       AUTOLOCK(__clientMutex);
+
+       ++__client;
+
+       if (__client == 1) {
+               if (!onStart()) {
+                       return false;
+               }
+
+               __started = true;
+       }
+
+       return true;
+}
+
+bool ServiceManager::stop(void)
+{
+       AUTOLOCK(__mutex);
+       AUTOLOCK(__clientMutex);
+
+       --__client;
+
+       if (__client == 0)
+               __started = false;
+
+       return true;
+}
+
+void ServiceManager::addControlResource(const rrs_resource_e resource_type, BrokerResource *info)
+{
+       __controlBrokerInfo.insert(std::make_pair((unsigned int)resource_type, info));
+}
+
+bool ServiceManager::deleteControlResource(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       control_broker_info::iterator it;
+    std::pair <control_broker_info::iterator, control_broker_info::iterator> range;
+
+    range = __controlBrokerInfo.equal_range(resource_type);
+    for (it = range.first; it != range.second; ++it) {
+               if (((*it).second)->resource_index == resource_index) {
+                       __controlBrokerInfo.erase(it);
+               }
+       }
+
+       return true;
+}
+
+BrokerResource *ServiceManager::getControlResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       control_broker_info::iterator it;
+    std::pair <control_broker_info::iterator, control_broker_info::iterator> range;
+
+    range = __controlBrokerInfo.equal_range(resource_type);
+    for (it = range.first; it != range.second; ++it) {
+               if (((*it).second)->resource_index == resource_index) {
+                       return ((*it).second);
+               }
+       }
+
+       return NULL;
+}
+
+void ServiceManager::addEventResource(const rrs_resource_e resource_type, BrokerResource *info)
+{
+       __eventBrokerInfo.insert(std::make_pair((unsigned int)resource_type, info));
+}
+
+bool ServiceManager::deleteEventResource(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       event_broker_info::iterator it;
+    std::pair <event_broker_info::iterator, event_broker_info::iterator> range;
+
+    range = __eventBrokerInfo.equal_range(resource_type);
+    for (it = range.first; it != range.second; ++it) {
+               if (((*it).second)->resource_index == resource_index) {
+                       __eventBrokerInfo.erase(it);
+               }
+       }
+
+       return true;
+}
+
+BrokerResource *ServiceManager::getEventResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index)
+{
+       event_broker_info::iterator it;
+    std::pair <event_broker_info::iterator, event_broker_info::iterator> range;
+
+    range = __eventBrokerInfo.equal_range(resource_type);
+    for (it = range.first; it != range.second; ++it) {
+               if (((*it).second)->resource_index == resource_index) {
+                       return ((*it).second);
+               }
+       }
+
+       return NULL;
+}
+
+bool ServiceManager::isStarted(void)
+{
+       bool ret_val;
+       AUTOLOCK(__mutex);
+       AUTOLOCK(__clientMutex);
+
+       ret_val = (__started == true) ? true : false;
+
+       return ret_val;
+}
+
+bool ServiceManager::addClient(const rrs_resource_e resource_type)
+{
+       if (!isSupported(resource_type)) {
+               ERR("Invalid resource type: 0x%x", resource_type);
+               return false;
+       }
+
+       AUTOLOCK(__clientInfoMutex);
+
+       ++(__clientInfo[resource_type]);
+       return true;
+}
+
+bool ServiceManager::deleteClient(const rrs_resource_e resource_type)
+{
+       if (!isSupported(resource_type)) {
+               ERR("Invalid resource type: 0x%x", resource_type);
+               return false;
+       }
+
+       AUTOLOCK(__clientInfoMutex);
+
+       auto iter = __clientInfo.find(resource_type);
+
+       if (iter == __clientInfo.end())
+               return false;
+
+       if (iter->second == 0)
+               return false;
+
+       --(iter->second);
+
+       return true;
+}
+
+unsigned int ServiceManager::getClientCnt(const rrs_resource_e resource_type)
+{
+       AUTOLOCK(__clientInfoMutex);
+
+       auto iter = __clientInfo.find(resource_type);
+
+       if (iter == __clientInfo.end())
+               return 0;
+
+       return iter->second;
+}
+
+bool ServiceManager::isSupported(const rrs_resource_e resource_type)
+{
+       //TO DO
+
+       return true;
+}
+
+void ServiceManager::setThread(working_func_t func, void *arg)
+{
+       __serviceThread.setContext(arg);
+       __serviceThread.setWorking(func);
+}
+
+
+bool ServiceManager::startThread(void)
+{
+       return __serviceThread.start();
+}
+
+bool ServiceManager::stopThread(void)
+{
+       return __serviceThread.pause();
+}
diff --git a/src/server/daemon/ServiceManager.h b/src/server/daemon/ServiceManager.h
new file mode 100755 (executable)
index 0000000..ac3bc94
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _SERVICE_MANAGER_H_
+#define _SERVICE_MANAGER_H_
+
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <vector>
+#include <string>
+#include "services_common.h"
+#include "WorkerThread.h"
+#include "ResourceQueue.h"
+
+class ServiceManager {
+public:
+       typedef std::unordered_map<unsigned int, unsigned int> client_info;
+       typedef std::multimap<unsigned int, BrokerResource *> event_broker_info;
+       typedef std::multimap<unsigned int, BrokerResource *> control_broker_info;
+       typedef WorkerThread::trans_func_t working_func_t;
+
+       ServiceManager();
+       virtual ~ServiceManager();
+
+       bool start(void);
+       bool stop(void);
+       bool isStarted(void);
+       bool addClient(const rrs_resource_e resource_type);
+       bool deleteClient(const rrs_resource_e resource_type);
+       // resource_index is used in case there are multiple resources of same type on a device
+       void addControlResource(const rrs_resource_e resource_type, BrokerResource *info);
+       bool deleteControlResource(const rrs_resource_e resource_type, const unsigned char resource_index = 1);
+       BrokerResource *getControlResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index = 1);
+       void addEventResource(const rrs_resource_e resource_type, BrokerResource *info);
+       bool deleteEventResource(const rrs_resource_e resource_type, const unsigned char resource_index = 1);
+       BrokerResource *getEventResourceInfo(const rrs_resource_e resource_type, const unsigned char resource_index = 1);
+       bool isSupported(const rrs_resource_e resource_type);
+
+       virtual bool init(void) {return true;}
+       virtual RrsService getType(void) {return UNKNOWN_SERVICE;}
+       virtual bool processEvent(BrokerResource &packet) {return true;}
+       virtual bool processCommand(void) {return true;}
+       virtual const char* getName(void) {return NULL;}
+protected:
+       void setThread(working_func_t func, void *arg);
+       bool startThread(void);
+       bool stopThread(void);
+       unsigned int getClientCnt(const rrs_resource_e resource_type);
+
+       virtual bool onStart(void) {return true;}
+       virtual bool onStop(void) {return true;}
+
+       Mutex __mutex;
+       Mutex __clientMutex;
+       unsigned int __client;
+       client_info __clientInfo;
+       control_broker_info __controlBrokerInfo;
+       event_broker_info __eventBrokerInfo;
+       Mutex __clientInfoMutex;
+       bool __started;
+private:
+       WorkerThread __serviceThread;
+};
+
+#endif
diff --git a/src/server/daemon/WorkerThread.cpp b/src/server/daemon/WorkerThread.cpp
new file mode 100755 (executable)
index 0000000..e8e187c
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "WorkerThread.h"
+#include <thread>
+#include "common.h"
+
+using std::thread;
+
+WorkerThread::WorkerThread()
+: __state(WORKER_STATE_INITIAL)
+, __context(NULL)
+, __threadCreated(false)
+{
+       for (int i = 0; i < TRANS_FUNC_CNT; ++i)
+               __transFunc[i] = NULL;
+}
+
+WorkerThread::~WorkerThread()
+{
+       stop();
+}
+
+bool WorkerThread::transitionFunction(trans_func_index index)
+{
+       if (__transFunc[index] != NULL) {
+               if(!__transFunc[index](__context)) {
+                       _T("Transition[%d] function returning false", index);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+WorkerThread::worker_state_t WorkerThread::getState(void)
+{
+       lock l(__mutex);
+       return __state;
+}
+
+
+bool WorkerThread::start(void)
+{
+       lock l(__mutex);
+
+       if (__state == WORKER_STATE_WORKING) {
+               _T("Worker thread is already working");
+               return true;
+       }
+
+       if ((__state == WORKER_STATE_INITIAL) || (__state == WORKER_STATE_STOPPED)) {
+               __state = WORKER_STATE_WORKING;
+
+               if (!__threadCreated) {
+                       thread th(&WorkerThread::main, this);
+                       th.detach();
+               }
+               return true;
+       } else if (__state == WORKER_STATE_PAUSED) {
+               __state = WORKER_STATE_WORKING;
+               __condWorking.notify_one();
+               return true;
+       }
+
+       _T("Failed to start, because current state(%d) is not for START", __state);
+
+       return false;
+}
+
+bool WorkerThread::stop(void)
+{
+       lock l(__mutex);
+
+       if (__state == WORKER_STATE_STOPPED) {
+               _T("Worker thread is already stopped");
+               return true;
+       }
+
+       if ((__state == WORKER_STATE_WORKING) || (__state == WORKER_STATE_PAUSED)) {
+               if (__state == WORKER_STATE_PAUSED)
+                       __condWorking.notify_one();
+
+               __state = WORKER_STATE_STOPPED;
+               return true;
+       }
+
+       _T("Failed to stop, because current state(%d) is not for STOP", __state);
+       return false;
+}
+
+bool WorkerThread::pause(void)
+{
+       lock l(__mutex);
+
+       if (__state == WORKER_STATE_PAUSED) {
+               _T("Worker thread is already paused");
+               return true;
+       }
+
+       if (__state == WORKER_STATE_WORKING) {
+               __state = WORKER_STATE_PAUSED;
+               return true;
+       }
+
+       _T("Failed to pause, because current state(%d) is not for PAUSE", __state);
+
+       return false;
+}
+
+bool WorkerThread::resume(void)
+{
+       lock l(__mutex);
+
+       if (__state == WORKER_STATE_WORKING) {
+               _T("Worker thread is already working");
+               return true;
+       }
+
+       if (__state == WORKER_STATE_PAUSED) {
+               __state = WORKER_STATE_WORKING;
+               __condWorking.notify_one();
+               return true;
+       }
+
+       _T("Failed to resume, because current state(%d) is not for RESUME", __state);
+       return false;
+}
+
+
+/*
+ * After state changed to STOPPED, it should not access member fields,
+    because some transition funciton of STOPPED delete this pointer
+ */
+
+void WorkerThread::main(void)
+{
+       _T("Worker thread(0x%x) is created", std::this_thread::get_id());
+
+       transitionFunction(STARTED);
+
+       while (true) {
+               worker_state_t state;
+               state = getState();
+
+               if (state == WORKER_STATE_WORKING) {
+                       if (!transitionFunction(WORKING)) {
+                               __state = WORKER_STATE_STOPPED;
+                               _T("Worker thread(0x%x) exits from working state", std::this_thread::get_id());
+                               __threadCreated = false;
+                               transitionFunction(STOPPED);
+                               break;
+                       }
+                       continue;
+               }
+
+               ulock u(__mutex);
+
+               if (__state == WORKER_STATE_PAUSED) {
+                       transitionFunction(PAUSED);
+
+                       _T("Worker thread(0x%x) is paused", std::this_thread::get_id());
+                       __condWorking.wait(u);
+
+                       if (__state == WORKER_STATE_WORKING) {
+                               transitionFunction(RESUMED);
+                               _T("Worker thread(0x%x) is resumed", std::this_thread::get_id());
+                       } else if (__state == WORKER_STATE_STOPPED) {
+                               __threadCreated = false;
+                               transitionFunction(STOPPED);
+                               break;
+                       }
+               } else if (__state == WORKER_STATE_STOPPED) {
+                       __threadCreated = false;
+                       transitionFunction(STOPPED);
+                       break;
+               }
+       }
+       _T("Worker thread(0x%x)'s main is terminated", std::this_thread::get_id());
+}
+
+void WorkerThread::setStarted(trans_func_t func)
+{
+       __transFunc[STARTED] = func;
+}
+
+void WorkerThread::setStopped(trans_func_t func)
+{
+       __transFunc[STOPPED] = func;
+}
+
+void WorkerThread::setPaused(trans_func_t func)
+{
+       __transFunc[PAUSED] = func;
+}
+
+void WorkerThread::setResumed(trans_func_t func)
+{
+       __transFunc[RESUMED] = func;
+}
+
+void WorkerThread::setWorking(trans_func_t func)
+{
+       __transFunc[WORKING] = func;
+}
+
+void WorkerThread::setContext(void *ctx)
+{
+       __context = ctx;
+}
diff --git a/src/server/daemon/WorkerThread.h b/src/server/daemon/WorkerThread.h
new file mode 100755 (executable)
index 0000000..f38a73d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _WORKER_THREAD_H_
+#define _WORKER_THREAD_H_
+
+#include <mutex>
+#include <condition_variable>
+
+class WorkerThread {
+public:
+       enum worker_state_t {
+               WORKER_STATE_INITIAL,
+               WORKER_STATE_WORKING,
+               WORKER_STATE_PAUSED,
+               WORKER_STATE_STOPPED,
+       };
+
+       typedef bool(*trans_func_t)(void *data);
+
+       WorkerThread();
+       virtual ~WorkerThread();
+
+       bool start(void);
+       bool stop(void);
+       bool pause(void);
+       bool resume(void);
+       worker_state_t getState(void);
+       void setStarted(trans_func_t func);
+       void setStopped(trans_func_t func);
+       void setPaused(trans_func_t func);
+       void setResumed(trans_func_t func);
+       void setWorking(trans_func_t func);
+       void setContext(void *ctx);
+
+private:
+       enum trans_func_index {
+               STARTED = 0,
+               STOPPED,
+               PAUSED,
+               RESUMED,
+               WORKING,
+               TRANS_FUNC_CNT,
+       };
+
+       typedef std::lock_guard<std::mutex>  lock;
+       typedef std::unique_lock<std::mutex> ulock;
+
+       bool transitionFunction(trans_func_index index);
+       void main(void);
+
+       worker_state_t __state;
+       void *__context;
+       std::mutex __mutex;
+       std::condition_variable __condWorking;
+       bool __threadCreated;
+       trans_func_t __transFunc[TRANS_FUNC_CNT];
+};
+
+#endif
diff --git a/src/server/daemon/main.cpp b/src/server/daemon/main.cpp
new file mode 100755 (executable)
index 0000000..abcc0ac
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 "rrs.h"
+#include <signal.h>
+#include <fstream>
+#include "common.h"
+#include "Server.h"
+#include "PluginLoader.h"
+
+using std::fstream;
+
+bool get_proc_name(pid_t pid, char *process_name)
+{
+       FILE *fp;
+       char buf[NAME_MAX];
+       char filename[PATH_MAX];
+
+       sprintf(filename, "/proc/%d/stat", pid);
+       fp = fopen(filename, "r");
+
+       if (fp == NULL)
+               return false;
+
+       if (fscanf(fp, "%*s (%[^)]", buf) < 1) {
+               fclose(fp);
+               return false;
+       }
+
+       strncpy(process_name, buf, NAME_MAX-1);
+       process_name[NAME_MAX-1] = '\0';
+       fclose(fp);
+
+       return true;
+}
+
+static void sig_term_handler(int signo, siginfo_t *info, void *data)
+{
+       char proc_name[NAME_MAX];
+
+       get_proc_name(info->si_pid, proc_name);
+
+       ERR("Received SIGTERM(%d) from %s(%d)\n", signo, proc_name, info->si_pid);
+       exit(EXIT_SUCCESS);
+}
+
+static void signal_init(void)
+{
+       struct sigaction sig_act;
+       memset(&sig_act, 0, sizeof(struct sigaction));
+
+       sig_act.sa_handler = SIG_IGN;
+       sigaction(SIGCHLD, &sig_act, NULL);
+       sigaction(SIGPIPE, &sig_act, NULL);
+
+       sig_act.sa_handler = NULL;
+       sig_act.sa_sigaction = sig_term_handler;
+       sig_act.sa_flags = SA_SIGINFO;
+       sigaction(SIGTERM, &sig_act, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+       INFO("Remote Resource Service started");
+
+       signal_init();
+
+       PluginLoader::__get_instance().loadPlugins();
+
+       Server::__get_instance().run();
+
+       Server::__get_instance().stop();
+
+       INFO("Remote Resource Service terminated");
+       return 0;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..90ae9f6
--- /dev/null
@@ -0,0 +1,34 @@
+cmake_minimum_required(VERSION 2.6)
+project(rrs-test CXX)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(rrs-test-pkgs REQUIRED glib-2.0 dlog sensor iotcon)
+
+INCLUDE_DIRECTORIES(include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+FILE(GLOB rrs-test-srcs *.c *.cpp)
+
+FOREACH(flag ${rrs-test-pkgs_LDFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+FOREACH(flag ${rrs-test-pkgs_CFLAGS})
+       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_SOURCE_DIR}/src/client)
+include_directories(${CMAKE_SOURCE_DIR}/src/common)
+include_directories(${CMAKE_SOURCE_DIR}/src/server)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrt -ldl -pthread -fPIE")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
+
+add_executable(${PROJECT_NAME} ${rrs-test-srcs})
+
+target_link_libraries(${PROJECT_NAME} ${rrs-test-pkgs_LDFLAGS}
+       "rrs-common"
+       "rrs-client"
+       )
+
+install(TARGETS ${PROJECT_NAME} DESTINATION bin)
diff --git a/test/rrs-test.cpp b/test/rrs-test.cpp
new file mode 100644 (file)
index 0000000..110eee2
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd 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 "rrs.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <tizen_type.h>
+#include "common.h"
+
+#define DEFAULT_INTERVAL 100 //ms
+
+void _discovery_handler_cb(rrs_error_e result, rrs_resource_h resource, rrs_control_data_h control_data, void *user_data);
+void _observe_accel_cb(rrs_error_e result, rrs_event_data_h event_data, void *user_data);
+void _observe_proxi_cb(rrs_error_e result, rrs_event_data_h event_data, void *user_data);
+bool _found_discovery_cb(rrs_error_e result, rrs_resource_h resource, void *user_data);
+bool _found_accel_cb(rrs_error_e result, rrs_resource_h resource, void *user_data);
+bool _found_proxi_cb(rrs_error_e result, rrs_resource_h resource, void *user_data);
+
+rrs_h rrs;
+rrs_resource_h accel_resource;
+rrs_resource_h proxi_resource;
+
+void _observe_accel_cb(rrs_error_e result, rrs_event_data_h event_data, void *user_data)
+{
+       static int counter = 0;
+       rrs_resource_e *resource_type = (rrs_resource_e *) user_data;
+
+       if (*resource_type == RRS_RESOURCE_ACCELEROMETER) {
+               double x = .0;
+               double y = .0;
+               double z = .0;
+               rrs_event_data_get_double(event_data, "x", &x);
+               rrs_event_data_get_double(event_data, "y", &y);
+               rrs_event_data_get_double(event_data, "z", &z);
+
+               INFO("Accelerometer Event X=%f, Y=%f, Z=%f", x, y, z);
+               if(++counter == 20) {
+                       rrs_control_data_h control_data;
+
+                       rrs_control_data_create(RRS_RESOURCE_ACCELEROMETER, &control_data);
+
+                       rrs_control_data_set_bool(control_data, "connect_sensor", false);
+                       rrs_control_data_set_bool(control_data, "disconnect_sensor", true);
+                       rrs_control_data_set_int(control_data, "interval", 0);
+                       rrs_control_data_set_int(control_data, "max_batch_latency", 0);
+                       rrs_control_data_set_bool(control_data, "register_event", false);
+                       rrs_control_data_set_bool(control_data, "unregister_event", true);
+                       rrs_control_data_set_bool(control_data, "get_data", false);
+
+                       if(rrs_resource_send_control(accel_resource, control_data, NULL, NULL) != RRS_ERROR_NONE)
+                               return;
+
+                       rrs_control_data_destroy(control_data);
+
+                       rrs_resource_unsubscribe_event(accel_resource);
+               }
+       }
+}
+
+void _observe_proxi_cb(rrs_error_e result, rrs_event_data_h event_data, void *user_data)
+{
+       static int counter = 0;
+       rrs_resource_e *resource_type = (rrs_resource_e *) user_data;
+
+       if (*resource_type == RRS_RESOURCE_PROXIMITY) {
+               int state = 0;
+               rrs_event_data_get_int(event_data, "state", &state);
+
+               if (state == 0)
+                       INFO("Proximity ON");
+               else if (state == 5)
+                       INFO("Proximity OFF");
+
+               if(++counter == 20) {
+                       rrs_control_data_h control_data;
+
+                       rrs_control_data_create(RRS_RESOURCE_PROXIMITY, &control_data);
+
+                       rrs_control_data_set_bool(control_data, "connect_sensor", false);
+                       rrs_control_data_set_bool(control_data, "disconnect_sensor", true);
+                       rrs_control_data_set_int(control_data, "interval", 0);
+                       rrs_control_data_set_int(control_data, "max_batch_latency", 0);
+                       rrs_control_data_set_bool(control_data, "register_event", false);
+                       rrs_control_data_set_bool(control_data, "unregister_event", true);
+                       rrs_control_data_set_bool(control_data, "get_data", false);
+
+                       if(rrs_resource_send_control(proxi_resource, control_data, NULL, NULL) != RRS_ERROR_NONE)
+                               return;
+
+                       rrs_control_data_destroy(control_data);
+
+                       rrs_resource_unsubscribe_event(proxi_resource);
+               }
+       }
+}
+
+bool _found_accel_cb(rrs_error_e result, rrs_resource_h resource, void *user_data)
+{
+       rrs_control_data_h control_data;
+       INFO("Registering for accelerometer observe mode");
+
+       accel_resource = resource;
+
+       rrs_resource_e *resource_type = (rrs_resource_e *) user_data;
+
+       if (*resource_type == RRS_RESOURCE_ACCELEROMETER) {
+               rrs_control_data_create(RRS_RESOURCE_ACCELEROMETER, &control_data);
+               if(rrs_resource_subscribe_event(resource, _observe_accel_cb, user_data) != RRS_ERROR_NONE)
+                       return false;
+       } else {
+               ERR("Wrong callback triggered - Error in RRS library!");
+               return false;
+       }
+
+       rrs_control_data_set_bool(control_data, "connect_sensor", true);
+       rrs_control_data_set_bool(control_data, "disconnect_sensor", false);
+       rrs_control_data_set_int(control_data, "interval", 1000);
+       rrs_control_data_set_int(control_data, "max_batch_latency", 0);
+       rrs_control_data_set_bool(control_data, "register_event", true);
+       rrs_control_data_set_bool(control_data, "unregister_event", false);
+       rrs_control_data_set_bool(control_data, "get_data", false);
+
+       INFO("Sending initial control data for accelerometer resource");
+
+       if(rrs_resource_send_control(resource, control_data, NULL, NULL) != RRS_ERROR_NONE)
+               return false;
+
+       rrs_control_data_destroy(control_data);
+
+       return true;
+}
+
+bool _found_proxi_cb(rrs_error_e result, rrs_resource_h resource, void *user_data)
+{
+       rrs_control_data_h control_data;
+       INFO("Registering for proximity observe mode");
+       proxi_resource = resource;
+
+       rrs_resource_e *resource_type = (rrs_resource_e *) user_data;
+
+       if (*resource_type == RRS_RESOURCE_PROXIMITY) {
+               rrs_control_data_create(RRS_RESOURCE_PROXIMITY, &control_data);
+               if(rrs_resource_subscribe_event(resource, _observe_proxi_cb, user_data) != RRS_ERROR_NONE)
+                       return false;
+       } else {
+               ERR("Wrong callback triggered - Error in RRS library!");
+               return false;
+       }
+
+       rrs_control_data_set_bool(control_data, "connect_sensor", true);
+       rrs_control_data_set_bool(control_data, "disconnect_sensor", false);
+       rrs_control_data_set_int(control_data, "interval", 0);
+       rrs_control_data_set_int(control_data, "max_batch_latency", 0);
+       rrs_control_data_set_bool(control_data, "register_event", true);
+       rrs_control_data_set_bool(control_data, "unregister_event", false);
+       rrs_control_data_set_bool(control_data, "get_data", false);
+
+       INFO("Sending initial control data for proximity resource");
+
+       if(rrs_resource_send_control(resource, control_data, NULL, NULL) != RRS_ERROR_NONE)
+               return false;
+
+       rrs_control_data_destroy(control_data);
+
+       return true;
+}
+
+void _discovery_handler_cb(rrs_error_e result, rrs_resource_h resource, rrs_control_data_h control_data, void *user_data)
+{
+       int accel_count = 0;
+       int proxi_count = 0;
+       char *device_id;
+
+       INFO("Receiving control data");
+
+       rrs_h *rrs_temp = (rrs_h *) user_data;
+
+       rrs_control_data_get_int(control_data, "accelerometer", &accel_count);
+       rrs_control_data_get_int(control_data, "proximity", &proxi_count);
+
+       INFO("Discovery Information: Accelerometer Count = %d, Proximity Sensor Count = %d", accel_count, proxi_count);
+
+       if (accel_count > 0) {
+               rrs_resource_e *accel_type = (rrs_resource_e *) malloc(sizeof(rrs_resource_e));
+
+               *accel_type = RRS_RESOURCE_ACCELEROMETER;
+               rrs_resource_find(*rrs_temp, *accel_type, _found_accel_cb, (void *) accel_type);
+       }
+
+       if (proxi_count > 0) {
+               rrs_resource_e *proxi_type = (rrs_resource_e *) malloc(sizeof(rrs_resource_e));
+
+               *proxi_type = RRS_RESOURCE_PROXIMITY;
+               rrs_resource_find(*rrs_temp, *proxi_type, _found_proxi_cb, (void *) proxi_type);
+       }
+
+       rrs_resource_get_device_id(resource, &device_id);
+
+       INFO("_discovery_handler_cb device_id - %s", device_id);
+}
+
+bool _found_discovery_cb(rrs_error_e result, rrs_resource_h resource, void *user_data)
+{
+       char *device_id;
+       INFO("Getting discovery resource information");
+
+       if(rrs_resource_monitor_control(resource, _discovery_handler_cb, user_data) != RRS_ERROR_NONE) {
+               ERR("Error receiving discovery information from Server!");
+               return false;
+       }
+
+       rrs_resource_get_device_id(resource, &device_id);
+
+       INFO("_found_discovery_cb device_id - %s", device_id);
+
+       return true;
+}
+
+int main(int argc, char **argv)
+{
+       GMainLoop *loop;
+
+       rrs_resource_e *discovery_resource_type = (rrs_resource_e *) malloc(sizeof(rrs_resource_e));
+
+       *discovery_resource_type = RRS_RESOURCE_DISCOVERY;
+
+       loop = g_main_loop_new(NULL, FALSE);
+
+       if (rrs_create(&rrs) != RRS_ERROR_NONE) {
+               printf("Error Creating RRS Handle!\n");
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       rrs_resource_find(rrs, *discovery_resource_type, _found_discovery_cb, (void *) &rrs);
+
+       g_main_loop_run(loop);
+       g_main_loop_unref(loop);
+
+       free(discovery_resource_type);
+       //free(proxi_type);
+       //free(accel_type);
+
+       if (rrs_destroy(rrs) != RRS_ERROR_NONE) {
+               printf("Error Destroying RRS Handle!\n");
+               return RRS_ERROR_INVALID_PARAMETER;
+       }
+
+       return 0;
+}