From: jk7744.park Date: Sat, 24 Oct 2015 07:39:00 +0000 (+0900) Subject: tizen 2.4 release X-Git-Tag: accepted/tizen/2.4/mobile/20151029.033406^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aedb6a68edc7c8de50f9fd43a8c2ad7f3a7abcf7;p=framework%2Fcontext%2Fcontext-common.git tizen 2.4 release --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a01ee28 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..10e3f20 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Mu-Woong Lee diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3757f59 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,58 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(context-common) +INCLUDE(GNUInstallDirs) + +# Targets +SET(target_lib "ctx-common") + +# Source Lists +FILE(GLOB_RECURSE SRCS src/*.cpp) +MESSAGE("Sources: ${SRCS}") + +# Dependencies +SET(DEPS "glib-2.0 gio-2.0 json-glib-1.0 dlog capi-base-common security-server") + +INCLUDE(FindPkgConfig) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/shared +) +ADD_DEFINITIONS(-g -O2 -Wall -fPIC -Wl,--as-needed) + +# Building Library +pkg_check_modules(lib_pkg REQUIRED ${DEPS}) + +FOREACH(flag ${lib_pkg_CFLAGS}) + SET(LIB_EXTRA_CFLAGS "${LIB_EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${target_lib} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target_lib} ${lib_pkg_LDFLAGS}) +SET_TARGET_PROPERTIES(${target_lib} PROPERTIES COMPILE_FLAGS ${LIB_EXTRA_CFLAGS}) +SET_TARGET_PROPERTIES(${target_lib} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"CONTEXT\"") +SET_TARGET_PROPERTIES(${target_lib} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target_lib} PROPERTIES VERSION ${FULLVER}) + +# Installing Library +INSTALL(TARGETS ${target_lib} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT RuntimeLibraries) +INSTALL( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/context-service/internal + FILES_MATCHING PATTERN "*.h" +) + +SET(VERSION ${FULLVER}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(PC_NAME ${PROJECT_NAME}) +SET(PC_INCLUDE "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/context-service/internal") +SET(PC_LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +SET(PC_DESCRIPTION "Tizen Context-Service Shared Library") +SET(PC_REQUIRED ${DEPS}) +SET(PC_LDFLAGS -l${target_lib}) +SET(PC_CFLAGS -I\${includedir}/context-service/internal) + +CONFIGURE_FILE( + ${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1b01074 --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2015 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 (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. + diff --git a/context-common.pc.in b/context-common.pc.in new file mode 100644 index 0000000..378b991 --- /dev/null +++ b/context-common.pc.in @@ -0,0 +1,13 @@ +#Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@PREFIX@ +libdir=@PC_LIBDIR@ +includedir=@PC_INCLUDE@ + +Name: @PC_NAME@ +Description: @PC_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} diff --git a/include/context_mgr.h b/include/context_mgr.h new file mode 100644 index 0000000..13765f0 --- /dev/null +++ b/include/context_mgr.h @@ -0,0 +1,52 @@ +/* + * 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 __CONTEXT_MANAGER_H__ +#define __CONTEXT_MANAGER_H__ + +namespace ctx { + /* Forward Declaration */ + class json; + class context_provider_iface; + class context_provider_info; + + enum operation_type_e { + OPS_SUBSCRIBE = 1, + OPS_READ = 2, + OPS_WRITE = 4, + }; + + namespace context_manager { + /* + */ + bool register_provider(const char *subject, context_provider_info &provider_info); + + /* + */ + bool register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options); + + /* + */ + bool publish(const char *subject, ctx::json option, int error, ctx::json data_updated); + + /* + */ + bool reply_to_read(const char *subject, ctx::json option, int error, ctx::json data_read); + + } /* namespace ctx::context_manager */ +} /* namespace ctx */ + +#endif /* End of __CONTEXT_MANAGER_H__ */ diff --git a/include/context_mgr_iface.h b/include/context_mgr_iface.h new file mode 100644 index 0000000..dd29568 --- /dev/null +++ b/include/context_mgr_iface.h @@ -0,0 +1,41 @@ +/* + * 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 __CONTEXT_MANAGER_INTERFACE_H__ +#define __CONTEXT_MANAGER_INTERFACE_H__ + +namespace ctx { + /* Forward Declaration */ + class json; + class context_provider_iface; + class context_provider_info; + + class context_manager_iface { + public: + virtual ~context_manager_iface() {} + virtual bool register_provider(const char *subject, context_provider_info &provider_info) = 0; + virtual bool register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options) = 0; + virtual bool publish(const char *subject, ctx::json &option, int error, ctx::json &data_updated) = 0; + virtual bool reply_to_read(const char *subject, ctx::json &option, int error, ctx::json &data_read) = 0; + }; /* class context_manager_iface */ + + namespace context_manager { + void set_instance(context_manager_iface* mgr); + } /* namespace ctx::context_manager */ + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_MANAGER_INTERFACE_H__ */ diff --git a/include/db_listener_iface.h b/include/db_listener_iface.h new file mode 100644 index 0000000..625c9fb --- /dev/null +++ b/include/db_listener_iface.h @@ -0,0 +1,56 @@ +/* + * 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 __CONTEXT_DATABASE_LISTENER_INTERFACE_H__ +#define __CONTEXT_DATABASE_LISTENER_INTERFACE_H__ + +#include + +namespace ctx { + /* Forward Declaration */ + class json; + + class db_listener_iface { + public: + virtual ~db_listener_iface() {} + + /** + * @brief Called when a table creation is done. + * @param[in] query_id The query id passed through ctx::db_manager::create_table(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + */ + virtual void on_creation_result_received(unsigned int query_id, int error) = 0; + + /** + * @brief Called when a record insertion is done. + * @param[in] query_id The query id passed through ctx::db_manager::insert(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] row_id The row id of the inserted record. + */ + virtual void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) = 0; + + /** + * @brief Called when a query execution is done. + * @param[in] query_id The query id passed through ctx::db_manager::execute(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] records Data records retreived. + */ + virtual void on_query_result_received(unsigned int query_id, int error, std::vector& records) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_DATABASE_LISTENER_INTERFACE_H__ */ diff --git a/include/db_mgr.h b/include/db_mgr.h new file mode 100644 index 0000000..f2f54be --- /dev/null +++ b/include/db_mgr.h @@ -0,0 +1,79 @@ +/* + * 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 __CONTEXT_DB_MANAGER_H__ +#define __CONTEXT_DB_MANAGER_H__ + +#include +#include +#include + +namespace ctx { + /* Forward Declaration */ + class json; + class db_listener_iface; + + namespace db_manager { + /** + * @brief Create a table if not exists. Async. + * @details The column @c row_id is created by default, thus do not use the same column name. + * It is the primary of the auto-increment integer type. + * @param[in] query_id This number will be returned through db_listener_iface::on_creation_result_received(). + * @param[in] table_name A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + * @param[in] listener A listner object to receive the result. Allows NULL. + */ + bool create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option = NULL, db_listener_iface* listener = NULL); + + /** + * @brief Insert a record to a table. Async. + * @param[in] query_id This number will be returned through db_listener_iface::on_insertion_result_received(). + * @param[in] table_name A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[in] listener A listner object to receive the result. Allows NULL. + */ + bool insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener = NULL); + + /** + * @brief Execute a SQL query. Async. + * @param[in] query_id This number will be returned through db_listener_iface::on_query_result_received(). + * @param[in] query A query to be executed. + * @param[in] listener A listner object to receive the result. + */ + bool execute(unsigned int query_id, const char* query, db_listener_iface* listener); + + /** + * @brief Insert a record to a table. Sync. + * @attention This cannot be used in the main thread. + * @param[in] table_name A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[out] row_id The row id of the inserted record. If fails, a negative integer. + */ + bool insert_sync(const char* table_name, json& record, int64_t* row_id); + + /** + * @brief Execute a SQL query. Sync. + * @attention This cannot be used in the main thread. + * @param[in] query A query to be executed. + * @param[out] records Query result. + */ + bool execute_sync(const char* query, std::vector* records); + + } /* namespace ctx::db_manager */ +} /* namespace ctx */ + +#endif /* __CONTEXT_DB_MANAGER_H__ */ diff --git a/include/db_mgr_iface.h b/include/db_mgr_iface.h new file mode 100644 index 0000000..18e0841 --- /dev/null +++ b/include/db_mgr_iface.h @@ -0,0 +1,42 @@ +/* + * 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 __CONTEXT_DB_MANAGER_INTERFACE_H__ +#define __CONTEXT_DB_MANAGER_INTERFACE_H__ + +#include + +namespace ctx { + /* Forward Declaration */ + class json; + class db_listener_iface; + + class db_manager_iface { + public: + virtual ~db_manager_iface() {} + virtual bool create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option = NULL, db_listener_iface* listener = NULL) = 0; + virtual bool insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener = NULL) = 0; + virtual bool execute(unsigned int query_id, const char* query, db_listener_iface* listener) = 0; + virtual bool insert_sync(const char* table_name, json& record, int64_t* row_id) = 0; + virtual bool execute_sync(const char* query, std::vector* records) = 0; + }; /* class db_manager */ + + namespace db_manager { + void set_instance(db_manager_iface* mgr); + } /* namespace ctx::db_manager */ +} /* namespace ctx */ + +#endif /* __CONTEXT_DB_MANAGER_INTERFACE_H__ */ diff --git a/include/dbus_listener_iface.h b/include/dbus_listener_iface.h new file mode 100644 index 0000000..4f64006 --- /dev/null +++ b/include/dbus_listener_iface.h @@ -0,0 +1,41 @@ +/* + * 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 __CONTEXT_DBUS_LISTENER_INTERFACE_H__ +#define __CONTEXT_DBUS_LISTENER_INTERFACE_H__ + +#include + +namespace ctx { + + class dbus_listener_iface { + public: + virtual ~dbus_listener_iface() {} + + /** + * @brief Called when receiving a signal. + * @param[in] sender The unique bus name of the sender of the signal. + * @param[in] path The object path that the signal was emitted on. + * @param[in] iface The name of the interface. + * @param[in] name The name of the signal. + * @param[in] param A GVariant tuple with parameters of the signal. + */ + virtual void on_signal_received(const char* sender, const char* path, const char* iface, const char* name, GVariant* param) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_DBUS_LISTENER_INTERFACE_H__ */ diff --git a/include/dbus_server.h b/include/dbus_server.h new file mode 100644 index 0000000..009d34e --- /dev/null +++ b/include/dbus_server.h @@ -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. + */ + +#ifndef __CONTEXT_DBUS_SERVER_H__ +#define __CONTEXT_DBUS_SERVER_H__ + +#include + +namespace ctx { + /* Forward Declaration */ + class dbus_listener_iface; + + namespace dbus_server { + /** + * @brief Subscribes to signals. + * @param[in] sender Sensor name to match on. NULL to listen from all senders. + * @param[in] path Object path to match on. NULL to match on all object paths. + * @param[in] iface D-Bus interface name to match on. NULL to match on all interfaces. + * @param[in] name D-Bus signal name to match on. NULL to match on all signals. + * @param[in] listener Listener object to receive matching signals. + * @return A subscription identifier that can be used with signal_unsubscribe().@n + * If failed, a negative value. + */ + int64_t signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener); + + /** + * @brief Unsubscribes from signals. + */ + void signal_unsubscribe(int64_t subscription_id); + + } /* namespace ctx::dbus_server */ +} /* namespace ctx */ + +#endif /* End of __CONTEXT_DBUS_SERVER_H__ */ diff --git a/include/dbus_server_iface.h b/include/dbus_server_iface.h new file mode 100644 index 0000000..6f10940 --- /dev/null +++ b/include/dbus_server_iface.h @@ -0,0 +1,40 @@ +/* + * 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 __CONTEXT_DBUS_SERVER_INTERFACE_H__ +#define __CONTEXT_DBUS_SERVER_INTERFACE_H__ + +#include + +namespace ctx { + /* Forward Declaration */ + class dbus_listener_iface; + + class dbus_server_iface { + public: + virtual ~dbus_server_iface() {} + virtual int64_t signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener) = 0; + virtual void signal_unsubscribe(int64_t subscription_id) = 0; + }; /* class ctx::dbus_server */ + + namespace dbus_server { + void set_instance(dbus_server_iface* svr); + } + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_DBUS_SERVER_INTERFACE_H__ */ + diff --git a/include/event_driven.h b/include/event_driven.h new file mode 100644 index 0000000..00225ce --- /dev/null +++ b/include/event_driven.h @@ -0,0 +1,44 @@ +/* + * 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 _EVENT_DRIVEN_THREAD_H_ +#define _EVENT_DRIVEN_THREAD_H_ + +#include + +class event_driven_thread { + private: + typedef struct thread_info_s* thread_info_t; + thread_info_t thread_info; + + static gpointer thread_func_wrapper(gpointer data); + void process_event_queue(); + virtual void on_thread_event_popped(int type, void* data) = 0; + virtual void delete_thread_event(int type, void* data) = 0; + + protected: + event_driven_thread(); + bool push_thread_event(int type, void* data = NULL); + + public: + virtual ~event_driven_thread(); + bool start(); + bool stop(); + bool is_running(); + +}; /* class event_driven_thread */ + +#endif /* _EVENT_DRIVEN_THREAD_H_ */ diff --git a/include/json.h b/include/json.h new file mode 100644 index 0000000..5c35299 --- /dev/null +++ b/include/json.h @@ -0,0 +1,121 @@ +/* + * 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 __CONTEXT_JSON_H__ +#define __CONTEXT_JSON_H__ + +#include +#include +#include +#include +#include + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while(0) + +#define EMPTY_JSON_OBJECT "{}" +#define DEFAULT_PRECISION 3 + +namespace ctx { + + class json { + private: + typedef struct _JsonNode json_node_t; + json_node_t *json_node; + + void parse(const char* s); + void release(); + + /* For json vs json comparison */ + bool get_member_list(json_node_t* node, std::list& list); + bool node_equals(json_node_t* lhs, json_node_t* rhs); + bool value_equals(json_node_t* lhs, json_node_t* rhs); + bool object_equals(json_node_t* lhs, json_node_t* rhs); + bool array_equals(json_node_t* lhs, json_node_t* rhs); + + 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); + + char* dup_cstr(); + std::string str(); + + bool get_keys(std::list* 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 array_get_size(const char* path, const char* key); + + bool array_append(const char* path, const char* key, json& val); + bool array_append(const char* path, const char* key, int val); + bool array_append(const char* path, const char* key, int64_t val); + bool array_append(const char* path, const char* key, double val, int prec = DEFAULT_PRECISION); + bool array_append(const char* path, const char* key, std::string val); + + bool array_set_at(const char* path, const char* key, int index, json& val); + bool array_set_at(const char* path, const char* key, int index, int val); + bool array_set_at(const char* path, const char* key, int index, int64_t val); + bool array_set_at(const char* path, const char* key, int index, double val, int prec = DEFAULT_PRECISION); + bool array_set_at(const char* path, const char* key, int index, std::string val); + + bool get_array_elem(const char* path, const char* key, int index, json* val); + bool get_array_elem(const char* path, const char* key, int index, int* val); + bool get_array_elem(const char* path, const char* key, int index, int64_t* val); + bool get_array_elem(const char* path, const char* key, int index, double* val); + bool get_array_elem(const char* path, const char* key, int index, std::string* val); + }; + +} /* namespace ctx */ + +#endif // __CONTEXT_JSON_H__ + diff --git a/include/provider_iface.h b/include/provider_iface.h new file mode 100644 index 0000000..f5268b6 --- /dev/null +++ b/include/provider_iface.h @@ -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 __CONTEXT_PROVIDER_INTERFACE_H__ +#define __CONTEXT_PROVIDER_INTERFACE_H__ + +namespace ctx { + + /* Forward Declaration */ + class json; + + class context_provider_iface { + public: + virtual ~context_provider_iface() {} + virtual int subscribe(const char *subject, ctx::json option, ctx::json *request_result); + virtual int unsubscribe(const char *subject, ctx::json option); + virtual int read(const char *subject, ctx::json option, ctx::json *request_result); + virtual int write(const char *subject, ctx::json data, ctx::json *request_result); + + protected: + context_provider_iface() {} + + }; /* class context_provider_iface */ + + class context_provider_info { + typedef context_provider_iface *(*creator_t)(void *data); + typedef void (*destroyer_t)(void *data); + + public: + creator_t create; + destroyer_t destroy; + void *data; + const char *privilege; + + context_provider_info(); + context_provider_info(creator_t cr, destroyer_t des, void *dat = NULL, const char *priv = NULL); + }; + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_PROVIDER_INTERFACE_H__ */ diff --git a/include/request_handler.h b/include/request_handler.h new file mode 100644 index 0000000..a2faffb --- /dev/null +++ b/include/request_handler.h @@ -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 __CONTEXT_LIB_REQUEST_HANDLER_H__ +#define __CONTEXT_LIB_REQUEST_HANDLER_H__ + +#include + +namespace ctx { namespace request_handler { + + /* + */ + typedef void(* subject_response_cb)(const char* subject, int req_id, int error, ctx::json response); + + /* + */ + bool register_callback(const char* subject, subject_response_cb callback); + + /* + */ + int subscribe(const char* subject, ctx::json* option, int* req_id, ctx::json* request_result = NULL); + + /* + */ + int unsubscribe(const char* subject, int req_id); + + /* + */ + int read(const char* subject, ctx::json* option, int* req_id, ctx::json* request_result = NULL); + + /* + */ + int read_sync(const char* subject, ctx::json* option, int* req_id, ctx::json* data_read); + + /* + */ + int write(const char* subject, ctx::json* data); + + /* + */ + int write_with_reply(const char* subject, ctx::json* data, ctx::json* request_result = NULL); + + /* + */ + int is_supported(const char* subject); + +} } /* namespace ctx::request_handler */ + +#endif // __CONTEXT_LIB_REQUEST_HANDLER_H__ diff --git a/include/scope_mutex.h b/include/scope_mutex.h new file mode 100644 index 0000000..17c8cf5 --- /dev/null +++ b/include/scope_mutex.h @@ -0,0 +1,37 @@ +/* + * 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 __CONTEXT_SCOPE_MUTEX_H__ +#define __CONTEXT_SCOPE_MUTEX_H__ + +#include +#include + +namespace ctx { + // RAII Class implementing the mutex helper on the base of GLib mutex, + // which automatically locks mutex during its creation and unlocks while exiting the scope. + class scope_mutex + { + private: + GMutex *mutex; + + public: + scope_mutex(GMutex *m); + ~scope_mutex(); + }; +} /* namespace ctx */ + +#endif // __CONTEXT_SCOPE_MUTEX_H__ diff --git a/include/shared_vars.h b/include/shared_vars.h new file mode 100644 index 0000000..a5bb371 --- /dev/null +++ b/include/shared_vars.h @@ -0,0 +1,28 @@ +/* + * 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 __CONTEXT_SHARED_VARS_H__ +#define __CONTEXT_SHARED_VARS_H__ + +#include + +namespace ctx { + namespace shared { + extern std::string wifi_bssid; + } +} + +#endif diff --git a/include/timer_listener_iface.h b/include/timer_listener_iface.h new file mode 100644 index 0000000..df11a92 --- /dev/null +++ b/include/timer_listener_iface.h @@ -0,0 +1,37 @@ +/* + * 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 __CONTEXT_TIMER_LISTENER_INTERFACE_H__ +#define __CONTEXT_TIMER_LISTENER_INTERFACE_H__ + +namespace ctx { + + class timer_listener_iface { + public: + virtual ~timer_listener_iface() {} + + /** + * @brief Called when a timer is expired. + * @param[in] timer_id The expired timers' ID + * @return @c true, if the timer needs to be repeated.@n + * @c false, if the timer does not need to be repeated anymore. + */ + virtual bool on_timer_expired(int timer_id, void* user_data) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of __CONTEXT_TIMER_LISTENER_INTERFACE_H__ */ diff --git a/include/timer_mgr.h b/include/timer_mgr.h new file mode 100644 index 0000000..732cfdf --- /dev/null +++ b/include/timer_mgr.h @@ -0,0 +1,69 @@ +/* + * 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 __CONTEXT_TIMER_MANAGER_H__ +#define __CONTEXT_TIMER_MANAGER_H__ + +namespace ctx { + /* Forward Declaration */ + class timer_listener_iface; + + namespace timer_manager { + + enum day_of_week_e { + SUN = 0x01, + MON = 0x02, + TUE = 0x04, + WED = 0x08, + THU = 0x10, + FRI = 0x20, + SAT = 0x40, + WEEKDAY = MON | TUE | WED | THU | FRI, + WEEKEND = SAT | SUN, + EVERYDAY = SUN | MON | TUE | WED | THU | FRI | SAT, + }; + + /** + * @brief Sets a repeated timer for a given interval of time (s). + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] interval Timer interval. The first timer will be expired after @c interval minutes, + * and will be repeated until the listener returns @c false. + * @param[in] listener A listner object to be notified. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int set_for(int interval, timer_listener_iface* listener, void* user_data = NULL); + + /** + * @brief Sets a timer that will be expired at a specific time, at designated days of week. + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] hour Hour + * @param[in] min Minute + * @param[in] day_of_week The timer will expire at hour:min:00, at every day(s) of week designated here. + * @param[in] listener Listener object. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int set_at(int hour, int min, int day_of_week, timer_listener_iface* listener, void* user_data = NULL); + + /** + * @brief Removes the timer specified by @c timer_id. + */ + void remove(int timer_id); + } +} /* namespace ctx */ + +#endif /* __CONTEXT_TIMER_MANAGER_H__ */ diff --git a/include/timer_mgr_iface.h b/include/timer_mgr_iface.h new file mode 100644 index 0000000..ac59921 --- /dev/null +++ b/include/timer_mgr_iface.h @@ -0,0 +1,56 @@ +/* + * 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 __CONTEXT_TIMER_MANAGER_INTERFACE_H__ +#define __CONTEXT_TIMER_MANAGER_INTERFACE_H__ + +namespace ctx { + /* Forward Declaration */ + class timer_listener_iface; + + class timer_manager_iface { + public: + virtual ~timer_manager_iface() {} + + /** + * @brief Sets a timer notifying at every @c interval minutes. + * @param[in] interval Repeating interval. Seconds. + * @param[in] listener Listener object. + * @return A timer identifier that can be used to distinguish timers. + * The same ID will be delivered whenever the timer is expired. + */ + virtual int set_for(int interval, timer_listener_iface* listener, void* user_data) = 0; + + /** + * @brief Sets a timer notifying at specific time at every days of week designated. + * @param[in] hour Hour + * @param[in] min Minute + * @param[in] day_of_week The timer will expire at hour:min:00, at every day(s) of week designated here. + * @param[in] listener Listener object. + * @return A timer identifier that can be used to distinguish timers. + * The same ID will be delivered whenever the timer is expired. + */ + virtual int set_at(int hour, int min, int day_of_week, timer_listener_iface* listener, void* user_data) = 0; + + virtual void remove(int timer_id) = 0; + }; + + namespace timer_manager { + void set_instance(timer_manager_iface* mgr); + } +} /* namespace ctx */ + +#endif /* __CONTEXT_TIMER_MANAGER_INTERFACE_H__ */ diff --git a/include/types_internal.h b/include/types_internal.h new file mode 100644 index 0000000..49f928c --- /dev/null +++ b/include/types_internal.h @@ -0,0 +1,124 @@ +/* + * 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 __CONTEXT_TYPES_INTERNAL_H__ +#define __CONTEXT_TYPES_INTERNAL_H__ + +#include +#include + +#define EXTAPI __attribute__ ((visibility("default"))) +#define EMPTY_STRING "" + +/* Internal Error Codes + * Please define the necessary error codes here. + * Note that, these error codes must be aligned with the error enums defined in all API headers. + */ +#define ERR_NONE TIZEN_ERROR_NONE +#define ERR_INVALID_PARAMETER TIZEN_ERROR_INVALID_PARAMETER +#define ERR_INVALID_OPERATION TIZEN_ERROR_INVALID_OPERATION +#define ERR_OUT_OF_MEMORY TIZEN_ERROR_OUT_OF_MEMORY +#define ERR_PERMISSION_DENIED TIZEN_ERROR_PERMISSION_DENIED +#define ERR_NOT_SUPPORTED TIZEN_ERROR_NOT_SUPPORTED +#define ERR_NO_DATA TIZEN_ERROR_NO_DATA +#define ERR_ALREADY_STARTED (TIZEN_ERROR_CONTEXT | 0x01) +#define ERR_NOT_STARTED (TIZEN_ERROR_CONTEXT | 0x02) +#define ERR_OUT_OF_RANGE (TIZEN_ERROR_CONTEXT | 0x03) +#define ERR_OPERATION_FAILED (TIZEN_ERROR_CONTEXT | 0x04) +#define ERR_RULE_ENABLED (TIZEN_ERROR_CONTEXT | 0x05) +#define ERR_RULE_NOT_ENABLED (TIZEN_ERROR_CONTEXT | 0x06) +#define ERR_INVALID_RULE (TIZEN_ERROR_CONTEXT | 0x07) +#define ERR_RULE_NOT_EXIST (TIZEN_ERROR_CONTEXT | 0x08) + +/* Logging and Error Handling */ +#define _I SLOGI +#define _D SLOGD +#define _W SLOGW +#define _E SLOGE +#define _SI SECURE_SLOGI +#define _SD SECURE_SLOGD +#define _SW SECURE_LOGW +#define _SE SECURE_SLOGE + +/* 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) + + +/* DBus */ +#define DBUS_DEST "org.tizen.context" +#define DBUS_PATH "/org/tizen/context" +#define DBUS_IFACE "org.tizen.context" +#define DBUS_TIMEOUT 3000000 + +#define METHOD_REQUEST "Request" +#define METHOD_RESPOND "Respond" +#define SIGNAL_LAUNCHED "Launched" + +enum request_type { + REQ_SUBSCRIBE = 1, + REQ_UNSUBSCRIBE, + REQ_READ, + REQ_READ_SYNC, + REQ_WRITE, + REQ_SUPPORT, +}; + +#define ARG_REQTYPE "type" +#define ARG_COOKIE "cookie" +#define ARG_REQID "req_id" +#define ARG_SUBJECT "subject" +#define ARG_INPUT "input" + +#define ARG_RESULT_ERR "r_err" +#define ARG_RESULT_ADD "r_add" +#define ARG_OUTPUT "output" + + +#endif /* __CONTEXT_TYPES_INTERNAL_H__ */ diff --git a/packaging/context-common.manifest b/packaging/context-common.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/context-common.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/context-common.spec b/packaging/context-common.spec new file mode 100644 index 0000000..48814fd --- /dev/null +++ b/packaging/context-common.spec @@ -0,0 +1,72 @@ +Name: context-common +Summary: Context-Service Shared Library +Version: 0.6.2 +Release: 1 +Group: System/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(security-server) + +%description +Context-Service Shared Library + +%prep +%setup -q + +%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" + +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} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files +%manifest packaging/%{name}.manifest +%defattr(-,root,root,-) +%{_libdir}/*.so* +/usr/share/license/%{name} + +%package devel +Summary: Context-Service Shared Library (Development) +Group: System/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Context-Service Shared Library (DEV) + +%files devel +%defattr(-,root,root,-) +%{_includedir}/context-service/internal/*.h +%{_libdir}/pkgconfig/%{name}.pc diff --git a/src/context_mgr.cpp b/src/context_mgr.cpp new file mode 100644 index 0000000..1bf2b2d --- /dev/null +++ b/src/context_mgr.cpp @@ -0,0 +1,52 @@ +/* + * 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 +#include +#include +#include +#include + +static ctx::context_manager_iface *_instance = NULL; + +void ctx::context_manager::set_instance(context_manager_iface* mgr) +{ + _instance = mgr; +} + +bool ctx::context_manager::register_provider(const char* subject, ctx::context_provider_info &provider_info) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->register_provider(subject, provider_info); +} + +bool ctx::context_manager::register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->register_trigger_item(subject, operation, attributes, options); +} + +bool ctx::context_manager::publish(const char* subject, ctx::json option, int error, ctx::json data_updated) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->publish(subject, option, error, data_updated); +} + +bool ctx::context_manager::reply_to_read(const char* subject, ctx::json option, int error, ctx::json data_read) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->reply_to_read(subject, option, error, data_read); +} diff --git a/src/db_mgr.cpp b/src/db_mgr.cpp new file mode 100644 index 0000000..12a0211 --- /dev/null +++ b/src/db_mgr.cpp @@ -0,0 +1,58 @@ +/* + * 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 +#include +#include +#include +#include + +static ctx::db_manager_iface *_instance = NULL; + +void ctx::db_manager::set_instance(ctx::db_manager_iface* mgr) +{ + _instance = mgr; +} + +bool ctx::db_manager::create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->create_table(query_id, table_name, columns, option, listener); +} + +bool ctx::db_manager::insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->insert(query_id, table_name, record, listener); +} + +bool ctx::db_manager::execute(unsigned int query_id, const char* query, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->execute(query_id, query, listener); +} + +bool ctx::db_manager::insert_sync(const char* table_name, json& record, int64_t* row_id) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->insert_sync(table_name, record, row_id); +} + +bool ctx::db_manager::execute_sync(const char* query, std::vector* records) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->execute_sync(query, records); +} diff --git a/src/dbus_client.cpp b/src/dbus_client.cpp new file mode 100644 index 0000000..c3c183c --- /dev/null +++ b/src/dbus_client.cpp @@ -0,0 +1,228 @@ +/* + * 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 +#include +#include + +#include +#include +#include "response_handler.h" +#include "dbus_client.h" + +static GDBusConnection *dbus_connection = NULL; +static GDBusNodeInfo *dbus_node_info = NULL; + +static const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static const char* get_security_cookie() +{ + static char *cookie = NULL; + static GMutex cookie_mutex; + ctx::scope_mutex sm(&cookie_mutex); + + if (cookie == NULL) { + int raw_size = security_server_get_cookie_size(); + IF_FAIL_RETURN_TAG(raw_size > 0, NULL, _E, "Invalid cookie size"); + + int ret; + char raw_cookie[raw_size]; + + ret = security_server_request_cookie(raw_cookie, raw_size); + IF_FAIL_RETURN_TAG(ret >= 0, NULL, _E, "Failed to get the security cookie"); + + cookie = g_base64_encode(reinterpret_cast(raw_cookie), raw_size); + IF_FAIL_RETURN_TAG(cookie, NULL, _E, "Failed to encode the cookie"); + } + + return cookie; +} + +static void handle_response(const gchar *sender, GVariant *param, GDBusMethodInvocation *invocation) +{ + gint req_id = 0; + const gchar *subject = NULL; + gint error = 0; + const gchar *data = NULL; + + g_variant_get(param, "(i&si&s)", &req_id, &subject, &error, &data); + _D("[Response] ReqId: %d, Subject: %s, Error: %d", req_id, subject, error); + + ctx::response_handler::deliver(subject, req_id, error, data); + g_dbus_method_invocation_return_value(invocation, NULL); +} + +static void handle_method_call(GDBusConnection *conn, const gchar *sender, + const gchar *obj_path, const gchar *iface, const gchar *method_name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + IF_FAIL_VOID_TAG(STR_EQ(obj_path, DBUS_PATH), _W, "Invalid path: %s", obj_path); + IF_FAIL_VOID_TAG(STR_EQ(iface, DBUS_IFACE), _W, "Invalid interface: %s", obj_path); + + if (STR_EQ(method_name, METHOD_RESPOND)) { + handle_response(sender, param, invocation); + } else { + _W("Invalid method: %s", method_name); + } +} + +ctx::dbus_client::dbus_client() +{ +} + +ctx::dbus_client::~dbus_client() +{ + release(); +} + +bool ctx::dbus_client::init() +{ + static GMutex connection_mutex; + ctx::scope_mutex sm(&connection_mutex); + + if (dbus_connection) { + return true; + } + + GError *gerr = NULL; + + dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL); + IF_FAIL_RETURN_TAG(dbus_node_info != NULL, false, _E, "Initialization failed"); + + gchar *addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(addr != NULL, false, _E, "Getting address failed"); + _SD("Address: %s", addr); + + dbus_connection = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(dbus_connection != NULL, false, _E, "Connection failed"); + + GDBusInterfaceVTable vtable; + vtable.method_call = handle_method_call; + vtable.get_property = NULL; + vtable.set_property = NULL; + + guint reg_id = g_dbus_connection_register_object(dbus_connection, DBUS_PATH, + dbus_node_info->interfaces[0], &vtable, NULL, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(reg_id>0, false, _E, "Object registration failed"); + + _I("Dbus connection established: %s", g_dbus_connection_get_unique_name(dbus_connection)); + return true; +} + +void ctx::dbus_client::release() +{ + if (dbus_connection) { + g_dbus_connection_flush_sync(dbus_connection, NULL, NULL); + g_dbus_connection_close_sync(dbus_connection, NULL, NULL); + g_object_unref(dbus_connection); + dbus_connection = NULL; + } + + if (dbus_node_info) { + g_dbus_node_info_unref(dbus_node_info); + dbus_node_info = NULL; + } +} + +int ctx::dbus_client::request( + int type, int req_id, const char* subject, const char* input, + std::string* req_result, std::string* data_read) +{ + _D("Requesting: %d, %d, %s", type, req_id, subject); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + const char *cookie = get_security_cookie(); + IF_FAIL_RETURN_TAG(cookie, ERR_OPERATION_FAILED, _E, "Cookie generation failed"); + + GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + GVariant *response = g_dbus_connection_call_sync(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + HANDLE_GERROR(err); + IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed"); + + gint _error = ERR_OPERATION_FAILED; + const gchar *_req_result = NULL; + const gchar *_data_read = NULL; + + g_variant_get(response, "(i&s&s)", &_error, &_req_result, &_data_read); + if (req_result) { + *req_result = _req_result; + } + if (data_read) { + *data_read = _data_read; + } + + g_variant_unref(response); + + return _error; +} + +int ctx::dbus_client::request_with_no_reply( + int type, int req_id, const char* subject, const char* input) +{ + _D("Requesting: %d, %d, %s", type, req_id, subject); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + const char *cookie = get_security_cookie(); + IF_FAIL_RETURN_TAG(cookie, ERR_OPERATION_FAILED, _E, "Cookie generation failed"); + + GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + g_dbus_connection_call(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err); + + if (err) { + HANDLE_GERROR(err); + return ERR_OPERATION_FAILED; + } + + return ERR_NONE; +} diff --git a/src/dbus_client.h b/src/dbus_client.h new file mode 100644 index 0000000..9707f3d --- /dev/null +++ b/src/dbus_client.h @@ -0,0 +1,39 @@ +/* + * 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 __CONTEXT_LIB_DBUS_HANDLER_H__ +#define __CONTEXT_LIB_DBUS_HANDLER_H__ + +#include + +namespace ctx { + + class dbus_client { + public: + dbus_client(); + ~dbus_client(); + + bool init(); + void release(); + + int request(int type, int req_id, const char* subject, const char* input, std::string* req_result, std::string* data_read); + int request_with_no_reply(int type, int req_id, const char* subject, const char* input); + + }; /* classs ctx::dbus_client */ + +} /* namespace ctx */ + +#endif // __CONTEXT_LIB_DBUS_HANDLER_H__ diff --git a/src/dbus_server.cpp b/src/dbus_server.cpp new file mode 100644 index 0000000..9f0b927 --- /dev/null +++ b/src/dbus_server.cpp @@ -0,0 +1,40 @@ +/* + * 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 +#include +#include +#include +#include + +static ctx::dbus_server_iface *_instance = NULL; + +void ctx::dbus_server::set_instance(dbus_server_iface* svr) +{ + _instance = svr; +} + +int64_t ctx::dbus_server::signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->signal_subscribe(sender, path, iface, name, listener); +} + +void ctx::dbus_server::signal_unsubscribe(int64_t subscription_id) +{ + IF_FAIL_VOID_TAG(_instance, _E, "Not initialized"); + _instance->signal_unsubscribe(subscription_id); +} diff --git a/src/event_driven.cpp b/src/event_driven.cpp new file mode 100644 index 0000000..2a383d6 --- /dev/null +++ b/src/event_driven.cpp @@ -0,0 +1,193 @@ +/* + * 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 +#include +#include + +struct thread_info_s { + GThread *thread; + gint is_running; + GAsyncQueue *event_queue; +}; + +struct event_message_s { + int type; + void* data; + bool is_stop_signal; + event_message_s() : type(-1), data(NULL), is_stop_signal(false) {} +}; + +event_driven_thread::event_driven_thread() +{ + thread_info = static_cast(g_malloc(sizeof(thread_info_s))); + + if (thread_info) { + thread_info->thread = NULL; + thread_info->is_running = 0; + thread_info->event_queue = NULL; + } +} + +event_driven_thread::~event_driven_thread() +{ + stop(); + g_free(thread_info); +} + +bool event_driven_thread::start() +{ + IF_FAIL_RETURN_TAG(thread_info, false, _E, "Memory allocation failed"); + + if (!g_atomic_int_get(&(thread_info->is_running))) { + +#if 0 + int stack_size = sysconf(_SC_PAGESIZE) * 4; + void *stack = NULL; + stack = g_malloc(stack_size); + IF_FAIL_RETURN_TAG(stack, false, _E, "Memory allocation failed"); +#endif + + thread_info->event_queue = g_async_queue_new(); + if (thread_info->event_queue == NULL) { + _E("Memory allocation failed"); + return false; + } + + g_atomic_int_set(&thread_info->is_running, 1); + +#if 0 + thread_info->pid = clone(&thread_func_wrapper, (char*)stack + stack_size, + SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM, this); + + if (thread_info->pid < 0) { + _E(RED("Thread creation failed")); + g_atomic_int_set(&thread_info->is_running, 0); + g_free(stack); + g_async_queue_unref(thread_info->event_queue); + return false; + } + + _I(PURPLE("PID %d initiated"), thread_info->pid); +#endif + + thread_info->thread = g_thread_new(NULL, thread_func_wrapper, static_cast(this)); + + if (thread_info->thread == NULL) { + _E(RED("Thread creation failed")); + g_atomic_int_set(&thread_info->is_running, 0); + g_async_queue_unref(thread_info->event_queue); + return false; + } + + _I(PURPLE("A thread initiated")); + } + + return true; +} + +bool event_driven_thread::stop() +{ + if (g_atomic_int_get(&(thread_info->is_running))) { + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->is_stop_signal = true; + g_async_queue_push(thread_info->event_queue, event); + g_atomic_int_set(&thread_info->is_running, 0); + +#if 0 + pid_t pid = waitpid(thread_info->pid, NULL, 0); + _I(PURPLE("PID %d terminated"), pid); + if (pid < 0) { + _E(RED("Failed to join %d from %d"), thread_info->pid, getpid()); + } +#endif + g_thread_join(thread_info->thread); + + // Free the memory allocated for the event queue + while ((event = static_cast(g_async_queue_try_pop(thread_info->event_queue)))) { + if (event->data) { + delete_thread_event(event->type, event->data); + } + delete event; + } + g_async_queue_unref(thread_info->event_queue); + } + + return true; +} + +bool event_driven_thread::is_running() +{ + if (g_atomic_int_get(&(thread_info->is_running))) { + return true; + } + return false; +} + +bool event_driven_thread::push_thread_event(int type, void* data) +{ + if (g_atomic_int_get(&(thread_info->is_running))) { + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->type = type; + event->data = data; + g_async_queue_push(thread_info->event_queue, event); + return true; + } + + return false; +} + +gpointer event_driven_thread::thread_func_wrapper(gpointer data) +{ + static_cast(data)->process_event_queue(); + return NULL; +} + +void event_driven_thread::process_event_queue() +{ +#if 0 + struct sigaction signal_action; + signal_action.sa_handler = child_signal_handler; + sigemptyset(&signal_action.sa_mask); + + sigaction(SIGINT, &signal_action, NULL); + sigaction(SIGHUP, &signal_action, NULL); + sigaction(SIGTERM, &signal_action, NULL); + sigaction(SIGQUIT, &signal_action, NULL); +#endif + + event_message_s *event = NULL; + + while (g_atomic_int_get(&(thread_info->is_running))) { + + event = static_cast(g_async_queue_pop(thread_info->event_queue)); + + if (event) { + if (event->is_stop_signal){ + delete event; + break; + } else { + on_thread_event_popped(event->type, event->data); + delete event; + } + } + + } +} diff --git a/src/json.cpp b/src/json.cpp new file mode 100644 index 0000000..13fa761 --- /dev/null +++ b/src/json.cpp @@ -0,0 +1,951 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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(); +} + +ctx::json::json() +{ + JsonObject *obj = json_object_new(); + IF_FAIL_VOID_TAG(obj, _E, "Json object construction failed"); + + json_node = json_node_new(JSON_NODE_OBJECT); + if (!json_node) { + json_object_unref(obj); + _E("Json object construction failed"); + } + + json_node_set_object(json_node, obj); + json_object_unref(obj); +} + +ctx::json::json(const json& j) +{ + json_node = json_node_copy(j.json_node); + IF_FAIL_VOID_TAG(json_node, _E, "Json object construction failed"); +} + +ctx::json::json(const char* s) +{ + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } +} + +ctx::json::json(const std::string& s) +{ + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } +} + +ctx::json::~json() +{ + release(); +} + +void ctx::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"); + + json_node = json_node_copy(root); + IF_FAIL_CATCH_TAG(json_node, _E, "Copying failed"); + +CATCH: + if (parser) + g_object_unref(parser); +} + +void ctx::json::release() +{ + if (json_node) { + json_node_free(json_node); + json_node = NULL; + } +} + +ctx::json& ctx::json::operator=(const json& j) +{ + release(); + json_node = json_node_copy(j.json_node); + if (!json_node) { + _E("Json object copy failed"); + } + return *this; +} + +ctx::json& ctx::json::operator=(const char* s) +{ + release(); + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } + return *this; +} + +ctx::json& ctx::json::operator=(const std::string& s) +{ + release(); + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } + return *this; +} + +bool ctx::json::operator==(const json& rhs) +{ + return node_equals(json_node, rhs.json_node); +} + +bool ctx::json::operator!=(const json& rhs) +{ + return !operator==(rhs); +} + +/* TODO +bool ctx::json::contains(const json& subset) const +{ + return false; +} +*/ + +char* ctx::json::dup_cstr() +{ + IF_FAIL_RETURN_TAG(json_node, 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, json_node); + 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 ctx::json::str() +{ + std::string output; + char *_s = dup_cstr(); + 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(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(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; jjson_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.json_node, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, 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.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool ctx::json::set(const char* path, const char* key, int val) +{ + return set(path, key, static_cast(val)); +} + +bool ctx::json::set(const char* path, const char* key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, 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 ctx::json::set(const char* path, const char* key, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, 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 ctx::json::set(const char* path, const char* key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, 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 ctx::json::set(const char* path, const char* key, GVariant *val) +{ + IF_FAIL_RETURN_TAG(this->json_node, 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.json_node), GVAR_VALUES, node); + + return set(path, key, gvar_json); +} + +bool ctx::json::get(const char* path, const char* key, json* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonObject *jobj = NULL; + JsonNode *node = NULL; + + jobj = traverse(json_node, 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->json_node) { + json_node_free(val->json_node); + } + val->json_node = 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 ctx::json::get(const char* path, const char* key, int* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, 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 ctx::json::get(const char* path, const char* key, int64_t* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, 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(string_to_double(json_node_get_string(node))); + } else { + return false; + } + + return true; +} + +bool ctx::json::get(const char* path, const char* key, double* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, 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 ctx::json::get(const char* path, const char* key, std::string* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, 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 ctx::json::get(const char* path, const char* key, GVariant **val) +{ + IF_FAIL_RETURN_TAG(this->json_node, 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.json_node, 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 ctx::json::array_get_size(const char* path, const char* key) +{ + IF_FAIL_RETURN_TAG(this->json_node, -1, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, -1, _E, "Invalid parameter"); + + JsonArray *jarr = search_array(json_node, path, key, false); + IF_FAIL_RETURN_TAG(jarr, -1, _D, "Mismatched data type"); + + return json_array_get_length(jarr); +} + +bool ctx::json::array_append(const char* path, const char* key, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.json_node, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_element(arr, val.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool ctx::json::array_append(const char* path, const char* key, int val) +{ + return array_append(path, key, static_cast(val)); +} + +bool ctx::json::array_append(const char* path, const char* key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_int_element(arr, val); + return true; +} + +bool ctx::json::array_append(const char* path, const char* key, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, 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 ctx::json::array_append(const char* path, const char* key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, 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 ctx::json::array_set_at(const char* path, const char* key, int index, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(val.json_node && key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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_OBJECT, false, _E, "Type mismatched: %s[%d]", key, index); + + JsonObject *obj = json_node_get_object(val.json_node); + IF_FAIL_RETURN_TAG(obj, false, _E, "Getting object failed"); + + json_node_set_object(node, obj); + json_node_free(val.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool ctx::json::array_set_at(const char* path, const char* key, int index, int val) +{ + return array_set_at(path, key, index, static_cast(val)); +} + +bool ctx::json::array_set_at(const char* path, const char* key, int index, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_INT64, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_int(node, val); + return true; +} + +bool ctx::json::array_set_at(const char* path, const char* key, int index, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_STRING, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, double_to_string(val, prec).c_str()); + return true; +} + +bool ctx::json::array_set_at(const char* path, const char* key, int index, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_STRING, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, val.c_str()); + return true; +} + +bool ctx::json::get_array_elem(const char* path, const char* key, int index, json* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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->json_node) { + json_node_free(val->json_node); + } + val->json_node = node_copy; + + return true; +} + +bool ctx::json::get_array_elem(const char* path, const char* key, int index, int* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + int64_t v; + if (get_array_elem(path, key, index, &v)) { + *val = v; + return true; + } + + return false; +} + +bool ctx::json::get_array_elem(const char* path, const char* key, int index, int64_t* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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(string_to_double(json_node_get_string(node))); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +bool ctx::json::get_array_elem(const char* path, const char* key, int index, double* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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 ctx::json::get_array_elem(const char* path, const char* key, int index, std::string* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, 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 ctx::json::get_member_list(json_node_t* node, std::list& 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(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 ctx::json::get_keys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return get_member_list(json_node, *list); +} + +bool ctx::json::node_equals(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(value_equals(lhs, rhs), false); + break; + case JSON_NODE_OBJECT: + IF_FAIL_RETURN(object_equals(lhs, rhs), false); + break; + case JSON_NODE_ARRAY: + IF_FAIL_RETURN(array_equals(lhs, rhs), false); + break; + default: + _W("Unsupported type"); + return false; + } + + return true; +} + +bool ctx::json::value_equals(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 ctx::json::object_equals(json_node_t* lhs, json_node_t* rhs) +{ + std::list lm, rm; + IF_FAIL_RETURN(get_member_list(lhs, lm), false); + IF_FAIL_RETURN(get_member_list(rhs, rm), false); + IF_FAIL_RETURN(lm.size() == rm.size(), false); + + lm.sort(); + rm.sort(); + + std::list::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(node_equals(lhs_child, rhs_child), false); + + ++lit; + ++rit; + } + + return true; +} + +bool ctx::json::array_equals(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(json_array_get_length(rarr)), false); + + for (int i=0; i +#include +#include + +int ctx::context_provider_iface::subscribe(const char *subject, ctx::json option, ctx::json *request_result) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::context_provider_iface::unsubscribe(const char *subject, ctx::json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::context_provider_iface::read(const char *subject, ctx::json option, ctx::json *request_result) +{ + return ERR_NOT_SUPPORTED; +} + +int ctx::context_provider_iface::write(const char *subject, ctx::json data, ctx::json *request_result) +{ + return ERR_NOT_SUPPORTED; +} + +ctx::context_provider_info::context_provider_info() + : create(NULL) + , destroy(NULL) + , data(NULL) + , privilege(NULL) +{ +} + +ctx::context_provider_info::context_provider_info( + ctx::context_provider_info::creator_t cr, + ctx::context_provider_info::destroyer_t des, void *dat, const char *priv) + : create(cr) + , destroy(des) + , data(dat) + , privilege(priv) +{ +} diff --git a/src/request_handler.cpp b/src/request_handler.cpp new file mode 100644 index 0000000..8cd061b --- /dev/null +++ b/src/request_handler.cpp @@ -0,0 +1,257 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include "response_handler.h" +#include "dbus_client.h" + +typedef std::map response_cb_map_t; + +static ctx::dbus_client *dbus_handle = NULL; +static response_cb_map_t *response_cb_map = NULL; + +namespace { + class exit_handler { + public: + exit_handler() {} + ~exit_handler() { delete dbus_handle; } + }; +} /* namespace ctx */ + +static exit_handler _exit_handler; + +static int generate_req_id() +{ + static GMutex rid_mutex; + static int req_id = 0; + + ctx::scope_mutex sm(&rid_mutex); + + // Overflow handling + if (++req_id < 0) { + req_id = 1; + } + + return req_id; +} + +static bool initialize() +{ + static GMutex init_mutex; + ctx::scope_mutex sm(&init_mutex); + + if (dbus_handle) { + return true; + } + + response_cb_map = new(std::nothrow) response_cb_map_t; + IF_FAIL_CATCH_TAG(response_cb_map, _E, "Memory allocation failed"); + + dbus_handle = new(std::nothrow) ctx::dbus_client(); + IF_FAIL_CATCH_TAG(dbus_handle, _E, "Memory allocation failed"); + IF_FAIL_CATCH_TAG(dbus_handle->init(), _E, "Dbus initialization failed"); + + return true; + +CATCH: + delete dbus_handle; + delete response_cb_map; + dbus_handle = NULL; + response_cb_map = NULL; + return false; +} + +int ctx::request_handler::subscribe(const char* subject, ctx::json* option, int* req_id, ctx::json* request_result) +{ + ASSERT_NOT_NULL(subject); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), ERR_OPERATION_FAILED, _E, "Connection failed"); + + *req_id = generate_req_id(); + + char *opt_str = NULL; + if (option) { + opt_str = option->dup_cstr(); + IF_FAIL_RETURN_TAG(opt_str, ERR_OPERATION_FAILED, _E, "Json string creation failed"); + } + + _I("[Subscribe] ReqId: %d, Subject: %s", *req_id, subject); + + std::string result_str; + int error = dbus_handle->request(REQ_SUBSCRIBE, *req_id, subject, opt_str, &result_str, NULL); + g_free(opt_str); + + if (request_result) { + *request_result = result_str; + } + + _D("Error: %#x", error); + _SD("Result: %s", result_str.c_str()); + + return error; +} + +int ctx::request_handler::unsubscribe(const char* subject, int req_id) +{ + ASSERT_NOT_NULL(subject); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + _I("[Unsubscribe] ReqId: %d, Subject: %s", req_id, subject); + return dbus_handle->request(REQ_UNSUBSCRIBE, req_id, subject, NULL, NULL, NULL); +} + +int ctx::request_handler::read(const char* subject, ctx::json* option, int* req_id, ctx::json* request_result) +{ + ASSERT_NOT_NULL(subject); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + + char *opt_str = NULL; + if (option) { + opt_str = option->dup_cstr(); + IF_FAIL_RETURN_TAG(opt_str, ERR_OPERATION_FAILED, _E, "Json string creation failed"); + } + + _I("[Read] ReqId: %d, Subject: %s", *req_id, subject); + + std::string result_str; + int error = dbus_handle->request(REQ_READ, *req_id, subject, opt_str, &result_str, NULL); + g_free(opt_str); + + if (request_result) { + *request_result = result_str; + } + + _D("Error: %#x", error); + _SD("Result: %s", result_str.c_str()); + + return error; +} + +int ctx::request_handler::read_sync(const char* subject, ctx::json* option, int* req_id, ctx::json* data_read) +{ + ASSERT_NOT_NULL(subject); + ASSERT_NOT_NULL(req_id); + ASSERT_NOT_NULL(data_read); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + + char *opt_str = NULL; + if (option) { + opt_str = option->dup_cstr(); + IF_FAIL_RETURN_TAG(opt_str, ERR_OPERATION_FAILED, _E, "Json string creation failed"); + } + + _I("[ReadSync] ReqId: %d, Subject: %s", *req_id, subject); + + std::string data_str; + int error = dbus_handle->request(REQ_READ_SYNC, *req_id, subject, opt_str, NULL, &data_str); + g_free(opt_str); + + *data_read = data_str; + + _D("Error: %#x", error); + _SD("Data: %s", data_str.c_str()); + + return error; +} + +int ctx::request_handler::write(const char* subject, ctx::json* data) +{ + ASSERT_NOT_NULL(subject); + ASSERT_NOT_NULL(data); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + int req_id = generate_req_id(); + char *data_str = data->dup_cstr(); + IF_FAIL_RETURN_TAG(data_str, ERR_OPERATION_FAILED, _E, "Json string creation failed"); + + _I("[Write] ReqId: %d, Subject: %s", req_id, subject); + _SD("Data: %s", data_str); + + int error = dbus_handle->request_with_no_reply(REQ_WRITE, req_id, subject, data_str); + g_free(data_str); + + _D("Error: %#x", error); + + return error; +} + +int ctx::request_handler::write_with_reply(const char* subject, ctx::json* data, ctx::json* request_result) +{ + ASSERT_NOT_NULL(subject); + ASSERT_NOT_NULL(data); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + int req_id = generate_req_id(); + char *data_str = data->dup_cstr(); + IF_FAIL_RETURN_TAG(data_str, ERR_OPERATION_FAILED, _E, "Json string creation failed"); + + _I("[Write with reply] ReqId: %d, Subject: %s", req_id, subject); + _SD("Data: %s", data_str); + + std::string result_str; + int error = dbus_handle->request(REQ_WRITE, req_id, subject, data_str, &result_str, NULL); + g_free(data_str); + + if (request_result) { + *request_result = result_str; + } + + _D("Error: %#x", error); + _SD("Result: %s", result_str.c_str()); + + return error; +} + +int ctx::request_handler::is_supported(const char* subject) +{ + ASSERT_NOT_NULL(subject); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + return dbus_handle->request(REQ_SUPPORT, generate_req_id(), subject, NULL, NULL, NULL); +} + +bool ctx::request_handler::register_callback(const char* subject, subject_response_cb callback) +{ + IF_FAIL_RETURN_TAG(subject && callback, false, _E, "Invalid parameter"); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + _D("Registering callback for subject '%s'", subject); + + static GMutex cb_list_mutex; + ctx::scope_mutex sm(&cb_list_mutex); + + (*response_cb_map)[subject] = callback; + + return true; +} + +void ctx::response_handler::deliver(const char* subject, int req_id, int error, const char* data) +{ + response_cb_map_t::iterator it = response_cb_map->find(subject); + IF_FAIL_VOID_TAG(it != response_cb_map->end(), _E, "Unknown subject '%s'", subject); + + it->second(subject, req_id, error, data); +} diff --git a/src/response_handler.h b/src/response_handler.h new file mode 100644 index 0000000..e512e48 --- /dev/null +++ b/src/response_handler.h @@ -0,0 +1,28 @@ +/* + * 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 __CONTEXT_LIB_RESPONSE_HANDLER_H__ +#define __CONTEXT_LIB_RESPONSE_HANDLER_H__ + +#include + +namespace ctx { namespace response_handler { + + void deliver(const char* subject, int req_id, int error, const char* data); + +} } /* namespace ctx::response_handler */ + +#endif // __CONTEXT_LIB_RESPONSE_HANDLER_H__ diff --git a/src/scope_mutex.cpp b/src/scope_mutex.cpp new file mode 100644 index 0000000..d2bf245 --- /dev/null +++ b/src/scope_mutex.cpp @@ -0,0 +1,27 @@ +/* + * 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 + +ctx::scope_mutex::scope_mutex(GMutex *m) : mutex(m) +{ + g_mutex_lock(mutex); +} + +ctx::scope_mutex::~scope_mutex() +{ + g_mutex_unlock(mutex); +} diff --git a/src/shared_vars.cpp b/src/shared_vars.cpp new file mode 100644 index 0000000..7679e41 --- /dev/null +++ b/src/shared_vars.cpp @@ -0,0 +1,19 @@ +/* + * 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 + +std::string ctx::shared::wifi_bssid = ""; diff --git a/src/timer_mgr.cpp b/src/timer_mgr.cpp new file mode 100644 index 0000000..cfb0f15 --- /dev/null +++ b/src/timer_mgr.cpp @@ -0,0 +1,45 @@ +/* + * 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 +#include +#include +#include + +static ctx::timer_manager_iface *_instance = NULL; + +void ctx::timer_manager::set_instance(ctx::timer_manager_iface* mgr) +{ + _instance = mgr; +} + +int ctx::timer_manager::set_for(int interval, timer_listener_iface* listener, void* user_data) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->set_for(interval, listener, user_data); +} + +int ctx::timer_manager::set_at(int hour, int min, int day_of_week, timer_listener_iface* listener, void* user_data) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->set_at(hour, min, day_of_week, listener, user_data); +} + +void ctx::timer_manager::remove(int timer_id) +{ + IF_FAIL_VOID_TAG(_instance, _E, "Not initialized"); + _instance->remove(timer_id); +}