From 7ebbd8b5cdfe4d37b847ae561987650cd5d0c0fc Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Wed, 18 May 2016 15:16:00 +0900 Subject: [PATCH] Uploading Device-to-Device Convergence framework source code Device-to-device(D2D) Convergence framework provides feature to discover near-by devices and to connect and execute the service remotely, which the near-by device provides. Change-Id: Iefc1f8cf70cc32c1de025209bc9a1cb6b1db3312 Signed-off-by: Jihoon Park --- AUTHORS | 1 + CMakeLists.txt | 20 + LICENSE | 203 +++++ common/common.h | 151 ++++ common/log.h | 87 ++ daemon/CMakeLists.txt | 42 + daemon/access_control/peer_creds.cpp | 79 ++ daemon/access_control/peer_creds.h | 40 + daemon/access_control/privilege.cpp | 73 ++ daemon/access_control/privilege.h | 29 + daemon/client.cpp | 75 ++ daemon/client.h | 56 ++ daemon/client_mgr_impl.cpp | 83 ++ daemon/client_mgr_impl.h | 52 ++ daemon/communication_info_base.h | 30 + daemon/connection_mgr_impl.cpp | 112 +++ daemon/connection_mgr_impl.h | 43 + daemon/conv_json.cpp | 951 ++++++++++++++++++++ daemon/conv_json.h | 117 +++ daemon/dbus_server_iface.h | 32 + daemon/dbus_server_impl.cpp | 289 ++++++ daemon/dbus_server_impl.h | 44 + daemon/device.cpp | 84 ++ daemon/device.h | 58 ++ daemon/device_iface.h | 40 + daemon/discovery_mgr_impl.cpp | 335 +++++++ daemon/discovery_mgr_impl.h | 83 ++ .../discovery_provider/ble_discovery_provider.cpp | 375 ++++++++ daemon/discovery_provider/ble_discovery_provider.h | 53 ++ .../discovery_provider/iotcon/device_adapter.cpp | 64 ++ daemon/discovery_provider/iotcon/device_adapter.h | 45 + .../discovery_provider/iotcon/resource_handle.cpp | 117 +++ daemon/discovery_provider/iotcon/resource_handle.h | 61 ++ .../discovery_provider/iotcon/service_adapter.cpp | 78 ++ daemon/discovery_provider/iotcon/service_adapter.h | 50 ++ .../iotcon_discovery_provider.cpp | 369 ++++++++ .../discovery_provider/iotcon_discovery_provider.h | 65 ++ .../smartview_discovery_provider.cpp | 249 ++++++ .../smartview_discovery_provider.h | 62 ++ daemon/discovery_provider_base.h | 40 + daemon/iotcon_communication_info.h | 38 + daemon/manager_iface.h | 36 + daemon/org.tizen.d2dconv.service.in | 5 + daemon/request.cpp | 178 ++++ daemon/request.h | 69 ++ daemon/request_handler.cpp | 98 +++ daemon/request_handler.h | 36 + daemon/server.cpp | 186 ++++ daemon/server.h | 29 + daemon/service.cpp | 105 +++ daemon/service.h | 67 ++ daemon/service_iface.h | 36 + daemon/service_info_base.h | 30 + daemon/service_mgr_impl.cpp | 376 ++++++++ daemon/service_mgr_impl.h | 53 ++ daemon/service_provider/app_comm_service_info.h | 170 ++++ .../service_provider/app_comm_service_provider.cpp | 502 +++++++++++ .../service_provider/app_comm_service_provider.h | 48 + .../remote_app_control_service_info.h | 55 ++ .../remote_app_control_service_provider.cpp | 572 ++++++++++++ .../remote_app_control_service_provider.h | 50 ++ daemon/service_provider_base.h | 58 ++ daemon/util.cpp | 154 ++++ daemon/util.h | 37 + doc/d2d_conv_manager_doc.h | 162 ++++ lib/CMakeLists.txt | 36 + lib/conv_lib.cpp | 240 +++++ lib/conv_lib_channel.cpp | 86 ++ lib/conv_lib_json.cpp | 966 +++++++++++++++++++++ lib/conv_lib_json.h | 119 +++ lib/conv_lib_payload.cpp | 179 ++++ lib/conv_lib_service.cpp | 596 +++++++++++++ lib/conv_lib_util.cpp | 34 + lib/conv_lib_util.h | 29 + lib/d2d-conv-manager.pc.in | 11 + lib/dbus_client.cpp | 240 +++++ lib/dbus_client.h | 37 + lib/include/d2d_conv_channel.h | 118 +++ lib/include/d2d_conv_device.h | 160 ++++ lib/include/d2d_conv_error.h | 57 ++ lib/include/d2d_conv_manager.h | 159 ++++ lib/include/d2d_conv_payload.h | 195 +++++ lib/include/d2d_conv_service.h | 456 ++++++++++ lib/internal_types.h | 63 ++ packaging/d2d-conv-manager-old.manifest | 59 ++ packaging/d2d-conv-manager-old.service | 17 + packaging/d2d-conv-manager.conf | 22 + packaging/d2d-conv-manager.manifest | 5 + packaging/d2d-conv-manager.service | 14 + packaging/d2d-conv-manager.spec | 140 +++ packaging/libd2d-conv-manager.manifest | 5 + test/CMakeLists.txt | 18 + test/test.c | 471 ++++++++++ 93 files changed, 12519 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 common/common.h create mode 100644 common/log.h create mode 100644 daemon/CMakeLists.txt create mode 100644 daemon/access_control/peer_creds.cpp create mode 100644 daemon/access_control/peer_creds.h create mode 100644 daemon/access_control/privilege.cpp create mode 100644 daemon/access_control/privilege.h create mode 100644 daemon/client.cpp create mode 100644 daemon/client.h create mode 100644 daemon/client_mgr_impl.cpp create mode 100644 daemon/client_mgr_impl.h create mode 100644 daemon/communication_info_base.h create mode 100644 daemon/connection_mgr_impl.cpp create mode 100644 daemon/connection_mgr_impl.h create mode 100644 daemon/conv_json.cpp create mode 100644 daemon/conv_json.h create mode 100644 daemon/dbus_server_iface.h create mode 100644 daemon/dbus_server_impl.cpp create mode 100644 daemon/dbus_server_impl.h create mode 100644 daemon/device.cpp create mode 100644 daemon/device.h create mode 100644 daemon/device_iface.h create mode 100644 daemon/discovery_mgr_impl.cpp create mode 100644 daemon/discovery_mgr_impl.h create mode 100644 daemon/discovery_provider/ble_discovery_provider.cpp create mode 100644 daemon/discovery_provider/ble_discovery_provider.h create mode 100644 daemon/discovery_provider/iotcon/device_adapter.cpp create mode 100644 daemon/discovery_provider/iotcon/device_adapter.h create mode 100644 daemon/discovery_provider/iotcon/resource_handle.cpp create mode 100644 daemon/discovery_provider/iotcon/resource_handle.h create mode 100644 daemon/discovery_provider/iotcon/service_adapter.cpp create mode 100644 daemon/discovery_provider/iotcon/service_adapter.h create mode 100644 daemon/discovery_provider/iotcon_discovery_provider.cpp create mode 100644 daemon/discovery_provider/iotcon_discovery_provider.h create mode 100644 daemon/discovery_provider/smartview_discovery_provider.cpp create mode 100644 daemon/discovery_provider/smartview_discovery_provider.h create mode 100644 daemon/discovery_provider_base.h create mode 100644 daemon/iotcon_communication_info.h create mode 100644 daemon/manager_iface.h create mode 100644 daemon/org.tizen.d2dconv.service.in create mode 100644 daemon/request.cpp create mode 100644 daemon/request.h create mode 100644 daemon/request_handler.cpp create mode 100644 daemon/request_handler.h create mode 100644 daemon/server.cpp create mode 100644 daemon/server.h create mode 100644 daemon/service.cpp create mode 100644 daemon/service.h create mode 100644 daemon/service_iface.h create mode 100644 daemon/service_info_base.h create mode 100644 daemon/service_mgr_impl.cpp create mode 100644 daemon/service_mgr_impl.h create mode 100644 daemon/service_provider/app_comm_service_info.h create mode 100644 daemon/service_provider/app_comm_service_provider.cpp create mode 100644 daemon/service_provider/app_comm_service_provider.h create mode 100644 daemon/service_provider/remote_app_control_service_info.h create mode 100644 daemon/service_provider/remote_app_control_service_provider.cpp create mode 100644 daemon/service_provider/remote_app_control_service_provider.h create mode 100644 daemon/service_provider_base.h create mode 100644 daemon/util.cpp create mode 100644 daemon/util.h create mode 100644 doc/d2d_conv_manager_doc.h create mode 100644 lib/CMakeLists.txt create mode 100644 lib/conv_lib.cpp create mode 100644 lib/conv_lib_channel.cpp create mode 100644 lib/conv_lib_json.cpp create mode 100644 lib/conv_lib_json.h create mode 100644 lib/conv_lib_payload.cpp create mode 100644 lib/conv_lib_service.cpp create mode 100644 lib/conv_lib_util.cpp create mode 100644 lib/conv_lib_util.h create mode 100644 lib/d2d-conv-manager.pc.in create mode 100644 lib/dbus_client.cpp create mode 100644 lib/dbus_client.h create mode 100644 lib/include/d2d_conv_channel.h create mode 100644 lib/include/d2d_conv_device.h create mode 100644 lib/include/d2d_conv_error.h create mode 100644 lib/include/d2d_conv_manager.h create mode 100644 lib/include/d2d_conv_payload.h create mode 100644 lib/include/d2d_conv_service.h create mode 100644 lib/internal_types.h create mode 100644 packaging/d2d-conv-manager-old.manifest create mode 100644 packaging/d2d-conv-manager-old.service create mode 100644 packaging/d2d-conv-manager.conf create mode 100644 packaging/d2d-conv-manager.manifest create mode 100644 packaging/d2d-conv-manager.service create mode 100644 packaging/d2d-conv-manager.spec create mode 100644 packaging/libd2d-conv-manager.manifest create mode 100644 test/CMakeLists.txt create mode 100644 test/test.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..539f969 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Kyoungmook Choi diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1f0bba2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(d2d-conv-manager) + +INCLUDE(FindPkgConfig) + +SET(EXTRA_CFLAGS "-Wall -Werror-implicit-function-declaration -fPIC -fvisibility=hidden") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +SET(EXTRA_CXXFLAGS "-std=c++0x") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") + +SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--hash-style=both") + +SET(CLIENT "d2d-conv-manager") +SET(DAEMON "d2d-conv-managerd") +SET(DBUS_INTERFACE "org.tizen.d2d-conv-manager") + +ADD_SUBDIRECTORY(lib) +ADD_SUBDIRECTORY(daemon) +ADD_SUBDIRECTORY(test) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1aea19e --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ +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/common/common.h b/common/common.h new file mode 100644 index 0000000..620b2b4 --- /dev/null +++ b/common/common.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_COMMON_H__ +#define __CONV_COMMON_H__ + +#include +#include "log.h" +#include "d2d_conv_manager.h" + +#define CONV_DATA "ConvHeader" +#define CONV_OPTION "ConvOption" +#define CONV_RESPONSE "ConvResponse" + +/* DBus */ +#define DBUS_DEST "org.tizen.d2dconv" +#define DBUS_PATH "/org/tizen/d2dconv" +#define DBUS_IFACE "org.tizen.d2dconv" +#define DBUS_TIMEOUT 3000000 + +#define METHOD_REQUEST "Request" +#define METHOD_RESPOND "Respond" +#define SIGNAL_LAUNCHED "Launched" + +#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" + +#define CONV_METHOD_REQUEST "CONV_Request" +#define CONV_METHOD_RESPOND "CONV_Respond" +#define CONV_ARG_KEY_RESULT "CONV_Result" + +#define CONV_SUBJECT_DISCOVERY_START "conv/discovery/start" +#define CONV_SUBJECT_DISCOVERY_STOP "conv/discovery/stop" + +#define CONV_SUBJECT_COMMUNICATION_RECV "conv/communication/recv" +#define CONV_SUBJECT_COMMUNICATION_START "conv/communication/start" +#define CONV_SUBJECT_COMMUNICATION_STOP "conv/communication/stop" +#define CONV_SUBJECT_COMMUNICATION_GET "conv/communication/get" +#define CONV_SUBJECT_COMMUNICATION_SET "conv/communication/set" + +#define CONV_SUBJECT_COMMUNICATION_WRITE "conv/communication/write" +#define CONV_SUBJECT_COMMUNICATION_READ "conv/communication/read" + +#define CONV_SUBJECT_CONNECTION_START "conv/connection/start" +#define CONV_SUBJECT_CONNECTION_STOP "conv/connection/stop" + +#define CONV_SERVICE_TYPE_SMARTVIEW_APP_COMMUNICATION "smartview" +#define CONV_SERVICE_TYPE_REMOTE_APP_CONTROL "remote_appcontrol" + +#define CONV_COMM_TYPE_SMARTVIEW "comm/smartview" +#define CONV_COMM_TYPE_IOTCON "comm/iotcon" + +#define CONV_RESOURCE_TYPE_SMARTVIEW_APP_COMMUNICATION "x.org.tizen.app-communication" +#define CONV_RESOURCE_TYPE_REMOTE_APP_CONTROL "x.org.tizen.remote-app-control" +#define CONV_RESOURCE_TYPE_TIZEN_D2D_SERVICE "x.org.tizen.d2d-service" + +#define CONV_URI_SMARTVIEW_APP_COMMUNICATION "/tizen/app-communication" +#define CONV_URI_SMARTVIEW_REMOTE_APP_CONTROL "/tizen/remote-app-control" +#define CONV_URI_SMARTVIEW_TIZEN_D2D_SERVICE "/tizen/d2d-service" + +#define CONV_PRIVILEGE_INTERNET "internet" +#define CONV_PRIVILEGE_BLUETOOTH "bluetooth" +#define CONV_PRIVILEGE_NETWORK_GET "network.get" +#define CONV_PRIVILEGE_D2D_DATA_SHARING "d2d.datasharing" + +enum request_type { + REQ_SUBSCRIBE = 1, + REQ_UNSUBSCRIBE, + REQ_READ, + REQ_READ_SYNC, + REQ_WRITE, + REQ_SUPPORT, +}; + +#define CONV_JSON_SERVICE_PATH "service" +#define CONV_JSON_SERVICE_DATA "data" +#define CONV_JSON_SERVICE_TYPE "type" + +#define CONV_JSON_DESCRIPTION "description" +#define CONV_JSON_PAYLOAD "payload" +#define CONV_JSON_SERVICE "service" +#define CONV_JSON_CHANNEL "channel" +#define CONV_JSON_IS_LOCAL "is_local" +#define CONV_JSON_DEVICE "device" +#define CONV_JSON_TYPE "type" +#define CONV_JSON_DISCOVERY_SERVICE_TYPE "service_type" +#define CONV_JSON_DISCOVERY_SERVICE_INFO "service_info" +#define CONV_JSON_REQ_ID "req_id" + +#define CONV_JSON_SERVICE_DATA_PATH NULL +#define CONV_JSON_SERVICE_DATA_NAME "name" +#define CONV_JSON_SERVICE_DATA_VERSION CONV_SERVICE_VERSION +#define CONV_JSON_SERVICE_DATA_TYPE "type" +#define CONV_JSON_SERVICE_DATA_ID "id" +#define CONV_JSON_SERVICE_DATA_URI CONV_SERVICE_ID + +#define CONV_TYPE_APP_TO_APP_COMMUNICATION 0 +#define CONV_TYPE_REMOVE_APP_CONTROL 1 + +#define CONV_DISCOVERY_MIN_VALUE 5 +#define CONV_DISCOVERY_MAX_VALUE 60 + +#define CONV_DISCOVERY_ERROR -1 +#define CONV_DISCOVERY_SUCCESS 0 +#define CONV_DISCOVERY_FINISHED 1 + +#define CONV_JSON_DEVICE_ID CONV_DEVICE_ID +#define CONV_JSON_DEVICE_NAME CONV_DEVICE_NAME +#define CONV_JSON_DEVICE_TYPE CONV_DEVICE_TYPE +#define CONV_JSON_DEVICE_ADDRESS "host_address" + +// smartview app to app communication service +#define CONV_JSON_CHANNEL_ID "channel_id" +#define CONV_JSON_URI "uri" +#define CONV_JSON_RESULT_TYPE "result_type" +#define CONV_JSON_MESSAGE "message" +#define CONV_JSON_CLIENT "client" +#define CONV_JSON_PAYLOAD_SIZE "payload_size" +#define CONV_JSON_EVENT "event" +#define CONV_JSON_FROM "from" +#define CONV_JSON_IS_HOST "isHost" +#define CONV_JSON_CONNECT_TIME "connectTime" +#define CONV_JSON_CLIENT_ID "clientId" +#define CONV_JSON_CHANNEL_URI "channelUri" +#define CONV_JSON_CLIENT_LIST "client_list" + +// remote app control service +#define CONV_JSON_APP_CONTROL "app_control" +#define CONV_JSON_REPLY "reply" + +#endif diff --git a/common/log.h b/common/log.h new file mode 100644 index 0000000..b0225b1 --- /dev/null +++ b/common/log.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_LOG_H__ +#define __CONV_LOG_H__ + +#define TIZEN_DEBUG_ENABLE +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "D2D-CONV-MANAGER" + +#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. + */ + + +/* 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 + +#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 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_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); } } 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, CONV_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed") +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, CONV_ERROR_INVALID_PARAMETER, _E, "Parameter null") + +#define HANDLE_GERROR(Err) \ + do { if ((Err)) { _E("GError: %s", Err->message); g_error_free(Err); Err = NULL; } } while (0) + + +#endif diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt new file mode 100644 index 0000000..ae9c8b7 --- /dev/null +++ b/daemon/CMakeLists.txt @@ -0,0 +1,42 @@ +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common/) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/include/) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/daemon/lib) + +SET(PTHREAD "pthread") + +FILE(GLOB DAEMON_SRCS *.c *.cpp ) +FILE(GLOB DAEMON_SRCS ${DAEMON_SRCS} discovery_provider/*.cpp) +FILE(GLOB DAEMON_SRCS ${DAEMON_SRCS} service_provider/*.cpp) +FILE(GLOB DAEMON_SRCS ${DAEMON_SRCS} access_control/*.cpp) +FILE(GLOB DAEMON_SRCS ${DAEMON_SRCS} discovery_provider/iotcon/*.cpp) + +SET(provider_deps "glib-2.0 dlog json-glib-1.0 iotcon capi-appfw-app-manager msf-api iotcon vconf capi-network-bluetooth capi-network-wifi-direct capi-appfw-application bundle capi-network-connection cynara-creds-gdbus cynara-client cynara-session capi-appfw-package-manager") +# SET(provider_deps "${provider_deps} security-server") +# Mobile profile +IF("${PROFILE}" STREQUAL "mobile") + ADD_DEFINITIONS("-D_MOBILE_") +# SET(provider_deps "${provider_deps} tapi capi-messaging-messages") +ENDIF("${PROFILE}" STREQUAL "mobile") + +# TV profile +IF("${PROFILE}" STREQUAL "tv") + ADD_DEFINITIONS("-D_TV_") +ENDIF("${PROFILE}" STREQUAL "tv") + +pkg_check_modules(daemon_pkgs REQUIRED ${provider_deps}) + +INCLUDE_DIRECTORIES(${daemon_pkgs_INCLUDE_DIRS}) +LINK_DIRECTORIES(${daemon_pkgs_LIBRARY_DIRS}) + +ADD_DEFINITIONS("-DCONV_DBUS_INTERFACE=\"${DBUS_INTERFACE}\"") + +ADD_EXECUTABLE(${DAEMON} ${DAEMON_SRCS}) + +TARGET_LINK_LIBRARIES(${DAEMON} ${daemon_pkgs_LIBRARIES} -lpthread) + + +INSTALL(TARGETS ${DAEMON} DESTINATION ${BIN_INSTALL_DIR}) + +SET(DBUS_SERVICE_FILE "org.tizen.d2dconv") +CONFIGURE_FILE(${DBUS_SERVICE_FILE}.service.in ${DBUS_SERVICE_FILE}.service @ONLY) +INSTALL(FILES ${DBUS_SERVICE_FILE}.service DESTINATION ${SHARE_INSTALL_PREFIX}/dbus-1/services) diff --git a/daemon/access_control/peer_creds.cpp b/daemon/access_control/peer_creds.cpp new file mode 100644 index 0000000..d2b2e27 --- /dev/null +++ b/daemon/access_control/peer_creds.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "common.h" +#include "peer_creds.h" +#include +#include +#include +#include + +conv::credentials::credentials(char *pkg_id, char *cli, char *sess, char *usr) : + package_id(pkg_id), + client(cli), + session(sess), + user(usr) +{ +} + +conv::credentials::~credentials() +{ + g_free(package_id); + g_free(client); + g_free(session); + g_free(user); +} + +bool conv::peer_creds::get(GDBusConnection *connection, const char *unique_name, conv::credentials **creds) +{ + pid_t pid = 0; + char *app_id = NULL; + char *package_id = NULL; + gchar *client = NULL; + char *session = NULL; + gchar *user = NULL; + int err; + + err = cynara_creds_gdbus_get_pid(connection, unique_name, &pid); + IF_FAIL_RETURN_TAG(err == CYNARA_API_SUCCESS, false, _E, "Peer credentialing failed"); + + app_manager_get_app_id(pid, &app_id); + package_manager_get_package_id_by_app_id(app_id, &package_id); + _D("AppId: %s, PackageId: %s", app_id, package_id); + + err = cynara_creds_gdbus_get_client(connection, unique_name, CLIENT_METHOD_DEFAULT, &client); + IF_FAIL_CATCH_TAG(err == CYNARA_API_SUCCESS, _E, "Peer credentialing failed"); + + session = cynara_session_from_pid(pid); + IF_FAIL_CATCH_TAG(session, _E, "Peer credentialing failed"); + + err = cynara_creds_gdbus_get_user(connection, unique_name, USER_METHOD_DEFAULT, &user); + IF_FAIL_CATCH_TAG(err == CYNARA_API_SUCCESS, _E, "Peer credentialing failed"); + + *creds = new(std::nothrow) credentials(package_id, client, session, user); + IF_FAIL_CATCH_TAG(*creds, _E, "Memory allocation failed"); + + return true; + +CATCH: + g_free(app_id); + g_free(package_id); + g_free(client); + g_free(session); + g_free(user); + return false; +} diff --git a/daemon/access_control/peer_creds.h b/daemon/access_control/peer_creds.h new file mode 100644 index 0000000..25269a5 --- /dev/null +++ b/daemon/access_control/peer_creds.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_PEER_CREDENTIALS_H__ +#define __CONV_PEER_CREDENTIALS_H__ + +#include +#include +#include + +namespace conv { + class credentials { + public: + char *package_id; + char *client; /* default: smack label */ + char *session; + char *user; /* default: UID */ + credentials(char *package_id, char *client, char *session, char *user); + ~credentials(); + }; + + namespace peer_creds { + bool get(GDBusConnection *connection, const char *uniqueName, conv::credentials **creds); + } +} /* namespace conv */ + +#endif /* End of __CONV_PEER_CREDENTIALS_H__ */ diff --git a/daemon/access_control/privilege.cpp b/daemon/access_control/privilege.cpp new file mode 100644 index 0000000..6619ca7 --- /dev/null +++ b/daemon/access_control/privilege.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "common.h" +#include "privilege.h" + +class permission_checker { +private: + cynara *__cynara; + + permission_checker() + { + if (cynara_initialize(&__cynara, NULL) != CYNARA_API_SUCCESS) { + _E("Cynara initialization failed"); + __cynara = NULL; + return; + } + _I("Cynara initialized"); + } + + ~permission_checker() + { + if (__cynara) + cynara_finish(__cynara); + + _I("Cynara deinitialized"); + } + +public: + static permission_checker& get_instance() + { + static permission_checker instance; + return instance; + } + + bool has_permission(const conv::credentials *creds, const char *privilege) + { + IF_FAIL_RETURN_TAG(__cynara, false, _E, "Cynara not initialized"); + int ret = cynara_check(__cynara, creds->client, creds->session, creds->user, privilege); + return (ret == CYNARA_API_ACCESS_ALLOWED); + } +}; + +bool conv::privilege_manager::is_allowed(const conv::credentials *creds, const char *privilege) +{/* + IF_FAIL_RETURN(creds && privilege, true); + + std::string priv = "http://tizen.org/privilege/"; + priv += privilege; + + return permission_checker::get_instance().has_permission(creds, priv.c_str()); +*/ + return true; +} + + + + diff --git a/daemon/access_control/privilege.h b/daemon/access_control/privilege.h new file mode 100644 index 0000000..4c51f15 --- /dev/null +++ b/daemon/access_control/privilege.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_PRIVILEGE_MANAGER_H__ +#define __CONV_PRIVILEGE_MANAGER_H__ + +#include +#include "peer_creds.h" + +namespace conv { + namespace privilege_manager { + bool is_allowed(const conv::credentials *creds, const char *privilege); + } /* namespace conv::privilege_manager */ +} /* namespace conv */ + +#endif /* End of __CONV_PRIVILEGE_MANAGER_H__ */ diff --git a/daemon/client.cpp b/daemon/client.cpp new file mode 100644 index 0000000..bbd4055 --- /dev/null +++ b/daemon/client.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "client.h" +#include "log.h" +#include "d2d_conv_manager.h" + +using namespace std; + +conv::client::client(string client_id, GDBusMethodInvocation *inv) +{ + id = client_id; +} + +conv::client::~client() +{ + for (service_info_map_t::iterator it = service_info_map.begin(); it != service_info_map.end(); ++it) { +// delete (it->second); + } + service_info_map.clear(); +} + +int conv::client::add_device() +{ + return CONV_ERROR_NONE; +} + +int conv::client::remove_device() +{ + return CONV_ERROR_NONE; +} + +string conv::client::get_id() +{ + return id; +} + +conv::service_info_base* conv::client::get_service_info(string type, string id) +{ + service_info_map_t::iterator it; + it = service_info_map.find(std::pair(type, id)); + + if ( it != service_info_map.end() ) + { + _D("service info found : %s, %s", type.c_str(), id.c_str()); + return (service_info_base*)(it->second); + } + else + { + _D("service info not found : %s, %s", type.c_str(), id.c_str()); + return NULL; + } +} + +int conv::client::add_service_info(string type, string id, service_info_base* info) +{ + service_info_map.insert(std::pair(std::pair(type, id), info)); + _D("service info is added : %s, %s", type.c_str(), id.c_str()); + + return CONV_ERROR_NONE; +} diff --git a/daemon/client.h b/daemon/client.h new file mode 100644 index 0000000..e1e901e --- /dev/null +++ b/daemon/client.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_CLIENT_H__ +#define __CONV_CLIENT_H__ + +#include +#include +#include +#include +#include "client.h" +#include "conv_json.h" +#include "device.h" +#include "service_info_base.h" + +namespace conv { + class client { + typedef std::vector device_list_t; + typedef std::pair service_key_t; + typedef std::map service_info_map_t; + + public: + client(std::string id, GDBusMethodInvocation *inv); + ~client(); + + int add_device(); + int remove_device(); + + std::string get_id(); + + service_info_base* get_service_info(std::string type, std::string id); + int add_service_info(std::string type, std::string id, service_info_base* info); + private: + device_list_t device_list; + service_info_map_t service_info_map; + + protected: + std::string id; + GDBusMethodInvocation *invocation; + }; +} + +#endif /* End of __CONV_CLIENT_H__ */ diff --git a/daemon/client_mgr_impl.cpp b/daemon/client_mgr_impl.cpp new file mode 100644 index 0000000..00972a3 --- /dev/null +++ b/daemon/client_mgr_impl.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "client_mgr_impl.h" + +static conv::client_manager_impl *_instance; + +using namespace std; + +conv::client_manager_impl::client_manager_impl() +{ +} + +conv::client_manager_impl::~client_manager_impl() +{ +} + +int conv::client_manager_impl::init() +{ + return CONV_ERROR_NONE; +} + +int conv::client_manager_impl::release() +{ + for (client_list_t::iterator it = client_list.begin(); it != client_list.end(); ++it) { + delete *it; + } + + client_list.clear(); + + return CONV_ERROR_NONE; +} + +void conv::client_manager::set_instance(conv::client_manager_impl* mgr) +{ + _instance = mgr; +} + + +int conv::client_manager_impl::handle_request(request* request_obj) +{ + _D("handle_request called"); + + return CONV_ERROR_NONE; +} + +conv::client* conv::client_manager::get_client(std::string client_id) +{ + IF_FAIL_RETURN_TAG(_instance, NULL, _E, "Not initialized"); + + return _instance->get_client(client_id); +} + +conv::client* conv::client_manager_impl::get_client(std::string client_id) +{ + for (client_list_t::iterator it = client_list.begin(); it != client_list.end(); ++it) { + if ( !(*it)->get_id().compare(client_id) ) + { + // already exists + _D("client exists"); + return *it; + } + } + + _D("new client obj created"); + client* client_obj = new conv::client(client_id, NULL); + + client_list.push_back(client_obj); + return client_obj; +} diff --git a/daemon/client_mgr_impl.h b/daemon/client_mgr_impl.h new file mode 100644 index 0000000..eed05d3 --- /dev/null +++ b/daemon/client_mgr_impl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CLIENT_MANAGER_IMPL_H__ +#define __CLIENT_MANAGER_IMPL_H__ + +#include +#include +#include +#include +#include "manager_iface.h" +#include "client.h" + +namespace conv { + class client_manager_impl : public manager_iface { + typedef std::vector client_list_t; + public: + client_manager_impl(); + ~client_manager_impl(); + + // int start(int time, request_info* request, json option); + // int stop(); + + int init(); + int release(); + int handle_request(request* request_obj); + conv::client* get_client(std::string client_id); + + private: + client_list_t client_list; + }; + + namespace client_manager { + void set_instance(client_manager_impl* mgr); + conv::client* get_client(std::string client_id); + } +} + +#endif /* __CLIENT_MANAGER_IMPL_H__ */ diff --git a/daemon/communication_info_base.h b/daemon/communication_info_base.h new file mode 100644 index 0000000..e7d7433 --- /dev/null +++ b/daemon/communication_info_base.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_COMMUNICATION_INFO_BASE_H__ +#define __CONV_COMMUNICATION_INFO_BASE_H__ + +#include + +namespace conv +{ + class communication_info_base { + public: + virtual ~communication_info_base() {} + }; +} + +#endif /* End of __CONV_COMMUNICATION_INFO_BASE_H__ */ diff --git a/daemon/connection_mgr_impl.cpp b/daemon/connection_mgr_impl.cpp new file mode 100644 index 0000000..fb71644 --- /dev/null +++ b/daemon/connection_mgr_impl.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "connection_mgr_impl.h" +#include "access_control/privilege.h" + +static conv::connection_manager_impl *_instance; +static conv::request* cur_Req; + +using namespace std; + +conv::connection_manager_impl::connection_manager_impl() +{ +} + +conv::connection_manager_impl::~connection_manager_impl() +{ +} + +int conv::connection_manager_impl::init() +{ + return CONV_ERROR_NONE; +} + +int conv::connection_manager_impl::release() +{ + return CONV_ERROR_NONE; +} + +void conv::connection_manager::set_instance(conv::connection_manager_impl* mgr) +{ + _instance = mgr; +} + +int conv::connection_manager_impl::handle_request(request* request_obj) +{ + _D("handle_request called"); + int error = CONV_ERROR_INVALID_OPERATION; + + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + + switch (request_obj->get_type()) { + case REQ_SUBSCRIBE: + { + cur_Req = request_obj; + error = CONV_ERROR_NONE; + } + break; + case REQ_UNSUBSCRIBE: + { + cur_Req = NULL; + error = CONV_ERROR_NONE; + } + break; + case REQ_WRITE: + { + json cb_json, jservice, description, tmp_payload; + string did; + description = request_obj->get_description(); + description.get(NULL, CONV_JSON_SERVICE, &jservice); + jservice.get(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_ID, &did); + // TODO: + //make callback data and invoke + cb_json.set(NULL, CONV_JSON_DESCRIPTION, request_obj->get_description()); + cb_json.set(NULL, CONV_JSON_PAYLOAD, tmp_payload); + if (cur_Req != NULL) { + cur_Req->publish(CONV_ERROR_NONE, cb_json); + } + error = CONV_ERROR_NONE; + } + break; + default: + { + _E("Invalid type of request"); + error = CONV_ERROR_INVALID_OPERATION; + } + break; + } + + request_obj->reply(error); + delete request_obj; + return CONV_ERROR_NONE; +} + +int conv::connection_manager::handle_request(request* request_obj) +{ + IF_FAIL_RETURN_TAG(_instance, CONV_ERROR_INVALID_PARAMETER, _E, "Not initialized"); + _instance->handle_request(request_obj); + + return CONV_ERROR_NONE; +} + diff --git a/daemon/connection_mgr_impl.h b/daemon/connection_mgr_impl.h new file mode 100644 index 0000000..fd93c46 --- /dev/null +++ b/daemon/connection_mgr_impl.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONNECTION_MANAGER_IMPL_H__ +#define __CONNECTION_MANAGER_IMPL_H__ + +#include +#include +#include +#include "manager_iface.h" +#include "request.h" + +namespace conv { + class connection_manager_impl : public manager_iface { + public: + connection_manager_impl(); + ~connection_manager_impl(); + + int init(); + int release(); + int handle_request(request* request_obj); + }; + + namespace connection_manager { + void set_instance(connection_manager_impl* mgr); + int handle_request(request* request_obj); + } +} + +#endif /* __CONNECTION_MANAGER_IMPL_H__ */ diff --git a/daemon/conv_json.cpp b/daemon/conv_json.cpp new file mode 100644 index 0000000..5de858f --- /dev/null +++ b/daemon/conv_json.cpp @@ -0,0 +1,951 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "conv_json.h" + +#define PATH_DELIM '.' +#define GVAR_VALUES "values" +#define GVAR_TYPES "types" + +static double string_to_double(const char* in) +{ + IF_FAIL_RETURN_TAG(in, 0, _E, "Parameter NULL"); + + // Locale-independent string-to-double conversion + double out; + std::istringstream istr(in); + istr.imbue(std::locale("C")); + istr >> out; + return out; +} + +static std::string double_to_string(double in, int prec) +{ + // Locale-independent double-to-string conversion + std::ostringstream ostr; + ostr.imbue(std::locale("C")); + ostr << std::setprecision(prec) << std::fixed << in; + return ostr.str(); +} + +json::json() +{ + 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); +} + +json::json(const json& j) +{ + json_node = json_node_copy(j.json_node); + IF_FAIL_VOID_TAG(json_node, _E, "Json object construction failed"); +} + +json::json(const char* s) +{ + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } +} + +json::json(const std::string& s) +{ + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } +} + +json::~json() +{ + release(); +} + +void json::parse(const char* s) +{ + gboolean result; + JsonParser *parser = NULL; + JsonNode *root = NULL; + + parser = json_parser_new(); + IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed"); + + result = json_parser_load_from_data(parser, s, -1, NULL); + IF_FAIL_CATCH_TAG(result, _E, "Parsing failed"); + + root = json_parser_get_root(parser); + IF_FAIL_CATCH_TAG(root, _E, "Getting root failed"); + + json_node = json_node_copy(root); + IF_FAIL_CATCH_TAG(json_node, _E, "Copying failed"); + +CATCH: + if (parser) + g_object_unref(parser); +} + +void json::release() +{ + if (json_node) { + json_node_free(json_node); + json_node = NULL; + } +} + +json& json::operator=(const json& j) +{ + release(); + json_node = json_node_copy(j.json_node); + if (!json_node) { + _E("Json object copy failed"); + } + return *this; +} + +json& json::operator=(const char* s) +{ + release(); + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } + return *this; +} + +json& json::operator=(const std::string& s) +{ + release(); + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } + return *this; +} + +bool json::operator==(const json& rhs) +{ + return node_equals(json_node, rhs.json_node); +} + +bool json::operator!=(const json& rhs) +{ + return !operator==(rhs); +} + +/* TODO +bool json::contains(const json& subset) const +{ + return false; +} +*/ + +char* 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 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; j < i; j++) { + g_free(tokens[j]); + } + g_free(tokens); + return NULL; +} + +static void free_tokenized_path(int length, char** tokens) +{ + int i; + if (tokens) { + for (i = 0; i < length; i++) { + g_free(tokens[i]); + } + g_free(tokens); + } +} + +static JsonObject* traverse(JsonNode* jnode, const char* path, bool force) +{ + IF_FAIL_RETURN_TAG(jnode, NULL, _E, "Invalid parameter"); + + int length = 0; + int depth = 0; + char **path_token = NULL; + JsonObject *jobj = NULL; + JsonObject *child_obj = NULL; + JsonNode *child_node = NULL; + + jobj = json_node_get_object(jnode); + IF_FAIL_RETURN(jobj, NULL); + + if (path) { + path_token = tokenize_path(path, &length); + IF_FAIL_RETURN_TAG(path_token, NULL, _E, "Invalid path"); + } + + for (depth = 0; depth < length; depth++) { + if (!json_object_has_member(jobj, path_token[depth])) { + if (force) { + child_obj = json_object_new(); + IF_FAIL_CATCH_TAG(child_obj, _E, "Memory allocation failed"); + json_object_set_object_member(jobj, path_token[depth], child_obj); + } else { + goto CATCH; + } + } + child_node = json_object_get_member(jobj, path_token[depth]); + IF_FAIL_CATCH(child_node && json_node_get_node_type(child_node) == JSON_NODE_OBJECT); + + jobj = json_node_get_object(child_node); + IF_FAIL_CATCH(jobj); + } + + free_tokenized_path(length, path_token); + return jobj; + +CATCH: + free_tokenized_path(length, path_token); + return NULL; +} + +bool json::set(const char* path, const char* key, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_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 json::set(const char* path, const char* key, int val) +{ + return set(path, key, static_cast(val)); +} + +bool 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 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 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 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 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 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 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 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 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 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 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 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 json::array_append(const char* path, const char* key, int val) +{ + return array_append(path, key, static_cast(val)); +} + +bool 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 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 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 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 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 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 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 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 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 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 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 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 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 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 json::get_keys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return get_member_list(json_node, *list); +} + +bool 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 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 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 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 < size; ++i) { + json_node_t *lhs_child = json_array_get_element(larr, i); + json_node_t *rhs_child = json_array_get_element(rarr, i); + IF_FAIL_RETURN(node_equals(lhs_child, rhs_child), false); + } + + return true; +} diff --git a/daemon/conv_json.h b/daemon/conv_json.h new file mode 100644 index 0000000..76c512c --- /dev/null +++ b/daemon/conv_json.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_JSON_H__ +#define __CONV_JSON_H__ + +#include +#include +#include +#include +#include "common.h" + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while (0) + +#define EMPTY_JSON_OBJECT "{}" +#define DEFAULT_PRECISION 3 + +class json { +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); +}; + +#endif // __CONV_JSON_H__ + diff --git a/daemon/dbus_server_iface.h b/daemon/dbus_server_iface.h new file mode 100644 index 0000000..26c7a22 --- /dev/null +++ b/daemon/dbus_server_iface.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_DBUS_SERVER_INTERFACE_H__ +#define __CONV_DBUS_SERVER_INTERFACE_H__ + +#include + +namespace conv { + 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 conv::dbus_server */ + +} /* namespace ctx */ + +#endif /* End of __CONV_DBUS_SERVER_INTERFACE_H__ */ diff --git a/daemon/dbus_server_impl.cpp b/daemon/dbus_server_impl.cpp new file mode 100644 index 0000000..f5c5a63 --- /dev/null +++ b/daemon/dbus_server_impl.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "server.h" +#include "access_control/peer_creds.h" +#include "dbus_server_impl.h" + +#define DEFAULT_APP_ID "Default" + +static bool conn_acquired = false; +static bool name_acquired = false; +static conv::dbus_server_impl *_instance = NULL; +static GDBusConnection *dbus_connection = NULL; +static guint dbus_owner_id = 0; +static GDBusNodeInfo *dbus_node_info = NULL; + +static const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static const char* req_type_to_str(int req_type) +{ + switch (req_type) { + case REQ_SUBSCRIBE: + return "Subscribe"; + case REQ_UNSUBSCRIBE: + return "Unsubscribe"; + case REQ_READ: + return "Read"; + case REQ_READ_SYNC: + return "Read (Sync)"; + case REQ_WRITE: + return "Write"; + default: + return NULL; + } +} + +static void handle_request(GDBusConnection* conn, const char *sender, GVariant *param, GDBusMethodInvocation *invocation) +{ + gint req_type = 0; + const gchar *cookie = NULL; + gint req_id = 0; + const gchar *subject = NULL; + const gchar *input = NULL; + + g_variant_get(param, "(i&si&s&s)", &req_type, &cookie, &req_id, &subject, &input); + IF_FAIL_VOID_TAG(req_type > 0 && req_id > 0 && cookie && subject && input, _E, "Invalid request"); + + _SD("Cookie: %s", cookie); + _I("[%s] ReqId: %d, Subject: %s", req_type_to_str(req_type), req_id, subject); + _SI("Input: %s", input); + + conv::credentials *creds = NULL; + // temporaily removed - privilege checker +/* + if (!peer_creds::get(conn, sender, &creds)) { + _E("Peer credentialing failed"); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", CONV_ERROR_INVALID_OPERATION, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT)); + return; + } +*/ + conv::request *recv_request = NULL; + try{ + recv_request = new conv::request(req_type, DEFAULT_APP_ID, req_id, subject, input, sender, creds, invocation); +// recv_request = new conv::request(req_type, app_id, req_id, subject, input, sender, NULL, invocation); + } catch (std::bad_alloc& ba) { + _E("Memory Allocation Failed.."); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", CONV_ERROR_INVALID_OPERATION, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT)); +// delete creds; + return; + } catch (int e) { + _E("Caught %d", e); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", CONV_ERROR_INVALID_OPERATION, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT)); +// delete creds; + return; + } + + if (!recv_request) { + _E("Memory allocation failed"); + g_dbus_method_invocation_return_value(invocation, g_variant_new("(iss)", CONV_ERROR_INVALID_OPERATION, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT)); + return; + } + + conv::send_request(recv_request); +} + +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_REQUEST)) { + handle_request(conn, sender, param, invocation); + } else { + _W("Invalid method: %s", method_name); + } + + _D("end of handle_method_call"); +} + +static void on_bus_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data) +{ + GError *error = NULL; + + GDBusInterfaceVTable vtable; + vtable.method_call = handle_method_call; + vtable.get_property = NULL; + vtable.set_property = NULL; + + guint reg_id = g_dbus_connection_register_object(conn, DBUS_PATH, + dbus_node_info->interfaces[0], &vtable, NULL, NULL, &error); + + if (reg_id <= 0) { + _E("Failed to acquire dbus gerror(%s)", error->message); + raise(SIGTERM); + } + + conn_acquired = true; + dbus_connection = conn; + + _I("Dbus connection acquired"); +} + +static void on_name_acquired(GDBusConnection *conn, const gchar *name, gpointer user_data) +{ + name_acquired = true; + _SI("Dbus name acquired: %s", name); +} + +static void on_name_lost(GDBusConnection *conn, const gchar *name, gpointer user_data) +{ + _E("Dbus name lost"); + raise(SIGTERM); +} + +conv::dbus_server_impl::dbus_server_impl() +{ +} + +conv::dbus_server_impl::~dbus_server_impl() +{ + release(); +} + +bool conv::dbus_server_impl::init() +{ + GError *error = NULL; + + _I("init with dbus_node_info : %x", dbus_node_info); + + dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, &error); + if (dbus_node_info == NULL) { + _E("g_dbus_node_info_new_for_xml() Fail(%s)", error->message); + g_error_free(error); + return false; + } + + dbus_owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_DEST, G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL); + + if (dbus_owner_id == 0) { + _E("dbus_owner_id Fail()"); + return false; + } + + _instance = this; + + return true; +} + +void conv::dbus_server_impl::release() +{ + if (dbus_connection) { + g_dbus_connection_flush_sync(dbus_connection, NULL, NULL); + } + + if (dbus_owner_id > 0) { + g_bus_unown_name(dbus_owner_id); + dbus_owner_id = 0; + } + + if (dbus_connection) { + 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; + } +} + +void conv::dbus_server_impl::publish(const char* dest, int req_id, const char* subject, int error, const char* data) +{ + IF_FAIL_VOID_TAG(dest && subject && data, _E, "Parameter null"); + + _SI("Publish: %s, %d, %s, %#x, %s", dest, req_id, subject, error, data); + + GVariant *param = g_variant_new("(isis)", req_id, subject, error, data); + IF_FAIL_VOID_TAG(param, _E, "Memory allocation failed"); + + _D("before g_dbus_connection_call.."); + GError *err = NULL; + g_dbus_connection_call(dbus_connection, dest, DBUS_PATH, DBUS_IFACE, + METHOD_RESPOND, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err); + + if (err != NULL) + { + _D("dbus_connection_call Error msg : %s", err->message); + + HANDLE_GERROR(err); + } + else + { + _D("err is NULL"); + } +} + +static void handle_call_result(GObject *source, GAsyncResult *res, gpointer user_data) +{ + _I("Call %u done", *static_cast(user_data)); + + GDBusConnection *conn = G_DBUS_CONNECTION(source); + GError *error = NULL; + g_dbus_connection_call_finish(conn, res, &error); + HANDLE_GERROR(error); +} + +void conv::dbus_server_impl::call(const char *dest, const char *obj, const char *iface, const char *method, GVariant *param) +{ + IF_FAIL_VOID_TAG(dest && obj && iface && method, _E, "Parameter null"); + + static unsigned int call_count = 0; + ++call_count; + + _SI("Call %u: %s, %s, %s.%s", call_count, dest, obj, iface, method); + + g_dbus_connection_call(dbus_connection, dest, obj, iface, method, param, NULL, + G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, handle_call_result, &call_count); +} + +void conv::dbus_server::publish(const char* dest, int req_id, const char* subject, int error, const char* data) +{ + _instance->publish(dest, req_id, subject, error, data); +} + +void conv::dbus_server::call(const char *dest, const char *obj, const char *iface, const char *method, GVariant *param) +{ + _instance->call(dest, obj, iface, method, param); +} + +void conv::dbus_server::set_instance(conv::dbus_server_iface* svr) +{ + _instance = static_cast(svr); +} diff --git a/daemon/dbus_server_impl.h b/daemon/dbus_server_impl.h new file mode 100644 index 0000000..3e45955 --- /dev/null +++ b/daemon/dbus_server_impl.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_DBUS_SERVER_IMPL_H__ +#define __CONV_DBUS_SERVER_IMPL_H__ + +#include +#include +#include "dbus_server_iface.h" + +namespace conv { + class dbus_server_impl : public dbus_server_iface { + public: + dbus_server_impl(); + ~dbus_server_impl(); + + bool init(); + void release(); + + void publish(const char *dest, int req_id, const char *subject, int error, const char *data); + void call(const char *dest, const char *obj, const char *iface, const char *method, GVariant *param); + }; /* class conv::dbus_server */ + + namespace dbus_server { + void publish(const char *dest, int req_id, const char *subject, int error, const char *data); + void call(const char *dest, const char *obj, const char *iface, const char *method, GVariant *param); + void set_instance(dbus_server_iface* svr); + } +} /* namespace conv */ + +#endif /* End of __CONV_DBUS_SERVER_IMPL_H__ */ diff --git a/daemon/device.cpp b/daemon/device.cpp new file mode 100644 index 0000000..3f048d9 --- /dev/null +++ b/daemon/device.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "device.h" +#include "log.h" +#include "d2d_conv_manager.h" + +using namespace std; + +conv::device::device() +{ +} + +conv::device::~device() +{ +} + +int conv::device::add_service(service_iface* service_obj) +{ + service_list.push_back(service_obj); + return CONV_ERROR_NONE; +} + +int conv::device::remove_service(service_iface* service_obj) +{ + return CONV_ERROR_NONE; +} + +string conv::device::getName() +{ + return name; +} + +string conv::device::getId() +{ + return id; +} + +string conv::device::getAddress() +{ + return ip_address; +} + +int conv::device::get_services_list(std::list *list) +{ + for (service_list_t::iterator iterPos = service_list.begin(); iterPos != service_list.end(); ++iterPos) + { + list->push_back(*iterPos); + } + return CONV_ERROR_NONE; +} + + +int conv::device::setName(string name) +{ + this->name = name; + return CONV_ERROR_NONE; +} + +int conv::device::setId(string id) +{ + this->id = id; + return CONV_ERROR_NONE; +} + +int conv::device::setAddress(string id) +{ + ip_address = id; + return CONV_ERROR_NONE; +} diff --git a/daemon/device.h b/daemon/device.h new file mode 100644 index 0000000..5e7c380 --- /dev/null +++ b/daemon/device.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_DEVICE_H__ +#define __CONV_DEVICE_H__ + +#include +#include +#include "service_iface.h" +#include "conv_json.h" + +#include "device_iface.h" + +namespace conv { + class device : public device_iface { + public: + typedef std::vector service_list_t; + device(); + ~device(); + + // functions from device_iface + int add_service(service_iface* service_obj); + int remove_service(service_iface* service_obj); + int get_services_list(std::list *list); + std::string getName(); + std::string getId(); + std::string getAddress(); + int setName(std::string name); + int setId(std::string id); + int setAddress(std::string host_address); + + private: + service_list_t service_list; + + protected: + std::string id; + std::string ip_address; + std::string name; + std::string type; + std::string wd_mac_address; + std::string bt_mac_address; + }; +} + +#endif /* End of __CONV_DEVICE_H__ */ diff --git a/daemon/device_iface.h b/daemon/device_iface.h new file mode 100644 index 0000000..e19137f --- /dev/null +++ b/daemon/device_iface.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _DEVICE_INTERFACE_H__ +#define _DEVICE_INTERFACE_H__ + +#include "service_iface.h" +#include +#include + +using namespace std; + +namespace conv { + class device_iface { + public: + virtual ~device_iface() {} + + virtual int add_service(service_iface* service_obj) = 0; + virtual int remove_service(service_iface* service_obj) = 0; + virtual int get_services_list(std::list *list) = 0; + + virtual string getName() = 0; + virtual string getId() = 0; + virtual string getAddress() = 0; + }; +} + +#endif diff --git a/daemon/discovery_mgr_impl.cpp b/daemon/discovery_mgr_impl.cpp new file mode 100644 index 0000000..b8eab9e --- /dev/null +++ b/daemon/discovery_mgr_impl.cpp @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "discovery_mgr_impl.h" +#include "discovery_provider/smartview_discovery_provider.h" +#include "discovery_provider/ble_discovery_provider.h" +#include "discovery_provider/iotcon_discovery_provider.h" +#include "access_control/privilege.h" + +#include "common.h" +#include "util.h" + +static conv::discovery_manager_impl *_instance = NULL; +typedef std::map discovered_ones_map_t; +static discovered_ones_map_t discovered_results; + +using namespace std; + +conv::discovery_manager_impl::discovery_manager_impl() +{ + count_discovery_request = 0; +} + +conv::discovery_manager_impl::~discovery_manager_impl() +{ +} + +int conv::discovery_manager_impl::init() +{ + _D("Discovery_Manager Init!!.."); + register_provider(new conv::smartview_discovery_provider()); + register_provider(new conv::ble_discovery_provider()); + register_provider(new conv::iotcon_discovery_provider()); + + request_map.clear(); + request_timer_map.clear(); + + + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::release() +{ + for (discovery_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + (*it)->stop(); + } + + for (discovery_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + delete *it; + } + + provider_list.clear(); + + return CONV_ERROR_NONE; +} + +void conv::discovery_manager::set_instance(conv::discovery_manager_impl* mgr) +{ + _instance = mgr; +} + +int conv::discovery_manager_impl::notify_time_up(std::string client) +{ + // 1. When no client is using discovery, it should be stopped + _D("notify_time_up.. with current discovery count :%d", count_discovery_request); + if (--count_discovery_request == 0) + { + stop_discovery(); + } + + // 2. Reqeust to stop timer related to client in the timer_map + timer_map_t::iterator timer_itr = request_timer_map.find(client); + if (timer_itr != request_timer_map.end()) + { + int timer_id = timer_itr->second; + _D("timer_id[%d]", timer_id); + conv::util::misc_stop_timer(reinterpret_cast (timer_id)); + } + + // 3. Notify the client that the requested discovery has been finished + request_map_t::iterator request_itr = request_map.find(client); + if (request_itr != request_map.end()) + { + json no_data; + request* cur_Req = request_itr->second; + cur_Req->publish(CONV_DISCOVERY_FINISHED, no_data); + } + + return CONV_ERROR_NONE; +} + +void conv::discovery_manager_impl::timer_worker(void* data) +{ + gpointer* param = reinterpret_cast (data); + std::string* req_client = reinterpret_cast (param[0]); + conv::discovery_manager_impl* cur_disc_mgr = reinterpret_cast (param[1]); + + _D("Timer_Worker.. req_client[%s] discovery_manager[%x]", (*req_client).c_str(), cur_disc_mgr); + + cur_disc_mgr->notify_time_up(*req_client); +} + +int conv::discovery_manager_impl::checkBoundaryForTimeout(int givenTimeout) +{ + if ( givenTimeout < CONV_DISCOVERY_MIN_VALUE ) + return CONV_DISCOVERY_MIN_VALUE; + else if ( givenTimeout > CONV_DISCOVERY_MAX_VALUE ) + return CONV_DISCOVERY_MAX_VALUE; + else + return givenTimeout; +} + +int conv::discovery_manager_impl::handle_request(request* request_obj) +{ + _D("handle_request called .. request:%x _instance:%x", request_obj, _instance); + if ( _instance ) + { + if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_DISCOVERY_START) ) + { + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + + discovered_results.clear(); + count_discovery_request++; + + for (discovery_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) + { + // Discovery Provider Starts!!!! + (*it)->start(); + } + + const char* client = request_obj->get_sender(); + if (client == NULL) + { + _D("client is empty.."); + return CONV_ERROR_INVALID_OPERATION; + } + _D("request_obj info .. client[%s]", client); + + int timeout = 0; + json description = request_obj->get_description(); + description.get(NULL, "timeout", &timeout); + timeout = checkBoundaryForTimeout(timeout); + + request_map_t::iterator map_itr = request_map.find(string(client)); + + if ( map_itr == request_map.end()) + { + // current request inserted into request_map.. + request_map.insert(request_map_t::value_type(string(client), request_obj)); + _D("client[%s] inserted into request_map", client); + } + else + { + _D("client[%s] already in request_map.. Replace!!!", client); + map_itr->second = request_obj; + } + + // request timer + gpointer *param = g_new0(gpointer, 2); + param[0] = reinterpret_cast(new string(client)); + param[1] = reinterpret_cast(this); + + int timer_id = reinterpret_cast(conv::util::misc_start_timer(timer_worker, timeout, param)); + request_timer_map[ string(client) ] = timer_id; + + request_obj->reply(CONV_ERROR_NONE); + + //delete request_obj; + } else if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_DISCOVERY_STOP) ){ + stop_discovery(); + + request_obj->reply(CONV_ERROR_NONE); + //delete request_obj; + } + + return CONV_ERROR_NONE; + } + + return CONV_ERROR_INVALID_OPERATION;; +} + +int conv::discovery_manager_impl::start_discovery() +{ + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::stop_discovery() +{ + _D("Stop_Discovery..."); + for (discovery_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + (*it)->stop(); + } + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::register_provider(discovery_provider_base *provider) +{ + if (!provider) { + _E("Provider NULL"); + throw static_cast(CONV_ERROR_INVALID_PARAMETER); + } + + provider_list.push_back(provider); + + if (provider->init() != CONV_ERROR_NONE) { + _E("Provider initialization failed"); + throw CONV_ERROR_INVALID_OPERATION; + } + + if (provider->set_manager(this) != CONV_ERROR_NONE) { + _E("Provider set_manager failed"); + throw CONV_ERROR_INVALID_OPERATION; + } + return CONV_ERROR_NONE; +} +int conv::discovery_manager_impl::convert_device_into_json(conv::device_iface* device_info, json* json_data) +{ + json_data->set(NULL, CONV_JSON_DEVICE_ID, device_info->getId()); + json_data->set(NULL, CONV_JSON_DEVICE_NAME, device_info->getName()); + json_data->set(NULL, CONV_JSON_DEVICE_ADDRESS, device_info->getAddress()); + + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::convert_service_into_json(conv::service_iface* service_info, json* json_data) +{ + string service_info_str = service_info->getServiceInfo(); + _D("Service-2-Json Conversion : %s", service_info_str.c_str()); + json service_json(service_info_str); + json_data->array_append(CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA, service_json); + json_data->array_append(CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_TYPE, service_info->getServiceType()); + + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::append_discovered_result(conv::device_iface* disc_device, conv::service_iface* disc_service) +{ + _D("Append Discovered Result.. Device:%x, Service:%x"); + IF_FAIL_RETURN_TAG((disc_device != NULL), CONV_ERROR_INVALID_PARAMETER, _E, "device_iface not initialized.."); + // discovery_manager deals with the cache for discovered ones + _D("Check if key[%s] exists in discovered_results", disc_device->getId().c_str()); + discovered_ones_map_t::iterator itor_disc; + itor_disc = discovered_results.find(disc_device->getId()); + if (itor_disc != discovered_results.end()) + { + _D("update discovered device's info [%s]", disc_device->getId().c_str()); + device_iface* cur_device = itor_disc->second; + cur_device->add_service(disc_service); + } + else + { + _D("newbie!! discovered device's info [%s]", disc_device->getId().c_str()); + discovered_results.insert(discovered_ones_map_t::value_type(disc_device->getId(), disc_device)); + } + + _D("Convert device_info into json type.."); + json device_json; + convert_device_into_json(disc_device, &device_json); + + _D("Convert service info into json type.."); + if (disc_service !=NULL) + convert_service_into_json(disc_service, &device_json); + else + { + typedef std::list serv_list_t; + serv_list_t serv_list; + disc_device->get_services_list(&serv_list); + + for (serv_list_t::iterator iterPos = serv_list.begin(); iterPos != serv_list.end(); ++iterPos) + { + service_iface* cur_serv = *iterPos; + convert_service_into_json(cur_serv, &device_json); + } + } + + // 1.set data info about device + + // 2.set data info about services included in 'device' + // iterate through request_map for service + _D("Iterate through request_map to publish.."); + int index = 0; + request_map_t::iterator IterPos; + for (IterPos = request_map.begin(); IterPos != request_map.end(); ++IterPos) + { + request* cur_Req = IterPos->second; + cur_Req->publish(CONV_ERROR_NONE, device_json); + + index++; + } + + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::set_discovery_filter(request* request_obj) +{ + json desc_data = request_obj->get_description(); + json filter_data; + desc_data.get(NULL, "filter", &filter_data); + discovery_filter_map.insert(filter_map_t::value_type(request_obj->get_id(), filter_data)); + + return CONV_ERROR_NONE; +} + +int conv::discovery_manager_impl::isvalid_discovery_on_filter(json& filter_json) +{ + return CONV_ERROR_NONE; +} + +int conv::discovery_manager::handle_request(request* request_obj) +{ + IF_FAIL_RETURN_TAG(_instance, CONV_ERROR_INVALID_PARAMETER, _E, "Not initialized"); + _instance->handle_request(request_obj); + + return CONV_ERROR_NONE; +} diff --git a/daemon/discovery_mgr_impl.h b/daemon/discovery_mgr_impl.h new file mode 100644 index 0000000..e06929a --- /dev/null +++ b/daemon/discovery_mgr_impl.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DISCOVERY_MANAGER_IMPL_H__ +#define __DISCOVERY_MANAGER_IMPL_H__ + +#include +#include +#include +#include + +#include "manager_iface.h" +#include "discovery_provider_base.h" +#include "request.h" + +#include "device_iface.h" +#include "service_iface.h" + +namespace conv { + class request; + class device; + + class discovery_manager_impl : public manager_iface { + public: + discovery_manager_impl(); + ~discovery_manager_impl(); + + int init(); + int release(); + int handle_request(request* request_obj); + + // discovery_manager aggregates devices with services which have been discovered through the registered discover providers + int append_discovered_result(device_iface* disc_device, service_iface* disc_service); + int notify_time_up(std::string client); + int stop_discovery(); + int start_discovery(); + + static void timer_worker(void* data); + + private: + int count_discovery_request; + + + typedef std::list discovery_provider_list_t; + typedef std::map request_map_t; + typedef std::map filter_map_t; + typedef std::map timer_map_t; + + int register_provider(discovery_provider_base *provider_base); + discovery_provider_list_t provider_list; + request_map_t request_map; + filter_map_t discovery_filter_map; + timer_map_t request_timer_map; + + // internal function + int convert_service_into_json(conv::service_iface* service_info, json* json_data); + int convert_device_into_json(conv::device_iface* service_info, json* json_data); + int set_discovery_filter(request* req_obj); + int isvalid_discovery_on_filter(json& filter_json); + int checkBoundaryForTimeout(int givenTimeout); + }; + + namespace discovery_manager { + void set_instance(discovery_manager_impl* mgr); + int handle_request(request* request_obj); + int set_result(device* device_obj); + }; +} + +#endif /* __DISCOVERY_MANAGER_IMPL_H__ */ diff --git a/daemon/discovery_provider/ble_discovery_provider.cpp b/daemon/discovery_provider/ble_discovery_provider.cpp new file mode 100644 index 0000000..9e3825c --- /dev/null +++ b/daemon/discovery_provider/ble_discovery_provider.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ble_discovery_provider.h" +#include "../discovery_mgr_impl.h" + +#include +#include + +#define TEMP_TEST + +#define MACSTR_LEN 18 +#define MAX_PEER_NUM 20 + +using namespace std; + +conv::ble_discovery_provider::ble_discovery_provider() +{ +} + +conv::ble_discovery_provider::~ble_discovery_provider() +{ +} + +void _cb_activation(int error_code, wifi_direct_device_state_e device_state, void *user_data) +{ + switch (device_state) { + case WIFI_DIRECT_DEVICE_STATE_ACTIVATED: + _D("event -WIFI_DIRECT_DEVICE_STATE_ACTIVATED"); + break; + + case WIFI_DIRECT_DEVICE_STATE_DEACTIVATED: + _D("event - WIFI_DIRECT_DEVICE_STATE_DEACTIVATED"); + break; + + default: + break; + } +} + +bool _cb_discovered_peers_impl(wifi_direct_discovered_peer_info_s* peer, void* user_data) +{ +// conv::ble_discovery_provider* disc_provider = (conv::ble_discovery_provider*)user_data; + +// conv::service *conv_service = new conv::service; + +#if 0//def TEMP_TEST + static int first = 1; + if (!strcmp(peer->device_name, "D2d note" ) ) { + first = 0; + int result = wifi_direct_connect(peer->mac_address); + _D("connect result = %d", result); + } +#endif + +#if 0 // TODO: make and notice if it's device support d2d + conv_service->setName(peer->device_name); + conv_service->setVersion("0.0"); + conv_service->setType(""); + conv_service->setId(peer->mac_address); + conv_service->setUri(""); + + disc_provider->notice_discovered(conv_service); +#endif + + if (NULL != peer) { + _D("device_name : %s", peer->device_name); + } + + return true; /* continue with the next iteration of the loop */ +} + +void _cb_discover(int error_code, wifi_direct_discovery_state_e discovery_state, void *user_data) +{ + switch (discovery_state) { + case WIFI_DIRECT_DISCOVERY_STARTED: + _D("_cb_discover - WIFI_DIRECT_DISCOVERY_STARTED"); + break; + + case WIFI_DIRECT_ONLY_LISTEN_STARTED: + _D("_cb_discover - WIFI_DIRECT_ONLY_LISTEN_STARTED"); + break; + + case WIFI_DIRECT_DISCOVERY_FINISHED: + wifi_direct_foreach_discovered_peers(_cb_discovered_peers_impl, user_data); + _D("_cb_discover - WIFI_DIRECT_DISCOVERY_FINISHED"); + break; + + case WIFI_DIRECT_DISCOVERY_FOUND: + { + _D("_cb_discover - WIFI_DIRECT_DISCOVERY_FOUND"); + } + break; + + default: + break; + } +} + +bool _cb_connected_peers_impl(wifi_direct_connected_peer_info_s* peer, void* user_data) +{ + _D("_cb_connected_peers_impl - %s", peer->ip_address); + + return true; /* continue with the next iteration of the loop */ +} + +void _cb_connection(int error_code, wifi_direct_connection_state_e connection_state, const char* mac_address, void *user_data) +{ + char *ip_addr = NULL; + bool owner; + + switch (connection_state) { + case WIFI_DIRECT_CONNECTION_IN_PROGRESS: + { + _D("event - WIFI_DIRECT_CONNECTION_IN_PROGRESS"); + + if (error_code == WIFI_DIRECT_ERROR_NONE) { + char _peer_mac[MACSTR_LEN+1]={0, }; + + if (NULL != mac_address) + g_strlcpy(_peer_mac, mac_address, sizeof(_peer_mac)); + + _D("Connection start with [%s] ", _peer_mac); + } + } + break; + + case WIFI_DIRECT_CONNECTION_RSP: + { + _D("event - WIFI_DIRECT_CONNECTION_RSP"); + +#ifdef TEMP_TEST + wifi_direct_foreach_connected_peers(_cb_connected_peers_impl, NULL); +#endif + + if (error_code == WIFI_DIRECT_ERROR_NONE) { + char incomming_peer_mac[MACSTR_LEN+1]={0, }; + char status[100] = {0, }; + + if (NULL != mac_address) + g_strlcpy(incomming_peer_mac, mac_address, sizeof(incomming_peer_mac)); + + _D("Connection response with [%s] ", incomming_peer_mac); + + wifi_direct_is_group_owner(&owner); + if (owner) { + wifi_direct_get_ip_address(&ip_addr); + if (NULL != ip_addr) { + sprintf(status, "GO - IP : %s", ip_addr); + free(ip_addr); + } + + } else { + wifi_direct_get_ip_address(&ip_addr); + if (NULL != ip_addr) { + sprintf(status, "STA - IP : %s", ip_addr); + free(ip_addr); + } + } + } else { + if (error_code == WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT) + _D("Error Code - WIFI_DIRECT_ERROR_CONNECTION_TIME_OUT"); + else if (error_code == WIFI_DIRECT_ERROR_AUTH_FAILED) + _D("Error Code - WIFI_DIRECT_ERROR_AUTH_FAILED"); + else if (error_code == WIFI_DIRECT_ERROR_CONNECTION_FAILED) + _D("Error Code - WIFI_DIRECT_ERROR_CONNECTION_FAILED"); + } + } + break; + + case WIFI_DIRECT_CONNECTION_WPS_REQ: + { + _D("event - WIFI_DIRECT_CONNECTION_WPS_REQ"); + } + break; + + case WIFI_DIRECT_CONNECTION_REQ: + { + _D("event - WIFI_DIRECT_CONNECTION_REQ"); + } + break; + + case WIFI_DIRECT_DISCONNECTION_IND: + { + _D("event - WIFI_DIRECT_DISCONNECTION_IND"); + + if (error_code == WIFI_DIRECT_ERROR_NONE) { + char incomming_peer_mac[MACSTR_LEN+1]={0, }; + + if (NULL != mac_address) + g_strlcpy(incomming_peer_mac, mac_address, sizeof(incomming_peer_mac)); + + _D("Disconnection IND from [%s] ", incomming_peer_mac); + } + } + break; + + case WIFI_DIRECT_DISCONNECTION_RSP: + { + _D("event - WIFI_DIRECT_DISCONNECTION_RSP"); + + if (error_code == WIFI_DIRECT_ERROR_NONE) { + char incomming_peer_mac[MACSTR_LEN+1]={0, }; + + if (NULL != mac_address) + g_strlcpy(incomming_peer_mac, mac_address, sizeof(incomming_peer_mac)); + + _D("Disconnection RSP with [%s] ", incomming_peer_mac); + } + } + break; + + case WIFI_DIRECT_DISASSOCIATION_IND: + { + _D("event - WIFI_DIRECT_DISASSOCIATION_IND"); + + if (error_code == WIFI_DIRECT_ERROR_NONE) { + char incomming_peer_mac[MACSTR_LEN+1]={0, }; + + if (NULL != mac_address) + g_strlcpy(incomming_peer_mac, mac_address, sizeof(incomming_peer_mac)); + + _D("Disassociation IND from [%s] ", incomming_peer_mac); + } + } + break; + + case WIFI_DIRECT_GROUP_CREATED: + { + _D("event - WIFI_DIRECT_GROUP_CREATED"); + } + break; + + case WIFI_DIRECT_GROUP_DESTROYED: + { + _D("event - WIFI_DIRECT_GROUP_DESTROYED"); + } + break; + + default: + break; + } +} + +int init_wfd_client(void* disc_provider) +{ + int ret; + + ret = wifi_direct_initialize(); + _D("wifi_direct_initialize() result=[%d]", ret); + + ret = wifi_direct_set_device_state_changed_cb(_cb_activation, (void*)NULL); + _D("wifi_direct_set_device_state_changed_cb() result=[%d]", ret); + + ret = wifi_direct_set_discovery_state_changed_cb(_cb_discover, disc_provider); + _D("wifi_direct_set_discovery_state_changed_cb() result=[%d]", ret); + + ret = wifi_direct_set_connection_state_changed_cb(_cb_connection, (void*)NULL); + _D("wifi_direct_set_connection_state_changed_cb() result=[%d]", ret); + +#if defined(TIZEN_TV) && defined(TIZEN_TV_PRODUCT) && defined(ENABLE_EXTRA_INFO) + ret = wifi_direct_set_peer_info_connection_state_changed_cb(_cb_peer_info_connection, (void*)NULL); + _D("wifi_direct_set_peer_info_connection_state_changed_cb() result=[%d]", ret); +#endif /* defined(TIZEN_TV) && defined(TIZEN_TV_PRODUCT) && defined(ENABLE_EXTRA_INFO) */ + + return ret; +} + +int start_wfd_discovery(void) +{ + int result; + connection_h connection; + connection_wifi_state_e wifi_state; + + IF_FAIL_RETURN_TAG(connection_create(&connection) == CONNECTION_ERROR_NONE, CONV_ERROR_NOT_SUPPORTED, _E, "connection error"); + result = connection_get_wifi_state(connection, &wifi_state); + if ((result != CONNECTION_ERROR_NONE) || (wifi_state == CONNECTION_WIFI_STATE_DEACTIVATED)) { + _E("ERROR : wifi is not on!"); + connection_destroy(connection); + return CONV_ERROR_NOT_SUPPORTED; + } + connection_destroy(connection); + + result = wifi_direct_activate(); + _D("wifi_direct_activate() result=[%d]", result); + + if (result == WIFI_DIRECT_ERROR_WIFI_USED) { + _E("ERROR : WIFI_DIRECT_ERROR_WIFI_USED "); + } else if (result == WIFI_DIRECT_ERROR_MOBILE_AP_USED) { + _E("ERROR : WIFI_DIRECT_ERROR_MOBILE_AP_USED "); + } + + result = wifi_direct_start_discovery(FALSE, 5); + _D("wifi_direct_start_discovery() listen_only=[false] result=[%d]", result); + + return result; +} +int conv::ble_discovery_provider::init() +{ + init_wfd_client((void*)this); + + return CONV_ERROR_NONE; +} + +int conv::ble_discovery_provider::release() +{ + return CONV_ERROR_NONE; +} + +int conv::ble_discovery_provider::start() +{ + return start_wfd_discovery(); +} + +int conv::ble_discovery_provider::stop() +{ + return CONV_ERROR_NONE; +} + +int conv::ble_discovery_provider::set_manager(discovery_manager_impl* disc_manager) +{ + discovery_manager = disc_manager; + return CONV_ERROR_NONE; +} + +int conv::ble_discovery_provider::checkExistence(conv::service* conv_service) +{ + // print conv_service Info.. + _D("Check Existence : %s", conv_service->getName().c_str()); + conv_service->printInfo(); + + // insert into cache + string cache_key = conv_service->getId(); // Serivce URI as Map Key.. + if (cache.find(cache_key) == cache.end()) + { + _D("conv_service with key[%s] does not exist..so go into the cache", cache_key.c_str()); + cache.insert(map::value_type(cache_key, conv_service)); + return CONV_ERROR_NONE; + } + else + { + _D("conv_service with key[%s] already exists..", cache_key.c_str()); + return 1; // temp.. + } +} + +int conv::ble_discovery_provider::notice_discovered(conv::service* conv_service) +{ + _D("Notice Discovered called with service[%x]", conv_service); + + // Double check if the noticed one already got delivered to.. + int alreadyExisted = checkExistence(conv_service); + _D("double check .. existence[%s]", (alreadyExisted == 0)? "No" : "Yes"); + + if (!alreadyExisted) { + //the discovered one is NEW!! + discovery_manager->append_discovered_result(NULL, conv_service); + } + + return CONV_ERROR_NONE; +} + diff --git a/daemon/discovery_provider/ble_discovery_provider.h b/daemon/discovery_provider/ble_discovery_provider.h new file mode 100644 index 0000000..1f7c71e --- /dev/null +++ b/daemon/discovery_provider/ble_discovery_provider.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BLE_DISCOVERY_PROVIDER_H__ +#define __BLE_DISCOVERY_PROVIDER_H__ + +#include +#include +#include +#include + +#include "../discovery_provider_base.h" +#include "../request.h" +#include "../service.h" + +namespace conv { + class ble_discovery_provider : public discovery_provider_base { + public: + ble_discovery_provider(); + ~ble_discovery_provider(); + + int init(); + int release(); + + int start(); + int stop(); + + int set_manager(discovery_manager_impl* disc_manager); + int notice_discovered(conv::service* conv_service); + + private: + discovery_manager_impl* discovery_manager; + + // for double check.. + map cache; + + int checkExistence(conv::service* conv_service); + }; +} +#endif /* __BLE_DISCOVERY_PROVIDER_H__ */ diff --git a/daemon/discovery_provider/iotcon/device_adapter.cpp b/daemon/discovery_provider/iotcon/device_adapter.cpp new file mode 100644 index 0000000..0129d2f --- /dev/null +++ b/daemon/discovery_provider/iotcon/device_adapter.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device_adapter.h" + +using namespace std; + +conv::device_adapter::device_adapter(resource_handle res_h) +{ + this->m_resource_h = res_h; +} + +conv::device_adapter::~device_adapter() +{ +} + +int conv::device_adapter::add_service(service_iface* service_obj) +{ + service_list.push_back(service_obj); + return CONV_ERROR_NONE; +} + +int conv::device_adapter::remove_service(service_iface* service_obj) +{ + service_list.remove(service_obj); + return CONV_ERROR_NONE; +} + +string conv::device_adapter::getName() +{ + return m_resource_h.get_device_name(); +} + +string conv::device_adapter::getId() +{ + return m_resource_h.get_device_id(); +} + +string conv::device_adapter::getAddress() +{ + return m_resource_h.get_host_address(); +} + +int conv::device_adapter::get_services_list(std::list *list) +{ + for (service_list_t::iterator iterPos = service_list.begin(); iterPos != service_list.end(); ++iterPos) + { + list->push_back(*iterPos); + } + return CONV_ERROR_NONE; +} diff --git a/daemon/discovery_provider/iotcon/device_adapter.h b/daemon/discovery_provider/iotcon/device_adapter.h new file mode 100644 index 0000000..3055f4e --- /dev/null +++ b/daemon/discovery_provider/iotcon/device_adapter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEVICE_ADAPTER_H__ +#define __DEVICE_ADAPTER_H__ + +#include "../../device_iface.h" +#include "resource_handle.h" +#include +#include + +namespace conv { + class device_adapter : public device_iface { + public : + typedef std::list service_list_t; + device_adapter(resource_handle res_h); + ~device_adapter(); + + int add_service(service_iface* service_obj); + int remove_service(service_iface* service_obj); + int get_services_list(std::list *list); + string getName(); + string getId(); + string getAddress(); + + private : + resource_handle m_resource_h; + service_list_t service_list; + }; +} + +#endif diff --git a/daemon/discovery_provider/iotcon/resource_handle.cpp b/daemon/discovery_provider/iotcon/resource_handle.cpp new file mode 100644 index 0000000..fe78726 --- /dev/null +++ b/daemon/discovery_provider/iotcon/resource_handle.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "resource_handle.h" +#include "d2d_conv_manager.h" + +using namespace std; + + +int conv::resource_handle::set_device_id(string dev_id) +{ + this->device_id = dev_id; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_device_id() +{ + return this->device_id; +} + +int conv::resource_handle::set_device_name(string dev_name) +{ + this->device_name = dev_name; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_device_name() +{ + return device_name; +} + +int conv::resource_handle::set_device_type(string dev_type) +{ + this->device_type = dev_type; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_device_type() +{ + return device_type; +} + +int conv::resource_handle::set_version(string ver) +{ + this->version = ver; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_version() +{ + return version; +} + +int conv::resource_handle::set_services_list(string list) +{ + this->services_list = json(list); + return CONV_ERROR_NONE; +} + +int conv::resource_handle::set_uri_path(string uri_path) +{ + this->uri_path = uri_path; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_uri_path() +{ + return uri_path; +} + +int conv::resource_handle::set_host_address(string host_address) +{ + this->host_address = host_address; + return CONV_ERROR_NONE; +} + +string conv::resource_handle::get_host_address() +{ + return host_address; +} + +list& conv::resource_handle::get_types() +{ + return types; +} + +int conv::resource_handle::add_types(string type) +{ + types.push_back(type); + return CONV_ERROR_NONE; +} + +list& conv::resource_handle::get_interfaces() +{ + return interfaces; +} + +int conv::resource_handle::add_interfaces(string interface) +{ + interfaces.push_back(interface); + return CONV_ERROR_NONE; +} + + diff --git a/daemon/discovery_provider/iotcon/resource_handle.h b/daemon/discovery_provider/iotcon/resource_handle.h new file mode 100644 index 0000000..7640690 --- /dev/null +++ b/daemon/discovery_provider/iotcon/resource_handle.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RESOURCE_HANDLE_H__ +#define _RESOURCE_HANDLE_H__ + +#include +#include +#include "../../conv_json.h" + +using namespace std; + +namespace conv{ +class resource_handle { + private: + string uri_path; + string host_address; + list types; + list interfaces; + + string device_id; + string device_name; + string device_type; + string version; + json services_list; + + public: + int set_device_id(string dev_id); + string get_device_id(); + int set_device_name(string dev_name); + string get_device_name(); + int set_device_type(string dev_type); + string get_device_type(); + int set_version(string ver); + string get_version(); + int set_services_list(string list); + + int set_uri_path(string uri_path); + string get_uri_path(); + int set_host_address(string host_address); + string get_host_address(); + list& get_types(); + int add_types(string type); + list& get_interfaces(); + int add_interfaces(string interface); +}; +} +#endif diff --git a/daemon/discovery_provider/iotcon/service_adapter.cpp b/daemon/discovery_provider/iotcon/service_adapter.cpp new file mode 100644 index 0000000..d37e7a4 --- /dev/null +++ b/daemon/discovery_provider/iotcon/service_adapter.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_adapter.h" + +using namespace std; + +conv::service_adapter::service_adapter(resource_handle res_h) +{ + this->m_resource_h = res_h; +} + +conv::service_adapter::~service_adapter() +{ +} + +string conv::service_adapter::getName() +{ + return m_resource_h.get_device_name(); +} + +string conv::service_adapter::getVersion() +{ + return m_resource_h.get_version(); +} + +string conv::service_adapter::getType() +{ + return m_resource_h.get_device_type(); +} + +string conv::service_adapter::getId() +{ + return m_resource_h.get_device_id(); +} + +string conv::service_adapter::getUri() +{ + string uri_path = m_resource_h.get_uri_path(); + string host_address = m_resource_h.get_host_address(); + + return host_address + uri_path; +} + +int conv::service_adapter::getServiceType() +{ + return service_type; +} + +int conv::service_adapter::setServiceType(int serviceType) +{ + this->service_type = serviceType; + return CONV_ERROR_NONE; +} + +int conv::service_adapter::setServiceInfo(string serviceInfo) +{ + this->service_info = serviceInfo; + return CONV_ERROR_NONE; +} + +string conv::service_adapter::getServiceInfo() +{ + return service_info; +} diff --git a/daemon/discovery_provider/iotcon/service_adapter.h b/daemon/discovery_provider/iotcon/service_adapter.h new file mode 100644 index 0000000..d179680 --- /dev/null +++ b/daemon/discovery_provider/iotcon/service_adapter.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SERVICE_ADAPTER_H__ +#define __SERVICE_ADAPTER_H__ + +#include "../../service_iface.h" +#include "resource_handle.h" + +namespace conv { + + class service_adapter : public service_iface { + public: + service_adapter(resource_handle res_h); + ~service_adapter(); + + string getName(); + string getVersion(); + string getType(); + string getId(); + string getUri(); + int getServiceType(); + string getServiceInfo(); + + int setServiceType(int serviceType); + int setServiceInfo(string serviceInfo); + + private: + resource_handle m_resource_h; + + int service_type; + string service_info; + }; + +} + +#endif diff --git a/daemon/discovery_provider/iotcon_discovery_provider.cpp b/daemon/discovery_provider/iotcon_discovery_provider.cpp new file mode 100644 index 0000000..d426120 --- /dev/null +++ b/daemon/discovery_provider/iotcon_discovery_provider.cpp @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iotcon_discovery_provider.h" + +#include +#include +#include +#include "iotcon/resource_handle.h" +#include "../conv_json.h" + +#include "../discovery_mgr_impl.h" +#include "iotcon/service_adapter.h" +#include "iotcon/device_adapter.h" + +#include "../util.h" + +using namespace std; + +typedef std::map resource_h_map_t; +static resource_h_map_t* resource_h_map = NULL; + +typedef std::list discovery_complete_list_t; +typedef std::map discovery_process_map_t; +static discovery_complete_list_t discovery_complete_list; +static discovery_process_map_t discovery_process_map; + +static conv::discovery_manager_impl* disc_manager; + +conv::iotcon_discovery_provider::iotcon_discovery_provider() +{ +} + +conv::iotcon_discovery_provider::~iotcon_discovery_provider() +{ +} + +int conv::iotcon_discovery_provider::init() +{ + int ret = iotcon_initialize(); + if (ret != IOTCON_ERROR_NONE) { + _E("Failed iotcon_connect... Error:%d", ret); + } + + if (resource_h_map != NULL) delete resource_h_map; + resource_h_map = new (std::nothrow) resource_h_map_t; + + return CONV_ERROR_NONE; +} + +int conv::iotcon_discovery_provider::release() +{ + iotcon_deinitialize(); + + if (resource_h_map != NULL) delete resource_h_map; + + return CONV_ERROR_NONE; +} + +static bool _get_resource_foreach_types(const char* type, void* user_data) +{ + _D("resource type : %s", type); + + list* list_types = (list*) user_data; + list_types->push_back(string(type)); + + return true; +} + +static bool response_state_cb(iotcon_state_h state, const char* key, void* user_data) +{ + _D("response_state_cb with the key[%s]", key); + return true; +} + +int conv::iotcon_discovery_provider::notice_discovered(service_iface* service) +{ + return CONV_ERROR_NONE; +} + +void conv::iotcon_discovery_provider::_on_response_get(iotcon_remote_resource_h resource, + iotcon_response_h response, void* user_data) +{ + _D("On Response Get.."); + + int ret; + iotcon_response_result_e response_result; + iotcon_representation_h recv_repr; + iotcon_state_h recv_state; + + unsigned int key_count; + + // uri_path , host_address + char *resource_uri_path, *resource_host; + iotcon_remote_resource_get_uri_path(resource, &resource_uri_path); + iotcon_remote_resource_get_host_address(resource, &resource_host); + + // Check if it's already done publishing.. + string discoveryKey = generateDiscoveryKey(resource_uri_path, resource_host); + discovery_complete_list_t::iterator itor; + _D("Check if key[%s] already exists in complete_list", discoveryKey.c_str()); + itor = find(discovery_complete_list.begin(), discovery_complete_list.end(), discoveryKey); + if (itor != discovery_complete_list.end() ) return; // Already done pushing upwards.. + + // Retreive info from process_map.. + resource_handle cur_resource_h; + discovery_process_map_t::iterator itor_process; + itor_process = discovery_process_map.find(discoveryKey); + _D("Check if key[%s] exists in process_map", discoveryKey.c_str()); + if (itor_process != discovery_process_map.end()) + cur_resource_h = itor_process->second; + else + { + _D("Not supposed to happen"); + return; + } + + + //============= Dealing with Response ==============// + + ret = iotcon_response_get_result(response, &response_result); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "Failed[%d] to get response result", ret); + IF_FAIL_VOID_TAG((response_result == IOTCON_RESPONSE_OK), _E, + "_on_response_get Response Error[%d]", response_result); + + ret = iotcon_response_get_representation(response, &recv_repr); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_response_get_representation() Fail[%d]", ret); + + ret = iotcon_representation_get_state(recv_repr, &recv_state); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_representation_get_state() Fail[%d]", ret); + + ret = iotcon_state_get_keys_count(recv_state, &key_count); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_state_get_keys_count() Fail[%d]", ret); + _D("state key count : %d", key_count); + + ret = iotcon_state_foreach(recv_state, response_state_cb, NULL); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_state_for_each() Fail[%d]", ret); + + char *device_id = NULL, *device_name = NULL, *device_type = NULL, *version = NULL, *service_list = NULL; + ret = iotcon_state_get_str(recv_state, "device_id", &device_id); // device id (ex. bt address) + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_state_get_str() Fail[%d]", ret); + cur_resource_h.set_device_id(string(device_id)); + +#ifdef _TV_ + if ( conv::util::get_bt_mac_address().compare(device_id) == 0 ) { + _D("the device has found itself..[device_id:%s].. out!", device_id); + return; + } +#else + if( conv::util::get_p2p_mac_address().compare(device_id) == 0 ) { + _D("the device has found itself..[device_id:%s].. out!", device_id); + return; + } +#endif + + ret = iotcon_state_get_str(recv_state, "device_name", &device_name); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_state_get_str() Fail[%d]", ret); + cur_resource_h.set_device_name(string(device_name)); + + ret = iotcon_state_get_str(recv_state, "device_type", &device_type); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "iotcon_state_get_str() Fail[%d]", ret); + cur_resource_h.set_device_type(string(device_type)); + + char* service_json_char = NULL; + ret = iotcon_state_get_str(recv_state, "service_json", &service_json_char); + if (service_json_char == NULL) + { + _D("service_json does not exist..."); + service_json_char = const_cast(""); + } + std::string service_json(service_json_char); + + cur_resource_h.set_services_list(service_json); + json service_list_json(service_json); + _D("on_response : device_id[%s] device_name[%s] device_type[%s] version[%s] service_list[%s]" + , device_id, device_name, device_type, version, service_list); + + if (disc_manager != NULL) + { + device_adapter* device = new(std::nothrow) device_adapter (cur_resource_h); + + int num_service = service_list_json.array_get_size(NULL, "service_list"); + for (int index = 0; index < num_service; index++) + { + int serv_type_int; + + json cur_service_json; + bool ret = service_list_json.get_array_elem(NULL, "service_list", index, &cur_service_json); + if (ret != true) + { + _D("json get array elem with service_list error.."); + continue; + } + + service_adapter* serv = new(std::nothrow) service_adapter(cur_resource_h); + json serv_info_json; + + cur_service_json.get(NULL, CONV_JSON_DISCOVERY_SERVICE_TYPE, &serv_type_int); + serv->setServiceType(serv_type_int); + cur_service_json.get(NULL, CONV_JSON_DISCOVERY_SERVICE_INFO, &serv_info_json); + serv->setServiceInfo(serv_info_json.str()); + + device->add_service(serv); + } + disc_manager->append_discovered_result(device, NULL); + } + + discovery_complete_list.push_back(discoveryKey); +} + +bool conv::iotcon_discovery_provider::_get_str_list_cb(int pos, const char* value, void* user_data) +{ + json* service_list = (json*) user_data; + service_list->array_append(NULL, "services_list", string(value)); + return IOTCON_FUNC_CONTINUE; +} + +void conv::iotcon_discovery_provider::on_received_detail_info(iotcon_remote_resource_h resource, iotcon_error_e error, + iotcon_request_type_e request_type, iotcon_response_h response, + void* user_data) +{ + _D("On Received Detail Info.. with type[%d]", request_type); + + switch (request_type) { + case IOTCON_REQUEST_GET : + _on_response_get(resource, response, NULL); + break; + case IOTCON_REQUEST_PUT: + case IOTCON_REQUEST_POST: + case IOTCON_REQUEST_DELETE: + _D("Not supported request_type"); + break; + default: + _E("Invalid Request Type"); + return; + } +} + +void conv::iotcon_discovery_provider::_get_detail_info(iotcon_remote_resource_h resource) +{ + iotcon_query_h query; + iotcon_remote_resource_h resource_clone = NULL; + + _D("_get_detail_info called.."); + + int ret = iotcon_remote_resource_clone(resource, &resource_clone); + if (ret != IOTCON_ERROR_NONE) { + _E("iotcon_remote_resource_clone() Failed(%d)", ret); + } + + ret = iotcon_query_create(&query); + IF_FAIL_VOID_TAG((ret == IOTCON_ERROR_NONE), _E, "Failed[%d] to create Query", ret); + + ret = iotcon_query_add(query, "query_key", "query_value"); + if (ret != IOTCON_ERROR_NONE) { + _E("Failed[%d] to add query", ret); + iotcon_query_destroy(query); + return; + } + + /* send Get Request */ + ret = iotcon_remote_resource_get(resource_clone, query, on_received_detail_info, NULL); + if (ret != IOTCON_ERROR_NONE) { + _E("Failed[%d] to get remote resource query", ret); + iotcon_query_destroy(query); + return; + } +} + +string conv::iotcon_discovery_provider::generateDiscoveryKey(char* uri_path, char* host_address) +{ + return string(host_address) + string(uri_path); +} + +int conv::iotcon_discovery_provider::add_iot_resource(iotcon_remote_resource_h resource) +{ + _D("add_iot_resource called.."); + resource_handle iot_resource_h; + + char* resource_uri_path = NULL; + char* resource_host = NULL; + iotcon_resource_types_h resource_types = NULL; + string resource_type; + iotcon_resource_interfaces_h resource_interfaces; + + // uri_path , host_address + iotcon_remote_resource_get_uri_path(resource, &resource_uri_path); + iotcon_remote_resource_get_host_address(resource, &resource_host); + + _D("found Resource : uri[%s], host_address[%s]", resource_uri_path, resource_host); + + // resource_types + iotcon_remote_resource_get_types(resource, &resource_types); + + // interface - IOTCON_INTERFACE_ DEFAULT / LINK / BATCH / GROUP + iotcon_remote_resource_get_interfaces(resource, &resource_interfaces); + + resource_handle res_handle; + // uri_path + res_handle.set_uri_path(string(resource_uri_path)); + // host_address + res_handle.set_host_address(string(resource_host)); + // resource types + iotcon_resource_types_foreach(resource_types, _get_resource_foreach_types, (void*)(&res_handle.get_types()) ); + + // Add resource handle into Temp Cache + string discovery_key = generateDiscoveryKey(resource_uri_path, resource_host); + _D("discovery_process_map insertion with key[%s]", discovery_key.c_str()); + discovery_process_map.insert(discovery_process_map_t::value_type(discovery_key, res_handle)); + + return CONV_ERROR_NONE; +} + +void conv::iotcon_discovery_provider::_found_resource(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data) +{ + _D("_found_resource called.."); + + IF_FAIL_VOID_TAG((resource != NULL), _E, "resource is NULL.."); + + int ret; + // add the found resource into Temp cache + ret = add_iot_resource(resource); + IF_FAIL_VOID_TAG((ret == CONV_ERROR_NONE), _E, "Failed to add iot resource"); + + // Get additional info from resource + _get_detail_info(resource); +} + +int conv::iotcon_discovery_provider::start() +{ + int ret; + _D("iotcon discovery provider start.."); + discovery_complete_list.clear(); + discovery_process_map.clear(); + + ret = iotcon_find_resource(IOTCON_MULTICAST_ADDRESS, IOTCON_CONNECTIVITY_IPV4, + CONV_RESOURCE_TYPE_TIZEN_D2D_SERVICE, false, _found_resource, NULL); + + IF_FAIL_RETURN_TAG((ret == 0), CONV_ERROR_INVALID_OPERATION, _E, "failed on iotcon_find_resource[%d]", ret); + + return CONV_ERROR_NONE; +} + +int conv::iotcon_discovery_provider::stop() +{ + return CONV_ERROR_NONE; +} + +int conv::iotcon_discovery_provider::set_manager(discovery_manager_impl* disco_manager) +{ + _D("set discovery manager.."); + disc_manager = disco_manager; + + return CONV_ERROR_NONE; +} + diff --git a/daemon/discovery_provider/iotcon_discovery_provider.h b/daemon/discovery_provider/iotcon_discovery_provider.h new file mode 100644 index 0000000..47d8917 --- /dev/null +++ b/daemon/discovery_provider/iotcon_discovery_provider.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __IOTCON_DISCOVERY_PROVIDER_H__ +#define __IOTCON_DISCOVERY_PROVIDER_H__ + +#include +#include +#include +#include +#include "../discovery_provider_base.h" +#include "../request.h" + +#include "../service_iface.h" +#include "iotcon/resource_handle.h" + +using namespace std; + +namespace conv { + class iotcon_discovery_provider : public discovery_provider_base { + private: + + static void _found_resource(iotcon_remote_resource_h resource, iotcon_error_e result, + void *user_data); + static void _get_detail_info(iotcon_remote_resource_h resource); + + static void on_received_detail_info(iotcon_remote_resource_h resource, iotcon_error_e error, + iotcon_request_type_e request_type, iotcon_response_h response, + void* user_data); + + static void _on_response_get(iotcon_remote_resource_h resource, + iotcon_response_h response, void* user_data); + + static int add_iot_resource(iotcon_remote_resource_h resource); + static string generateDiscoveryKey(char* uri_path, char* host_address); + static bool _get_str_list_cb(int pos, const char* value, void* user_data); + + public: + iotcon_discovery_provider(); + ~iotcon_discovery_provider(); + + int init(); + int release(); + + int start(); + int stop(); + + int set_manager(discovery_manager_impl* disc_manager); + static int notice_discovered(service_iface* service); + }; +} +#endif /* __SMARTVIEW_DISCOVERY_PROVIDER_H__ */ diff --git a/daemon/discovery_provider/smartview_discovery_provider.cpp b/daemon/discovery_provider/smartview_discovery_provider.cpp new file mode 100644 index 0000000..a52797e --- /dev/null +++ b/daemon/discovery_provider/smartview_discovery_provider.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "smartview_discovery_provider.h" + +#include "../discovery_mgr_impl.h" +#include "../service.h" +#include "../device.h" +#include "../conv_json.h" + +#include "../util.h" + +using namespace std; + +class SearchListenerImpl : public SearchListener { + private: + conv::discovery_manager_impl* disc_manager; + conv::smartview_discovery_provider* disc_provider; + + public: + void set_discovery_manager(conv::discovery_manager_impl* disc_manager) + { + this->disc_manager = disc_manager; + } + + void set_discovery_provider(conv::smartview_discovery_provider* disc_provider) + { + this->disc_provider = disc_provider; + } + + void onStart() { + _I("onStart on SearchListener"); + } + void onStop() { + _I("onStop on SearchListener"); + } + void onFound(Service service) { + _I("onFound on SearchListener.. towards disc_manager:%x", disc_manager); + if (disc_provider != NULL) { + disc_provider->notice_discovered(&service); + } + } + void onLost(Service service) { + _I("onLost on SearchListener"); + } +}; + +static SearchListenerImpl* listener_impl = NULL; + +conv::smartview_discovery_provider::smartview_discovery_provider() +{ +} + +conv::smartview_discovery_provider::~smartview_discovery_provider() +{ +} + +int conv::smartview_discovery_provider::init() +{ + _D("smartview_discovery init"); + search = new Search(); + if (listener_impl == NULL) + { + listener_impl = new SearchListenerImpl; + listener_impl->set_discovery_provider(this); + } + search->setSearchListener(listener_impl); + + _D("smartview_discovery init Done"); + + return CONV_ERROR_NONE; +} + +int conv::smartview_discovery_provider::release() +{ + if ( search != NULL ) + { + delete search; + } + + return CONV_ERROR_NONE; +} + +int conv::smartview_discovery_provider::start() +{ + // Cache init.. + cache.clear(); + + _D("smartview_discovery start"); + search->start(); + _D("smartview_discovery start done"); + + return CONV_ERROR_NONE; +} + +int conv::smartview_discovery_provider::stop() +{ + _D("smartview_discovery stop"); + search->stop(); + return CONV_ERROR_NONE; +} + +int conv::smartview_discovery_provider::set_manager(discovery_manager_impl* disc_manager) +{ + discovery_manager = disc_manager; + + listener_impl->set_discovery_manager(disc_manager); + return CONV_ERROR_NONE; +} + +conv::device* conv::smartview_discovery_provider::convert_into_conv_device(Service* smartview_service) +{ + string serv_name, serv_version, serv_type, serv_id, serv_uri; + + serv_name = smartview_service->getName(); + serv_version = smartview_service->getVersion(); + serv_type = smartview_service->getType(); + serv_id = smartview_service->getId(); + serv_uri = smartview_service->getUri(); + + _D("SmartView Discovered Service : Name[%s] Version[%s] Type[%s] Id[%s] Uri[%s] ", + serv_name.c_str(), serv_version.c_str(), serv_type.c_str(), + serv_id.c_str(), serv_uri.c_str() ); + + conv::device* device_info = new(std::nothrow) conv::device; + device_info->setId(serv_id); + device_info->setName(serv_name); + + /* + conv::service* service_info = new(std::nothrow) conv::service; + service_info->setVersion (serv_version); + service_info->setType (serv_type); + service_info->setUri (serv_uri); + + device_info->add_service (service_info); + */ + + return device_info; +} + +conv::service* conv::smartview_discovery_provider::convert_into_conv_service(Service* smartview_service) +{ + string serv_name, serv_version, serv_type, serv_id, serv_uri; + + serv_name = smartview_service->getName(); + serv_version = smartview_service->getVersion(); + serv_type = smartview_service->getType(); + serv_id = smartview_service->getId(); + serv_uri = smartview_service->getUri(); + + _D("SmartView Discovered Service : Name[%s] Version[%s] Type[%s] Id[%s] Uri[%s] ", + serv_name.c_str(), serv_version.c_str(), serv_type.c_str(), + serv_id.c_str(), serv_uri.c_str() ); + + json json_serv_info; + json_serv_info.set(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_URI, serv_uri); + json_serv_info.set(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_ID, serv_id); + json_serv_info.set(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_NAME, serv_name); + json_serv_info.set(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_VERSION, serv_version); + json_serv_info.set(CONV_JSON_SERVICE_DATA_PATH, CONV_JSON_SERVICE_DATA_TYPE, serv_type); + + conv::service *conv_service = new conv::service; + + conv_service->setName(serv_name); + conv_service->setVersion(serv_version); + conv_service->setType(serv_type); + conv_service->setId(serv_id); + conv_service->setUri(serv_uri); + + conv_service->setServiceInfo(json_serv_info.str()); + conv_service->setServiceType(CONV_TYPE_APP_TO_APP_COMMUNICATION); + + return conv_service; +} + +int conv::smartview_discovery_provider::checkExistence(conv::service* conv_service) +{ + _D("Check Existence : "); + conv_service->printInfo(); + + // insert into cache + string cache_key = conv_service->getUri(); // Serivce URI as Map Key + if (cache.find(cache_key) == cache.end()){ + _D("Flow_service with key[%s] does not exist..so go into the cache", cache_key.c_str()); + cache.insert(map::value_type(cache_key, conv_service)); + return CONV_ERROR_NONE; + } else { + _D("Flow_service with key[%s] already exists..", cache_key.c_str()); + return CONV_ERROR_INVALID_PARAMETER; + } +} + +int conv::smartview_discovery_provider::notice_discovered(Service* service) +{ + _D("Notice Discovered called with service[%x]", service); + + // Covert MSF-API's Service into D2D Flow's Device n Service + conv::device* conv_device = convert_into_conv_device(service); + IF_FAIL_RETURN_TAG((conv_device != NULL), CONV_ERROR_INVALID_PARAMETER, _E, "failed to convert into flow device.."); + + conv::service* conv_service = convert_into_conv_service(service); + IF_FAIL_RETURN_TAG((conv_service != NULL), CONV_ERROR_INVALID_PARAMETER, _E, "failed to convert into flow service.."); + conv_device->add_service(conv_service); + + _D("Success in converting into flow.service[%x] .device[%x]", conv_service, conv_device); + +#ifdef _TV_ + if ( conv::util::get_bt_mac_address().compare(conv_service->getId()) == 0 ) { + _D("the device has found itself..[device_id:%s].. out!", conv_service->getId().c_str()); + if(conv_device != NULL) delete conv_device; + if(conv_service != NULL) delete conv_service; + + return CONV_ERROR_NONE; + } +#else + if ( conv::util::get_p2p_mac_address().compare(conv_service->getId()) == 0 ) { + _D("the device has found itself..[device_id:%s].. out!", conv_service->getId().c_str()); + if(conv_device != NULL) delete conv_device; + if(conv_service != NULL) delete conv_service; + + return CONV_ERROR_NONE; + } +#endif + + + // Double check if the noticed one already got delivered + int alreadyExisted = checkExistence(conv_service); + _D("double check .. existence[%s]", (alreadyExisted == 0)? "No" : "Yes"); + + if (!alreadyExisted) { + //the discovered one is NEW!! + discovery_manager->append_discovered_result(conv_device, conv_service); + } + + return CONV_ERROR_NONE; +} diff --git a/daemon/discovery_provider/smartview_discovery_provider.h b/daemon/discovery_provider/smartview_discovery_provider.h new file mode 100644 index 0000000..2fe450c --- /dev/null +++ b/daemon/discovery_provider/smartview_discovery_provider.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SMARTVIEW_DISCOVERY_PROVIDER_H__ +#define __SMARTVIEW_DISCOVERY_PROVIDER_H__ + +#include +#include +#include +#include + +#include "../discovery_provider_base.h" +#include "../request.h" +#include "../service.h" +#include "../device.h" + +#include +#include + +namespace conv { + + class smartview_discovery_provider : public discovery_provider_base { + public: + smartview_discovery_provider(); + ~smartview_discovery_provider(); + + int init(); + int release(); + + int start(); + int stop(); + + int set_manager(discovery_manager_impl* disc_manager); + int notice_discovered(Service *service); + + private: + Service service; + Search* search; + discovery_manager_impl* discovery_manager; + + map cache; // for double check + + conv::service* convert_into_conv_service(Service* smartview_service); + conv::device* convert_into_conv_device(Service* smartview_service); + int checkExistence(conv::service* conv_service); + }; +} + +#endif /* __SMARTVIEW_DISCOVERY_PROVIDER_H__ */ diff --git a/daemon/discovery_provider_base.h b/daemon/discovery_provider_base.h new file mode 100644 index 0000000..a041829 --- /dev/null +++ b/daemon/discovery_provider_base.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DISCOVERY_PROVIDER_BASE_H__ +#define __DISCOVERY_PROVIDER_BASE_H__ + +#include +#include "conv_json.h" + + +namespace conv { + + class discovery_manager_impl; + + class discovery_provider_base { + public: + virtual ~discovery_provider_base() {} + virtual int init() = 0; + virtual int release() = 0; + virtual int start() = 0; + virtual int stop() = 0; + + virtual int set_manager(discovery_manager_impl* discovery_manager) = 0; + }; /* class discovery_provider_base */ +} + +#endif /* End of __DISCOVERY_PROVIDER_BASE_H__ */ diff --git a/daemon/iotcon_communication_info.h b/daemon/iotcon_communication_info.h new file mode 100644 index 0000000..e2c0bc6 --- /dev/null +++ b/daemon/iotcon_communication_info.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __IOTCON_COMMUNICATION_INFO_H__ +#define __IOTCON_COMMUNICATION_INFO_H__ + +#include +#include +#include +#include +#include "communication_info_base.h" + +namespace conv { + class iotcon_communication_info : public communication_info_base { + public: + std::string address; + std::string uri; + std::string resource_type; + + iotcon_remote_resource_h iotcon_resource_handle; + iotcon_representation_h iotcon_representation_handle; + }; + +} +#endif /* __IOTCON_COMMUNICATION_INFO_H__ */ diff --git a/daemon/manager_iface.h b/daemon/manager_iface.h new file mode 100644 index 0000000..e867be5 --- /dev/null +++ b/daemon/manager_iface.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_MANAGER_INTERFACE_H__ +#define __CONV_MANAGER_INTERFACE_H__ + +#include +#include "conv_json.h" + +namespace conv { + class request; + + class manager_iface { + public: + virtual ~manager_iface() {} + virtual int init() = 0; + virtual int release() = 0; + virtual int handle_request(request* request_obj) = 0; +// virtual int publish(const char* subject, json data_updated, json option) = 0; + }; /* class manager_iface */ +} + +#endif /* End of __CONV_MANAGER_INTERFACE_H__ */ diff --git a/daemon/org.tizen.d2dconv.service.in b/daemon/org.tizen.d2dconv.service.in new file mode 100644 index 0000000..15bd540 --- /dev/null +++ b/daemon/org.tizen.d2dconv.service.in @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=@DBUS_INTERFACE@ +Exec=@BIN_INSTALL_DIR@/d2d-conv-managerd + +Libs: -L${libdir} -pthread diff --git a/daemon/request.cpp b/daemon/request.cpp new file mode 100644 index 0000000..5f96fe3 --- /dev/null +++ b/daemon/request.cpp @@ -0,0 +1,178 @@ +/* + * 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 "common.h" +#include "request.h" +#include "dbus_server_impl.h" + +conv::request::request(int type, const char* client, int req_id, const char* subj, const char* desc) + : _type(type) + , _req_id(req_id) + , _client(client) + , _subject(subj) + , _description(desc) +{ +} + +conv::request::request(int type, + const char *client, int req_id, const char *subj, const char *desc, + const char *sender, credentials *creds, GDBusMethodInvocation *inv) + : _type(type) + , _req_id(req_id) + , _client(client) + , _subject(subj) + , _description(desc) + , __creds(creds) + , __sender(sender) + , __invocation(inv) +{ +} + +conv::request::~request() +{ + if ( __creds != NULL ) + { + delete __creds; + } +} + +int conv::request::get_type() +{ + return _type; +} + +int conv::request::get_id() +{ + return _req_id; +} + +const char* conv::request::get_client() +{ + return _client.c_str(); +} + +const char* conv::request::get_sender() +{ + return __sender.c_str(); +} + +const char* conv::request::get_subject() +{ + return _subject.c_str(); +} + +json& conv::request::get_description() +{ + return _description; +} + +conv::credentials* conv::request::get_creds() +{ + return __creds; +} + +bool conv::request::reply(int error) +{ + IF_FAIL_RETURN(__invocation, true); + + _I("Reply %#x", error); + + g_dbus_method_invocation_return_value(__invocation, g_variant_new("(iss)", error, EMPTY_JSON_OBJECT, EMPTY_JSON_OBJECT)); + __invocation = NULL; + _D("Reply done"); + return true; +} + +bool conv::request::reply(int error, json& request_result) +{ + IF_FAIL_RETURN(__invocation, true); + IF_FAIL_RETURN(_type != REQ_READ_SYNC, true); + + char *result = request_result.dup_cstr(); + IF_FAIL_RETURN_TAG(result, false, _E, "Memory allocation failed"); + + _I("Reply %#x", error); + _SD("Result: %s", result); + + g_dbus_method_invocation_return_value(__invocation, g_variant_new("(iss)", error, result, EMPTY_JSON_OBJECT)); + __invocation = NULL; + + g_free(result); + return true; +} + +bool conv::request::reply(int error, json& request_result, json& data_read) +{ + if (__invocation == NULL) { + return publish(error, data_read); + } + + char *result = NULL; + char *data = NULL; + + result = request_result.dup_cstr(); + IF_FAIL_CATCH_TAG(result, _E, "Memory allocation failed"); + + data = data_read.dup_cstr(); + IF_FAIL_CATCH_TAG(data, _E, "Memory allocation failed"); + + _I("Reply %#x", error); + _SD("Result: %s", result); + _SD("Data: %s", data); + + g_dbus_method_invocation_return_value(__invocation, g_variant_new("(iss)", error, result, data)); + __invocation = NULL; + + g_free(result); + g_free(data); + return true; + +CATCH: + g_free(result); + g_free(data); + return false; +} + +bool conv::request::publish(int error, json& data) +{ + char *data_str = data.dup_cstr(); + IF_FAIL_RETURN_TAG(data_str, false, _E, "Memory allocation failed"); + + _D("info : sendor %s", __sender.c_str()); + _D("info : req_id %d", _req_id); + _D("info : subject %s", _subject.c_str()); + _D("info : error %d", error); + _D("info : data %s", data_str); + _D("info : description %s", _description.str().c_str()); + _D("publish info : sender[%s] req_id[%d] subject[%s] error[%d] data[%s]" + , __sender.c_str(), _req_id, _subject.c_str(), error, data_str); + + conv::dbus_server::publish(__sender.c_str(), _req_id, _subject.c_str(), error, data_str); + g_free(data_str); + + return true; +} + +bool conv::request::get_channel_from_description(json* target) +{ + return _description.get(NULL, CONV_JSON_CHANNEL, target); +} + +bool conv::request::get_payload_from_description(json* target) +{ + return _description.get(NULL, CONV_JSON_PAYLOAD, target); +} diff --git a/daemon/request.h b/daemon/request.h new file mode 100644 index 0000000..f87915f --- /dev/null +++ b/daemon/request.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REQUEST_H__ +#define __REQUEST_H__ + +#include +#include +#include "common.h" +#include "conv_json.h" +#include "service_info_base.h" +#include "communication_info_base.h" +#include "access_control/peer_creds.h" + +namespace conv { + class request { + public: + request(int type, const char *client, int req_id, const char *subj, const char *desc); + request(int type, + const char *client, int req_id, const char *subj, const char *desc, + const char *sender, credentials *creds, GDBusMethodInvocation *inv); + ~request(); + + int get_type(); + int get_id(); + const char *get_client(); + const char *get_sender(); + const char *get_subject(); + json& get_description(); + credentials *get_creds(); + bool reply(int error); + bool reply(int error, json &request_result); + bool reply(int error, json &request_result, json &data_read); + bool publish(int error, json &data); + + bool get_channel_from_description(json* target); + bool get_payload_from_description(json* target); + std::string service_type; + + std::string connection_type; + service_info_base* service_info; + communication_info_base* communication_info; + + protected: + int _type; + int _req_id; + std::string _client; + std::string _subject; + json _description; + credentials *__creds; + std::string __sender; + GDBusMethodInvocation *__invocation; + }; +} + +#endif /* End of __REQUEST_H__ */ diff --git a/daemon/request_handler.cpp b/daemon/request_handler.cpp new file mode 100644 index 0000000..6a900c9 --- /dev/null +++ b/daemon/request_handler.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "request_handler.h" +#include "discovery_mgr_impl.h" +#include "service_mgr_impl.h" +#include "connection_mgr_impl.h" + +using namespace std; + +conv::request_handler::request_handler() +{ +} + +conv::request_handler::~request_handler() +{ +} + +int conv::request_handler::init() +{ + return CONV_ERROR_NONE; +} + +int conv::request_handler::release() +{ + return CONV_ERROR_NONE; +} + +int conv::request_handler::handle_request(request* request_obj) +{ + _D("handle_request called"); + int result = CONV_ERROR_INVALID_OPERATION; + + switch (request_obj->get_type()) { + case REQ_SUBSCRIBE: + _D("Requested type : REQ_SUBSCRIBE.."); + if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_RECV) ) + { + result = service_manager::handle_request(request_obj); + } + else if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_CONNECTION_START) ) + { + result = connection_manager::handle_request(request_obj); + } + break; + case REQ_UNSUBSCRIBE: + if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_RECV) ) + { + result = service_manager::handle_request(request_obj); + } + else if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_CONNECTION_START) ) + { + result = connection_manager::handle_request(request_obj); + } + break; + case REQ_READ: + break; + case REQ_READ_SYNC: + break; + case REQ_WRITE: + _D("Requested type : REQ_WRITE.."); + if (!strcmp (request_obj->get_subject(), CONV_SUBJECT_DISCOVERY_START) || !strcmp (request_obj->get_subject(), CONV_SUBJECT_DISCOVERY_STOP)) + { + return discovery_manager::handle_request (request_obj); + } + else if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_START) || !strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_STOP) + || !strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_SET) || !strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_GET)) + { + result = service_manager::handle_request(request_obj); + } + else if ( !strcmp(request_obj->get_subject(), CONV_SUBJECT_CONNECTION_START) || !strcmp(request_obj->get_subject(), CONV_SUBJECT_CONNECTION_STOP) ) + { + result = connection_manager::handle_request(request_obj); + } + break; + case REQ_SUPPORT: + break; + default: + _E("Invalid type of request"); + request_obj->reply(result); + delete request_obj; + } + + return result; +} diff --git a/daemon/request_handler.h b/daemon/request_handler.h new file mode 100644 index 0000000..c68a3ca --- /dev/null +++ b/daemon/request_handler.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REQUEST_HANDLER_H__ +#define __REQUEST_HANDLER_H__ + +#include +#include "request.h" + +namespace conv { + class request_handler { + public: + request_handler(); + ~request_handler(); + + int init(); + int release(); + + int handle_request(request* request_obj); + }; +} + +#endif /* __REQUEST_HANDLER_H__ */ diff --git a/daemon/server.cpp b/daemon/server.cpp new file mode 100644 index 0000000..5b5731d --- /dev/null +++ b/daemon/server.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + + +#include "d2d_conv_manager.h" +#include "server.h" +#include "dbus_server_impl.h" +#include "discovery_mgr_impl.h" +#include "connection_mgr_impl.h" +#include "client_mgr_impl.h" +#include "service_mgr_impl.h" +#include "request_handler.h" + +using namespace std; + +static GMainLoop *mainloop = NULL; +static gboolean started = FALSE; +static conv::dbus_server_impl *dbus_handle = NULL; +static conv::discovery_manager_impl *discovery_mgr = NULL; +static conv::connection_manager_impl *connection_mgr = NULL; +static conv::client_manager_impl *client_mgr = NULL; +static conv::service_manager_impl *service_mgr = NULL; +static conv::request_handler *request_mgr = NULL; + +void conv::initialize() +{ + int result; + + if (started) { + _D("flowd is started already"); + return; + } + + mainloop = g_main_loop_new(NULL, FALSE); + + _I("Init Discovery Manager"); + discovery_mgr = new(std::nothrow) conv::discovery_manager_impl(); + IF_FAIL_CATCH_TAG(discovery_mgr, _E, "Memory allocation failed"); + discovery_manager::set_instance(discovery_mgr); + result = discovery_mgr->init(); + IF_FAIL_CATCH_TAG(result == CONV_ERROR_NONE, _E, "Initialization Failed"); + + _I("Init Connection Manager"); + connection_mgr = new(std::nothrow) conv::connection_manager_impl(); + IF_FAIL_CATCH_TAG(connection_mgr, _E, "Memory allocation failed"); + connection_manager::set_instance(connection_mgr); + result = connection_mgr->init(); + IF_FAIL_CATCH_TAG(result == CONV_ERROR_NONE, _E, "Initialization Failed"); + + _I("Init Client Manager"); + client_mgr = new(std::nothrow) conv::client_manager_impl(); + IF_FAIL_CATCH_TAG(client_mgr, _E, "Memory allocation failed"); + client_manager::set_instance(client_mgr); + result = client_mgr->init(); + IF_FAIL_CATCH_TAG(result == CONV_ERROR_NONE, _E, "Initialization Failed"); + + _I("Init Service Manager"); + service_mgr = new(std::nothrow) conv::service_manager_impl(); + IF_FAIL_CATCH_TAG(service_mgr, _E, "Memory allocation failed"); + service_manager::set_instance(service_mgr); + result = service_mgr->init(); + IF_FAIL_CATCH_TAG(result == CONV_ERROR_NONE, _E, "Initialization Failed"); + + _I("Init Request Manager"); + request_mgr = new(std::nothrow) request_handler(); + IF_FAIL_CATCH_TAG(request_mgr, _E, "Memory allocation failed"); + result = request_mgr->init(); + IF_FAIL_CATCH_TAG(result == CONV_ERROR_NONE, _E, "Initialization Failed"); + + _I("Init Dbus Server"); + dbus_handle = new(std::nothrow) conv::dbus_server_impl(); + IF_FAIL_CATCH_TAG(discovery_mgr, _E, "Memory allocation failed"); + dbus_server::set_instance(dbus_handle); + result = dbus_handle->init(); + IF_FAIL_CATCH_TAG(result == true, _E, "Initialization Failed"); + + _I("Start main loop"); + started = TRUE; + + g_main_loop_run(mainloop); + + return; + +CATCH: + _E(RED("Launching Failed")); + + g_main_loop_quit(mainloop); +} + +void conv::release() +{ + _I(CYAN("Terminating flow-daemon")); + _I("Release discovery manager"); + if (discovery_mgr) + discovery_mgr->release(); + + _I("Release connection manager"); + if (connection_mgr) + connection_mgr->release(); + + _I("Release dbus server"); + if (dbus_handle) + dbus_handle->release(); + + _I("Release client manager"); + if (client_mgr) + client_mgr->release(); + + _I("Release service manager"); + if (service_mgr) + service_mgr->release(); + + _I("Release request handler"); + if (request_mgr) + request_mgr->release(); + + g_main_loop_unref(mainloop); + + delete discovery_mgr; + delete connection_mgr; + delete dbus_handle; + delete client_mgr; + delete request_mgr; + delete service_mgr; + started = FALSE; +} + + +void conv::send_request(request* request_obj) +{ + _D("send_request request_obj:%x request_mg:%x", request_obj, request_mgr); + if (request_mgr) { + request_mgr->handle_request(request_obj); + } else if (request_obj) { //jhp27.park temp code.. + request_obj->reply(CONV_ERROR_NONE); + } + + _D("request handling done"); +} + +static void signal_handler(int signo) +{ + _I("SIGNAL %d received", signo); + + // Stop the main loop + g_main_loop_quit(mainloop); +} + +int main(int argc, char **argv) +{ + static struct sigaction signal_action; + signal_action.sa_handler = 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); + sigaction(SIGABRT, &signal_action, NULL); + +#if !defined(GLIB_VERSION_2_36) + g_type_init(); +#endif + + conv::initialize(); + conv::release(); + + return EXIT_SUCCESS; +} diff --git a/daemon/server.h b/daemon/server.h new file mode 100644 index 0000000..de513f0 --- /dev/null +++ b/daemon/server.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_SERVER_H__ +#define __CONV_SERVER_H__ + +#define CONV_DAEMON +#include "log.h" +#include "request.h" + +namespace conv { + void initialize(); + void release(); + void send_request(request* request_obj); +} +#endif diff --git a/daemon/service.cpp b/daemon/service.cpp new file mode 100644 index 0000000..17efcbe --- /dev/null +++ b/daemon/service.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "service.h" + +using namespace std; + +conv::service::service() +{ +} + +conv::service::~service() +{ +} + +string conv::service::getName() +{ + return service_name; +} + +string conv::service::getVersion() +{ + return service_version; +} + +string conv::service::getType() +{ + return this->type; +} + +string conv::service::getId() +{ + return service_id; +} + +string conv::service::getUri() +{ + return service_uri; +} + +int conv::service::getServiceType() +{ + return 0; //string("oic.r.tizen.app-communication"); +} + +string conv::service::getServiceInfo() +{ + return service_info; +} + +void conv::service::setName(string name) +{ + this->service_name = name; +} + +void conv::service::setVersion(string version) +{ + this->service_version = version; +} + +void conv::service::setType(string type) +{ + this->type = type; +} + +void conv::service::setId(string id) +{ + this->service_id = id; +} + +void conv::service::setUri(string uri) +{ + this->service_uri = uri; +} + +void conv::service::setServiceInfo(string service_info) +{ + this->service_info = service_info; +} + +void conv::service::setServiceType(int service_type) +{ + this->service_type = service_type; +} + +void conv::service::printInfo() +{ + _D("Flow Service Info : Name[%s] Version[%s] Type[%d] Id[%s] Uri[%s] ", + service_name.c_str(), service_version.c_str(), service_type, + service_id.c_str(), service_uri.c_str()); +} diff --git a/daemon/service.h b/daemon/service.h new file mode 100644 index 0000000..5a74313 --- /dev/null +++ b/daemon/service.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_SERVICE_H__ +#define __CONV_SERVICE_H__ + +#include +#include "conv_json.h" +#include "service_iface.h" + +using namespace std; + +namespace conv +{ + class service : public service_iface { + public: + service(); + ~service(); + + // functions from service_iface + string getName(); + string getVersion(); + string getType(); + string getId(); + string getUri(); + int getServiceType(); + string getServiceInfo(); + + // + void setName(string name); + void setVersion(string version); + void setType(string type); + void setId(string id); + void setUri(string uri); + void setServiceInfo(string service_info); + void setServiceType(int service_type); + + void printInfo(); + + protected: + int connection_state; + string service_name; + int service_type; + string service_info; + + //.. + string service_version; + string service_id; + string service_uri; + string type; + }; +} + +#endif /* End of __CONV_SERVICE_H__ */ diff --git a/daemon/service_iface.h b/daemon/service_iface.h new file mode 100644 index 0000000..e0c87d0 --- /dev/null +++ b/daemon/service_iface.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _SERVICE_INTERFACE_H__ +#define _SERVICE_INTERFACE_H__ + +#include +using namespace std; + +namespace conv { + class service_iface { + public: + virtual ~service_iface() {} + virtual string getName() = 0; + virtual string getVersion() = 0; + virtual string getType() = 0; + virtual string getId() = 0; + virtual string getUri() = 0; + virtual int getServiceType() = 0; + virtual string getServiceInfo() = 0; + }; +} + +#endif diff --git a/daemon/service_info_base.h b/daemon/service_info_base.h new file mode 100644 index 0000000..89779e7 --- /dev/null +++ b/daemon/service_info_base.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_SERVICE_INFO_BASE_H__ +#define __CONV_SERVICE_INFO_BASE_H__ + +#include + +namespace conv +{ + class service_info_base { + public: + virtual ~service_info_base() {} + }; +} + +#endif /* End of __CONV_SERVICE_INFO_BASE_H__ */ diff --git a/daemon/service_mgr_impl.cpp b/daemon/service_mgr_impl.cpp new file mode 100644 index 0000000..1d0bc4f --- /dev/null +++ b/daemon/service_mgr_impl.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service_mgr_impl.h" +#include "service_provider/app_comm_service_provider.h" +#include "service_provider/remote_app_control_service_provider.h" +#include "connection_mgr_impl.h" +#include "access_control/privilege.h" +#include "util.h" +#include + +static conv::service_manager_impl *_instance; +static iotcon_resource_h iotcon_resource; + +using namespace std; + +conv::service_manager_impl::service_manager_impl() +{ +} + +conv::service_manager_impl::~service_manager_impl() +{ +} + +int conv::service_manager_impl::init() +{ + register_provider(new conv::app_comm_service_provider()); + register_provider(new conv::remote_app_control_service_provider()); + + //TBD + register_discovery_info(); + return CONV_ERROR_NONE; +} + +int conv::service_manager_impl::release() +{ + int error = iotcon_resource_destroy(iotcon_resource); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource destroy failed"); + iotcon_resource = NULL; + + for (service_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + (*it)->release(); + } + + for (service_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + delete *it; + } + + provider_list.clear(); + + return CONV_ERROR_NONE; +} + +int conv::service_manager_impl::handle_request(request* request_obj) +{ + _D("handle_request called"); + string type; + int error = CONV_ERROR_INVALID_OPERATION; + bool json_return; + + json description = request_obj->get_description(); + json_return = description.get(NULL, CONV_JSON_TYPE, &type); + + IF_FAIL_CATCH_TAG(json_return, _E, "json parse error : no type info"); + + for (service_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + if ( (*it)->get_type().compare(type) == 0 ) + { + _D("found service provider"); + + error = (*it)->load_service_info(request_obj); + IF_FAIL_CATCH_TAG(error == CONV_ERROR_NONE, _E, "%d, service_info load error", error); + + if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_START)) { + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_D2D_DATA_SHARING) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + error = (*it)->start_request(request_obj); + } else if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_STOP)) { + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + error = (*it)->stop_request(request_obj); + } else if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_GET)) { + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + error = (*it)->get_request(request_obj); + } else if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_SET)) { + if ( !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_INTERNET) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_BLUETOOTH) || + !conv::privilege_manager::is_allowed(request_obj->get_creds(), CONV_PRIVILEGE_D2D_DATA_SHARING) ) + { + _E("permission denied"); + request_obj->reply(CONV_ERROR_PERMISSION_DENIED); + delete request_obj; + return CONV_ERROR_PERMISSION_DENIED; + } + error = (*it)->set_request(request_obj); + } else if (!strcmp(request_obj->get_subject(), CONV_SUBJECT_COMMUNICATION_RECV)) { + return (*it)->register_request(request_obj); + } + IF_FAIL_CATCH_TAG(error == CONV_ERROR_NONE, _E, "service manager request handle error"); + } + } + + request_obj->reply(CONV_ERROR_NONE); + delete request_obj; + _D("request_obj deleted"); + return CONV_ERROR_NONE; + +CATCH: + request_obj->reply(error); + delete request_obj; + + return error; +} + +void conv::service_manager::set_instance(conv::service_manager_impl* mgr) +{ + _instance = mgr; +} + +int conv::service_manager::handle_request(request* request_obj) +{ + IF_FAIL_RETURN_TAG(_instance, CONV_ERROR_INVALID_PARAMETER, _E, "Not initialized"); + _instance->handle_request(request_obj); + + return CONV_ERROR_NONE; +} + +int conv::service_manager_impl::register_provider(conv::service_provider_base *provider) +{ + if (!provider) { + _E("Provider NULL"); + throw static_cast(CONV_ERROR_INVALID_PARAMETER); + } + + provider_list.push_back(provider); + + if (provider->init() != CONV_ERROR_NONE) { + _E("Provider initialization failed"); + throw CONV_ERROR_INVALID_OPERATION; + } + + return CONV_ERROR_NONE; +} + + + +static int _send_response(iotcon_request_h request, iotcon_representation_h repr, + iotcon_response_result_e result) +{ + int ret; + iotcon_response_h response; + + ret = iotcon_response_create(request, &response); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_create() Fail(%d)", ret); + return CONV_ERROR_INVALID_OPERATION; + } + + ret = iotcon_response_set_result(response, result); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_set_result() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + ret = iotcon_response_set_representation(response, IOTCON_INTERFACE_DEFAULT, repr); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_set_representation() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + /* send Representation to the client */ + ret = iotcon_response_send(response); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_send() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + iotcon_response_destroy(response); + + return CONV_ERROR_NONE; +} + + +static iotcon_representation_h _get_d2d_service_representation(conv::service_manager_impl* instance) +{ + int ret; + iotcon_state_h state; + iotcon_representation_h repr; + + ret = iotcon_representation_create(&repr); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_representation_create() Fail(%d)", ret); + return NULL; + } + + ret = iotcon_state_create(&state); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_state_create() Fail(%d)", ret); + iotcon_representation_destroy(repr); + return NULL; + } + +#ifdef _TV_ + char* device_id = (char*) conv::util::get_bt_mac_address().c_str(); +#else + char* device_id = (char*) conv::util::get_p2p_mac_address().c_str(); +#endif + char* device_name = (char*) conv::util::get_device_name().c_str(); + + iotcon_state_add_str(state, CONV_JSON_DEVICE_ID, device_id); + iotcon_state_add_str(state, CONV_JSON_DEVICE_NAME, device_name); +#ifdef _TV_ + string device_type("TV"); +#else + string device_type("MOBILE"); +#endif + iotcon_state_add_str(state, CONV_JSON_DEVICE_TYPE, (char*) device_type.c_str()); + + json service_json; + instance->get_service_info_for_discovery(&service_json); + char* service_json_char = service_json.dup_cstr(); + + iotcon_state_add_str(state, "service_json", service_json_char); + + ret = iotcon_representation_set_state(repr, state); + g_free(service_json_char); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_representation_set_state() Fail(%d)", ret); + iotcon_state_destroy(state); + iotcon_representation_destroy(repr); + return NULL; + } + + iotcon_state_destroy(state); + + return repr; +} + +int conv::service_manager_impl::get_service_info_for_discovery(json* service_json) +{ + IF_FAIL_RETURN_TAG(service_json, CONV_ERROR_INVALID_OPERATION, _E, "service_json is NULL"); + + for (service_provider_list_t::iterator it = provider_list.begin(); it != provider_list.end(); ++it) { + json service_info; + if ( (*it)->get_service_info_for_discovery(&service_info) == CONV_ERROR_NONE ) + { + service_json->array_append(NULL, "service_list", service_info); + } + } + + _D("service_info : %s", service_json->str().c_str()); + + return CONV_ERROR_NONE; +} + +static void iotcon_request_cb(iotcon_resource_h resource, iotcon_request_h request, void *user_data) +{ + _D("request cb called"); + + int ret; + iotcon_request_type_e type; + char *host_address; + + conv::service_manager_impl *instance = (conv::service_manager_impl*)user_data; + + IF_FAIL_VOID_TAG(request, _E, "request is NULL"); + + ret = iotcon_request_get_host_address(request, &host_address); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_request_get_host_address() Fail(%d)", ret); + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } + _I("host_address : %s", host_address); + + ret = iotcon_request_get_request_type(request, &type); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_request_get_types() Fail(%d)", ret); + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } + + if (IOTCON_REQUEST_GET == type) + { + iotcon_representation_h resp_repr; + _I("GET request"); + + resp_repr = _get_d2d_service_representation(instance); + if (resp_repr == NULL) { + _I("_get_d2d_service_representation() Fail"); + ret = CONV_ERROR_INVALID_OPERATION; + } else { + ret = _send_response(request, resp_repr, IOTCON_RESPONSE_OK); + if (ret != IOTCON_ERROR_NONE) { + _E("_send_response() Fail(%d)", ret); + iotcon_representation_destroy(resp_repr); + return; + } + + iotcon_representation_destroy(resp_repr); + } + } + + if (IOTCON_ERROR_NONE != ret) { + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } +} + +int conv::service_manager_impl::register_discovery_info() +{ + // register resource + int properties; + iotcon_resource_interfaces_h resource_ifaces = NULL; + iotcon_resource_types_h resource_types = NULL; + int error; + + properties = IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE; + + error = iotcon_resource_types_create(&resource_types); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed"); + + iotcon_resource_types_add(resource_types, CONV_RESOURCE_TYPE_TIZEN_D2D_SERVICE); + + error = iotcon_resource_interfaces_create(&resource_ifaces); + + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "ri creation failed"); + + iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT); + + error = iotcon_resource_create("/tizen/d2d-service", resource_types, resource_ifaces, properties, iotcon_request_cb, this, &iotcon_resource); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource creation failed"); + + _D("device info registered as resource"); + iotcon_resource_types_destroy(resource_types); + iotcon_resource_interfaces_destroy(resource_ifaces); + + return CONV_ERROR_NONE; +} + diff --git a/daemon/service_mgr_impl.h b/daemon/service_mgr_impl.h new file mode 100644 index 0000000..5c64451 --- /dev/null +++ b/daemon/service_mgr_impl.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SERVICE_MANAGER_IMPL_H__ +#define __SERVICE_MANAGER_IMPL_H__ + +#include +#include +#include +#include "manager_iface.h" +#include "request.h" +#include "service_provider_base.h" + +namespace conv { + class service_manager_impl : public manager_iface { + public: + service_manager_impl(); + ~service_manager_impl(); + + int init(); + int release(); + int handle_request(request* request_obj); + + int get_service_info_for_discovery(json* service_json); + + private: + typedef std::list service_provider_list_t; + + int register_provider(service_provider_base *provider_base); + int register_discovery_info(); + service_provider_list_t provider_list; + }; + + namespace service_manager { + void set_instance(service_manager_impl* mgr); + int handle_request(request* request_obj); + } +} + +#endif /* __SERVICE_MANAGER_IMPL_H__ */ diff --git a/daemon/service_provider/app_comm_service_info.h b/daemon/service_provider/app_comm_service_info.h new file mode 100644 index 0000000..c8518ad --- /dev/null +++ b/daemon/service_provider/app_comm_service_info.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __APP_COMMUNICATION_SERVICE_INFO_H__ +#define __APP_COMMUNICATION_SERVICE_INFO_H__ + +#include +#include +#include +#include "../service_info_base.h" +#include "../request.h" +#include +#include +#include +#include + +namespace conv { + class app_comm_service_listener : public OnConnectListener, public OnDisconnectListener, public OnClientConnectListener, public OnClientDisconnectListener, + public OnMessageListener, public OnErrorListener { + public: + conv::request* request_obj; + string uri; + string channel_id; + + void onConnect(Client client){ + _D("onConnect Called"); + publish_response(CONV_ERROR_NONE, "onConnect", &client); + } + + void onDisconnect(Client client){ + _D("onDisconnect Called"); + publish_response(CONV_ERROR_NONE, "onDisconnect", &client); + } + + void onClientConnect(Client client){ + _D("onClientDisconnect Called"); + publish_response(CONV_ERROR_NONE, "onClientConnect", &client); + } + + void onClientDisconnect(Client client){ + _D("onClientDisconnect Called"); + publish_response(CONV_ERROR_NONE, "onClientDisconnect", &client); + } + + void onMessage(Message message){ + _D("onMessage Called"); + + if ( request_obj != NULL ) + { + _D(RED("publishing_response")); + json result; + json payload; + json message_json; + json description; + + _D("size %d", message.m_payload_size); + _D("payload %s", message.m_payload); + + message_json.set(NULL, CONV_JSON_EVENT, message.m_event); + message_json.set(NULL, CONV_JSON_MESSAGE, message.m_data); + message_json.set(NULL, CONV_JSON_FROM, message.m_from); + string payload_str(reinterpret_cast(message.m_payload), message.m_payload_size); + + json payload_json = payload_str; + message_json.set(NULL, CONV_JSON_PAYLOAD, payload_json); + message_json.set(NULL, CONV_JSON_PAYLOAD_SIZE, message.m_payload_size); + + payload.set(NULL, CONV_JSON_RESULT_TYPE, "onMessage"); + payload.set(NULL, CONV_JSON_MESSAGE, message_json); + + description = request_obj->get_description(); + + description.set(CONV_JSON_CHANNEL, CONV_JSON_URI, uri); + description.set(CONV_JSON_CHANNEL, CONV_JSON_CHANNEL_ID, channel_id); + + result.set(NULL, CONV_JSON_DESCRIPTION, description); + result.set(NULL, CONV_JSON_PAYLOAD, payload); + request_obj->publish(CONV_ERROR_NONE, result); + } + } + + void onError(Client client){ + _D("onError Called"); + publish_response(CONV_ERROR_NONE, "onError", &client); + } + + void publish_response(int error, string result_type, Client *client) { + bool isHost = client->isHost(); + int connecttime = client->getConnectTime(); + + if ( request_obj != NULL ) + { + _D(RED("publishing_response")); + json result; + json payload; + json client_json; + json description; + + client_json.set(NULL, CONV_JSON_IS_HOST, isHost); + client_json.set(NULL, CONV_JSON_CONNECT_TIME, connecttime); + client_json.set(NULL, CONV_JSON_CLIENT_ID, client->getId()); + + payload.set(NULL, CONV_JSON_RESULT_TYPE, result_type); + payload.set(NULL, CONV_JSON_CLIENT, client_json); + + description = request_obj->get_description(); + + description.set(CONV_JSON_CHANNEL, CONV_JSON_URI, uri); + description.set(CONV_JSON_CHANNEL, CONV_JSON_CHANNEL_ID, channel_id); + + result.set(NULL, CONV_JSON_DESCRIPTION, description); + result.set(NULL, CONV_JSON_PAYLOAD, payload); + request_obj->publish(error, result); + } + } + }; + + // application information to handle app-to-app service with specific 'channel' + class application_info { + public: + Channel* application; + app_comm_service_listener service_listener; + }; + + typedef vector application_info_list_t; + + // service information to handle app-to-app service with specific device 'id' + class app_comm_service_info : public service_info_base { + public: + ~app_comm_service_info() { + if ( service_obj != NULL ) + { + delete service_obj; + } + + if ( registered_request != NULL ) + { + delete registered_request; + } + + for (application_info_list_t::iterator iter = application_info_list.begin(); iter != application_info_list.end(); ++iter) + { + application_info *app_info = *iter; + delete app_info; + application_info_list.erase(iter); + } + } + std::string id; + Service* service_obj; + bool is_local; + conv::request* registered_request; + + application_info_list_t application_info_list; + }; + +} +#endif /* __APP_COMMUNICATION_SERVICE_INFO_H__ */ diff --git a/daemon/service_provider/app_comm_service_provider.cpp b/daemon/service_provider/app_comm_service_provider.cpp new file mode 100644 index 0000000..344e335 --- /dev/null +++ b/daemon/service_provider/app_comm_service_provider.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app_comm_service_provider.h" +#include "../client_mgr_impl.h" +#include + +using namespace std; + +class ResultClient : public Result_Base +{ + public: + void onSuccess(Client abc) + { + _D("Client Success"); + } + void onError(Error) + { + _D("Client Error"); + } +}; + +class ResultDisconnect : public Result_Base +{ + public: + conv::application_info* app_info; + void onSuccess(Client abc) + { + _D("Client Success"); + release(); + } + void onError(Error) + { + _D("Client Success"); + release(); + } + private: + void release() + { + } +}; + +static ResultClient result_connect; +static ResultDisconnect result_disconnect; + +conv::app_comm_service_provider::app_comm_service_provider() +{ + _type = CONV_SERVICE_TYPE_SMARTVIEW_APP_COMMUNICATION; + _resource_type = CONV_RESOURCE_TYPE_SMARTVIEW_APP_COMMUNICATION; + _uri = CONV_URI_SMARTVIEW_APP_COMMUNICATION; +} + +conv::app_comm_service_provider::~app_comm_service_provider() +{ +} + +int conv::app_comm_service_provider::init() +{ + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::release() +{ + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::load_service_info(request* request_obj) +{ + string client; + conv::client* client_obj = NULL; + int is_local = 0; + + json service; + string name, version, type, id, uri; + + json description = request_obj->get_description(); + + description.get(NULL, CONV_JSON_SERVICE, &service); + + service.get(NULL, CONV_JSON_SERVICE_DATA_NAME, &name); + service.get(NULL, CONV_JSON_SERVICE_DATA_VERSION, &version); + service.get(NULL, CONV_JSON_SERVICE_DATA_TYPE, &type); + service.get(NULL, CONV_JSON_SERVICE_DATA_ID, &id); + service.get(NULL, CONV_JSON_SERVICE_DATA_URI, &uri); + + description.get(NULL, CONV_JSON_IS_LOCAL, &is_local); + + client = request_obj->get_sender(); + + _D("client id : %s", client.c_str()); + client_obj = conv::client_manager::get_client(client); + IF_FAIL_RETURN_TAG(client_obj, CONV_ERROR_OUT_OF_MEMORY, _E, "client info alloc failed"); + + app_comm_service_info *svc_info = NULL; + + if (is_local == 1) + { + service_info_base* svc_info_base = client_obj->get_service_info(_type, "LOCAL_HOST"); + + if ( svc_info_base != NULL ) { + _D("local service instance already exists"); + svc_info = reinterpret_cast(svc_info_base); + + if (svc_info == NULL) + { + _D("casting failed"); + return CONV_ERROR_INVALID_OPERATION; + } + } + else + { + _D("allocating new service instance for local service"); + svc_info = new app_comm_service_info(); + + svc_info->is_local = true; + client_obj->add_service_info(_type, "LOCAL_HOST", (service_info_base*)svc_info); + + _D("MSF service is created"); + } + } else { + service_info_base* svc_info_base = client_obj->get_service_info(_type, id); + + if ( svc_info_base != NULL ) { + _D("service instance already exists"); + svc_info = reinterpret_cast(svc_info_base); + + if (svc_info == NULL) + { + _D("casting failed"); + return CONV_ERROR_INVALID_OPERATION; + } + } + else + { + _D("allocating new service instance"); + svc_info = new app_comm_service_info(); + + _D("uri : %s", uri.c_str()); + svc_info->service_obj = new Service(id, version, name, type, uri); + svc_info->is_local = false; + client_obj->add_service_info(_type, id, (service_info_base*)svc_info); + + _D("MSF service is created"); + } + } + request_obj->service_info = svc_info; + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::start_request(request* request_obj) +{ + _D("communcation/start requested"); + app_comm_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + json channel; + request_obj->get_channel_from_description(&channel); + + string uri, channel_id; + + channel.get(NULL, CONV_JSON_URI, &uri); + channel.get(NULL, CONV_JSON_CHANNEL_ID, &channel_id); + + application_info *app_info = NULL; + + for (application_info_list_t::iterator iter = svc_info->application_info_list.begin(); iter != svc_info->application_info_list.end(); ++iter) { + _D("iteration"); + if ( (*iter) != NULL && !(*iter)->service_listener.uri.compare(uri) && !(*iter)->service_listener.channel_id.compare(channel_id) ) + { + if ( (*iter)->application != NULL ) + { + _D("already started"); + // check if it's connected and re-try if it's not + return CONV_ERROR_INVALID_OPERATION; + } else { + _D("app_info exists but no application instance"); + app_info = (*iter); + break; + } + } + } + + if ( app_info == NULL ) + { + app_info = new application_info(); + + app_info->service_listener.uri = uri; + app_info->service_listener.channel_id = channel_id; + } + + // if it's local -> server application + if ( svc_info->is_local ) + { + _D("COMMUNCATION_START : local channel. channel_id : %s", channel_id.c_str()); + Channel* application = Service::getLocal().createChannel(channel_id); + + // add listeners + app_info->service_listener.request_obj = svc_info->registered_request; + application->setonConnectListener(&app_info->service_listener); + application->setonClientConnectListener(&app_info->service_listener); + application->setonClientDisconnectListener(&app_info->service_listener); + application->setonErrorListener(&app_info->service_listener); + application->setonDisconnectListener(&app_info->service_listener); + application->addOnAllMessageListener(&app_info->service_listener); + + app_info->application = application; + application->set_connect_result(NULL); + application->connect(); + _D("connect called"); + svc_info->application_info_list.push_back(app_info); + } else { + _D("COMMUNCATION_START : uri : %s, channel_id : %s", uri.c_str(), channel_id.c_str()); + Application* application = new Application(svc_info->service_obj, uri, channel_id); + + // add listeners + app_info->service_listener.request_obj = svc_info->registered_request; + application->setonConnectListener(&app_info->service_listener); + application->setonClientConnectListener(&app_info->service_listener); + application->setonClientDisconnectListener(&app_info->service_listener); + application->setonErrorListener(&app_info->service_listener); + application->setonDisconnectListener(&app_info->service_listener); + application->addOnAllMessageListener(&app_info->service_listener); + + app_info->application = application; + + application->set_connect_result(NULL); + application->connect(); + + svc_info->application_info_list.push_back(app_info); + } + _D("connect requested"); + + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::stop_request(request* request_obj) +{ + _D("communcation/stop requested"); + app_comm_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + json channel; + request_obj->get_channel_from_description(&channel); + + string uri, channel_id; + + channel.get(NULL, CONV_JSON_URI, &uri); + channel.get(NULL, CONV_JSON_CHANNEL_ID, &channel_id); + + for (application_info_list_t::iterator iter = svc_info->application_info_list.begin(); iter != svc_info->application_info_list.end(); ++iter) { + _D("%s, %s", (*iter)->service_listener.uri.c_str(), (*iter)->service_listener.channel_id.c_str()); + if ( (*iter) != NULL && !(*iter)->service_listener.uri.compare(uri) && !(*iter)->service_listener.channel_id.compare(channel_id) ) + { + application_info *app_info = *iter; + + _D("COMMUNCATION_STOP : uri : %s, channel_id : %s", uri.c_str(), channel_id.c_str()); + + if ( *iter == NULL ) + { + _D("iter is NULL"); + } + + if ( svc_info->is_local ) + { + result_disconnect.app_info = app_info; + app_info->application->set_disconnect_result(NULL); + app_info->application->disconnect(); + + app_info->application = NULL; + delete app_info; + svc_info->application_info_list.erase(iter); + } else { + result_disconnect.app_info = app_info; + ((Application*)app_info->application)->set_disconnect_result(NULL); + ((Application*)app_info->application)->disconnect(); + + delete (Application*)app_info->application; + app_info->application = NULL; + delete app_info; + svc_info->application_info_list.erase(iter); + } + return CONV_ERROR_NONE; + } + } + + _D("no connection found"); + return CONV_ERROR_NONE; +} + + +int conv::app_comm_service_provider::get_request(request* request_obj) +{ + _D("communcation/get requested"); + app_comm_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + json channel; + request_obj->get_channel_from_description(&channel); + + string uri, channel_id; + + channel.get(NULL, CONV_JSON_URI, &uri); + channel.get(NULL, CONV_JSON_CHANNEL_ID, &channel_id); + + application_info *app_info = NULL; + + for (application_info_list_t::iterator iter = svc_info->application_info_list.begin(); iter != svc_info->application_info_list.end(); ++iter) { + _D("iteration"); + if ( (*iter) != NULL && !(*iter)->service_listener.uri.compare(uri) && !(*iter)->service_listener.channel_id.compare(channel_id) ) + { + if ( (*iter)->application != NULL ) + { + _D("app_info exists and application instance exists"); + app_info = (*iter); + + Clients* client_list = app_info->application->getclients(); + + if ( svc_info->registered_request == NULL) + { + _D("No callback is registered"); + request_obj->reply(CONV_ERROR_INVALID_OPERATION); + delete request_obj; + + return CONV_ERROR_INVALID_OPERATION; + } + + if (client_list == NULL) { + _D("No clients"); + request_obj->reply(CONV_ERROR_NO_DATA); + delete request_obj; + + return CONV_ERROR_NO_DATA; + } else { + std::list cl = client_list->lists(); + + int cs_index = 0; + + Client client_obj; + _D("clients size = %d", client_list->size()); + + json result; + + for (auto cs_itr = cl.begin(); cs_itr != cl.end(); cs_itr++) { + cs_index++; + json client; + + client.set(NULL, CONV_JSON_CLIENT_ID, (*cs_itr).getId()); + client.set(NULL, CONV_JSON_IS_HOST, (*cs_itr).isHost()); + client.set(NULL, CONV_JSON_CONNECT_TIME, (*cs_itr).getConnectTime()); + Channel* cha = NULL; + cha = (*cs_itr).getChannel(); + + if (cha != NULL) + client.set(NULL, CONV_JSON_CHANNEL_URI, cha->getChannelUri(NULL).c_str()); + + result.array_append(NULL, CONV_JSON_CLIENT_LIST, client); + } + send_response(result, svc_info->registered_request); + + return CONV_ERROR_NONE; + } + } + } + } + + _D("service is not started"); + + return CONV_ERROR_INVALID_OPERATION; +} + +int conv::app_comm_service_provider::send_response(json payload, request* request_obj) +{ + _D(RED("publishing_response")); + json result; + json description; + + payload.set(NULL, CONV_JSON_RESULT_TYPE, "getClient"); + + description = request_obj->get_description(); + + result.set(NULL, CONV_JSON_DESCRIPTION, description); + result.set(NULL, CONV_JSON_PAYLOAD, payload); + request_obj->publish(CONV_ERROR_NONE, result); + + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::set_request(request* request_obj) +{ + _D("communcation/set requested"); + app_comm_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + json channel; + request_obj->get_channel_from_description(&channel); + + string uri, channel_id; + + channel.get(NULL, CONV_JSON_URI, &uri); + channel.get(NULL, CONV_JSON_CHANNEL_ID, &channel_id); + + for (application_info_list_t::iterator iter = svc_info->application_info_list.begin(); iter != svc_info->application_info_list.end(); ++iter) { + _D("iteration"); + if ( (*iter) != NULL && !(*iter)->service_listener.uri.compare(uri) && !(*iter)->service_listener.channel_id.compare(channel_id) ) + { + if ( (*iter)->application != NULL ) + { + _D("publishing payload"); + + json payload; + + request_obj->get_payload_from_description(&payload); + + char* message = new char[strlen(payload.str().c_str())+1]; + + strcpy(message, payload.str().c_str()); + + string payload_str = payload.str(); + + (*iter)->application->publish("d2d_service_message", NULL, reinterpret_cast(message), strlen(message)); + + _D("publishing done"); + + delete message; + return CONV_ERROR_NONE; + } + } + } + _D("service is not started"); + + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::register_request(request* request_obj) +{ + _D("communcation/recv requested"); + app_comm_service_info *svc_info = reinterpret_cast(request_obj->service_info); + svc_info->registered_request = request_obj; + + request_obj->reply(CONV_ERROR_NONE); + _D("subscribe requested"); + + return CONV_ERROR_NONE; +} + +int conv::app_comm_service_provider::get_service_info_for_discovery(json* json_obj) +{ + json_obj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_TYPE, CONV_SERVICE_APP_TO_APP_COMMUNICATION); + + // set data for service handle + connection_h connection; + IF_FAIL_RETURN_TAG(connection_create(&connection) == CONNECTION_ERROR_NONE, CONV_ERROR_NOT_SUPPORTED, _E, "connection error"); + + char* address = NULL; + int ret = connection_get_ip_address(connection, CONNECTION_ADDRESS_FAMILY_IPV4, &address); + + if(ret != CONNECTION_ERROR_NONE) + { + _E("connection error"); + if (connection_get_ip_address(connection, CONNECTION_ADDRESS_FAMILY_IPV6, &address) != CONNECTION_ERROR_NONE) + { + _E("connection error"); + connection_destroy(connection); + return CONV_ERROR_NOT_SUPPORTED; + } + } + + if ( address == NULL || strlen(address) < 1 ) + { + _E("connection error"); + connection_destroy(connection); + return CONV_ERROR_NOT_SUPPORTED; + } else { + char uri[1000]; + Service local_service = Service::getLocal(); + + sprintf(uri, "http://%s:8001/api/v2/", address); + + json info; + + info.set(NULL, CONV_JSON_SERVICE_DATA_URI, uri); + info.set(NULL, CONV_JSON_SERVICE_DATA_VERSION, local_service.getVersion()); + info.set(NULL, CONV_JSON_SERVICE_DATA_TYPE, local_service.getType()); + info.set(NULL, CONV_JSON_SERVICE_DATA_ID, local_service.getId()); + info.set(NULL, CONV_JSON_SERVICE_DATA_NAME, local_service.getName()); + + json_obj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_INFO, info); + g_free(address); + } + + connection_destroy(connection); + return CONV_ERROR_NONE; +} diff --git a/daemon/service_provider/app_comm_service_provider.h b/daemon/service_provider/app_comm_service_provider.h new file mode 100644 index 0000000..ec204a7 --- /dev/null +++ b/daemon/service_provider/app_comm_service_provider.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __APP_COMMUNICATION_SERVICE_PROVIDER_H__ +#define __APP_COMMUNICATION_SERVICE_PROVIDER_H__ + +#include +#include +#include +#include "../service_provider_base.h" +#include "app_comm_service_info.h" + +namespace conv { + class app_comm_service_provider : public service_provider_base { + public: + app_comm_service_provider(); + ~app_comm_service_provider(); + + int init(); + int release(); + + app_comm_service_info* get_svc_info(request* request_obj); + int start_request(request* request_obj); + int stop_request(request* request_obj); + int get_request(request* request_obj); + int set_request(request* request_obj); + int register_request(request* request_obj); + int load_service_info(request* request_obj); + int get_service_info_for_discovery(json* json_obj); + + private: + int send_response(json payload, request* request_obj); + }; +} +#endif /* __APP_COMMUNICATION_SERVICE_PROVIDER_H__ */ diff --git a/daemon/service_provider/remote_app_control_service_info.h b/daemon/service_provider/remote_app_control_service_info.h new file mode 100644 index 0000000..262925c --- /dev/null +++ b/daemon/service_provider/remote_app_control_service_info.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REMOTE_APP_CONTROL_SERVICE_INFO_H__ +#define __REMOTE_APP_CONTROL_SERVICE_INFO_H__ + +#include +#include +#include +#include "../service_info_base.h" +#include "../iotcon_communication_info.h" +#include "../request.h" +#include + +namespace conv { + class remote_app_control_service_info : public service_info_base { + public: + ~remote_app_control_service_info() + { + if ( registered_request != NULL ) + { + delete registered_request; + } + + if ( iotcon_info_obj.iotcon_resource_handle != NULL ) + { + iotcon_remote_resource_destroy(iotcon_info_obj.iotcon_resource_handle); + } + if ( iotcon_info_obj.iotcon_representation_handle != NULL ) + { + iotcon_representation_destroy(iotcon_info_obj.iotcon_representation_handle); + } + } + std::string device_id; + std::string device_name; + std::string device_address; + request* registered_request; + iotcon_communication_info iotcon_info_obj; + }; + +} +#endif /* __REMOTE_APP_CONTROL_SERVICE_INFO_H__ */ diff --git a/daemon/service_provider/remote_app_control_service_provider.cpp b/daemon/service_provider/remote_app_control_service_provider.cpp new file mode 100644 index 0000000..5718f54 --- /dev/null +++ b/daemon/service_provider/remote_app_control_service_provider.cpp @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "remote_app_control_service_provider.h" +#include "../client_mgr_impl.h" + +using namespace std; + +struct app_control_cb_info_s { + int req_id; + iotcon_request_h request_handle; +}; + +struct response_cb_info_s { + int req_id; + conv::request* request_obj; +}; + +static int get_req_id() +{ + static int req_id = 0; + + if (++req_id < 0) { + req_id = 1; + } + + return req_id; +} + +static std::map app_control_cb_map; +static std::map response_cb_map; + +conv::remote_app_control_service_provider::remote_app_control_service_provider() +{ + _type = CONV_SERVICE_TYPE_REMOTE_APP_CONTROL; + _resource_type = CONV_RESOURCE_TYPE_REMOTE_APP_CONTROL; + _uri = CONV_URI_SMARTVIEW_REMOTE_APP_CONTROL; +} + +conv::remote_app_control_service_provider::~remote_app_control_service_provider() +{ + app_control_cb_map.clear(); + response_cb_map.clear(); +} + +static int _send_response(iotcon_request_h request, iotcon_representation_h repr, + iotcon_response_result_e result) +{ + int ret; + iotcon_response_h response; + + ret = iotcon_response_create(request, &response); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_create() Fail(%d)", ret); + return CONV_ERROR_INVALID_OPERATION; + } + + ret = iotcon_response_set_result(response, result); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_set_result() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + ret = iotcon_response_set_representation(response, IOTCON_INTERFACE_DEFAULT, repr); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_set_representation() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + /* send Representation to the client */ + ret = iotcon_response_send(response); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_send() Fail(%d)", ret); + iotcon_response_destroy(response); + return CONV_ERROR_INVALID_OPERATION; + } + + iotcon_response_destroy(response); + + return CONV_ERROR_NONE; +} + +static void _app_control_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data) +{ + _D("app control reply received"); + + int reply_id = (int)user_data; + + std::map::iterator find_iter = app_control_cb_map.find(reply_id); + + IF_FAIL_VOID_TAG(find_iter != app_control_cb_map.end(), _E, "No reply data"); + + app_control_cb_info_s cb_info = find_iter->second; + + bundle* p_bundle; + iotcon_representation_h rep; + iotcon_representation_create(&rep); + iotcon_state_h state; + iotcon_state_create(&state); + + app_control_export_as_bundle(reply, &p_bundle); + + bundle_raw* p_bundle_raw; + int len; + bundle_encode(p_bundle, &p_bundle_raw, &len); + char* bundle_raw = reinterpret_cast(p_bundle_raw); + + iotcon_state_add_str(state, CONV_JSON_APP_CONTROL, bundle_raw); + iotcon_state_add_int(state, CONV_JSON_REQ_ID, cb_info.req_id); + + iotcon_representation_set_state(rep, state); + + _D("Send response to sender"); + _send_response(cb_info.request_handle, rep, IOTCON_RESPONSE_OK); + _D("Response sent"); + + bundle_free(p_bundle); + app_control_cb_map.erase(find_iter); +} + +static void handle_request(iotcon_representation_h rep, iotcon_request_h request) +{ + iotcon_state_h state; + char* appctl_char; + app_control_h app_control; + int reply = 0; + + int ret = iotcon_representation_get_state(rep, &state); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_representation_get_state() Fail(%d)", ret); + return; + } + + ret = iotcon_state_get_str(state, CONV_JSON_APP_CONTROL, &appctl_char); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_state_get_str() Fail(%d)", ret); + return; + } + + bundle_raw* encoded = reinterpret_cast(appctl_char); + bundle* appctl_bundle = bundle_decode(encoded, strlen(appctl_char)); + + app_control_create(&app_control); + app_control_import_from_bundle(app_control, appctl_bundle); + + iotcon_state_get_int(state, CONV_JSON_REPLY, &reply); + + if ( reply == 1 ) + { + bool waiting_reply = false; + + // check if it's already launched and waiting for app_control response + for(std::map::iterator it = app_control_cb_map.begin(); it != app_control_cb_map.end(); it++) { + app_control_cb_info_s found_cb_info = it->second; + if(found_cb_info.request_handle == request) { + waiting_reply = true; + _D("app_control_send_launch_request is already called...waiting reply"); + break; + } + } + + if ( !waiting_reply ) + { + int req_id; + int reply_id = get_req_id(); + + iotcon_state_get_int(state, CONV_JSON_REQ_ID, &req_id); + + app_control_cb_info_s cb_info; + cb_info.req_id = req_id; + cb_info.request_handle = request; + app_control_cb_map[reply_id] = cb_info; + + app_control_send_launch_request(app_control, _app_control_cb, (void*)reply_id); + _D("app_control_send_launch_request with callback"); + + bundle_free(appctl_bundle); + } + } else { + iotcon_response_result_e result; + ret = app_control_send_launch_request(app_control, NULL, NULL); + + if (ret != APP_CONTROL_ERROR_NONE) + { + _E("Launch request failed(%d)", ret); + result = IOTCON_RESPONSE_ERROR; + } else { + _D("Launch request succeeded"); + result = IOTCON_RESPONSE_OK; + } + bundle_free(appctl_bundle); + app_control_destroy(app_control); + + _send_response(request, NULL, result); + } +} + +void conv::remote_app_control_service_provider::iotcon_request_cb(iotcon_resource_h resource, iotcon_request_h request, void *user_data) +{ + _D("request cb called"); + + int ret; + iotcon_request_type_e type; + char *host_address; + + IF_FAIL_VOID_TAG(request, _E, "request is NULL"); + + ret = iotcon_request_get_host_address(request, &host_address); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_request_get_host_address() Fail(%d)", ret); + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } + _I("host_address : %s", host_address); + + ret = iotcon_request_get_request_type(request, &type); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_request_get_types() Fail(%d)", ret); + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } + + _D("request type : %d", type); + + if (IOTCON_REQUEST_PUT == type) + { + iotcon_representation_h req_repr; + _I("GET request"); + + ret = iotcon_request_get_representation(request, &req_repr); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_request_get_representation() Fail(%d)", ret); + return; + } + + handle_request(req_repr, request); + iotcon_representation_destroy(req_repr); + } + + if (IOTCON_ERROR_NONE != ret) { + _send_response(request, NULL, IOTCON_RESPONSE_ERROR); + return; + } +} + +int conv::remote_app_control_service_provider::init() +{ + // register resource + int properties; + iotcon_resource_interfaces_h resource_ifaces = NULL; + iotcon_resource_types_h resource_types = NULL; + int error; + + properties = IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE; + + error = iotcon_resource_types_create(&resource_types); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed"); + + iotcon_resource_types_add(resource_types, _resource_type.c_str()); + + error = iotcon_resource_interfaces_create(&resource_ifaces); + + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "ri creation failed"); + + iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT); + + + error = iotcon_resource_create(CONV_URI_SMARTVIEW_REMOTE_APP_CONTROL, resource_types, resource_ifaces, properties, iotcon_request_cb, NULL, &iotcon_resource); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource creation failed"); + + + iotcon_resource_types_destroy(resource_types); + iotcon_resource_interfaces_destroy(resource_ifaces); + + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::release() +{ + // unregister resource + int error = iotcon_resource_destroy(iotcon_resource); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "resource destroy failed"); + iotcon_resource = NULL; + + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::start_request(request* request_obj) +{ + _D("communcation/start requested"); + int error; + + int properties; + iotcon_resource_interfaces_h resource_ifaces = NULL; + iotcon_resource_types_h resource_types = NULL; + + remote_app_control_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + if ( svc_info->iotcon_info_obj.iotcon_resource_handle != NULL ) + { + _D("already started"); + return CONV_ERROR_INVALID_OPERATION; + } + + properties = IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE; + + error = iotcon_resource_types_create(&resource_types); + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "rt creation failed"); + + iotcon_resource_types_add(resource_types, svc_info->iotcon_info_obj.resource_type.c_str()); + + error = iotcon_resource_interfaces_create(&resource_ifaces); + + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "ri creation failed"); + + iotcon_resource_interfaces_add(resource_ifaces, IOTCON_INTERFACE_DEFAULT); + + error = iotcon_remote_resource_create(svc_info->iotcon_info_obj.address.c_str(), IOTCON_CONNECTIVITY_IPV4, svc_info->iotcon_info_obj.uri.c_str(), properties, resource_types, resource_ifaces, + &(svc_info->iotcon_info_obj.iotcon_resource_handle)); + + _D("remote resource created : %s, %s", svc_info->iotcon_info_obj.address.c_str(), svc_info->iotcon_info_obj.uri.c_str()); + + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "remote resource creation failed %s, %s", svc_info->iotcon_info_obj.address.c_str(), svc_info->iotcon_info_obj.uri.c_str()); + + iotcon_resource_types_destroy(resource_types); + iotcon_resource_interfaces_destroy(resource_ifaces); + + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::stop_request(request* request_obj) +{ + _D("communcation/stop requested"); + + remote_app_control_service_info *svc_info = reinterpret_cast(request_obj->service_info); + + if ( svc_info->iotcon_info_obj.iotcon_resource_handle == NULL ) + { + _D("not even started"); + return CONV_ERROR_INVALID_OPERATION; + } + + iotcon_remote_resource_destroy(svc_info->iotcon_info_obj.iotcon_resource_handle); + + svc_info->iotcon_info_obj.iotcon_resource_handle = NULL; + + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::get_request(request* request_obj) +{ + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::send_response(json payload, request* request_obj) +{ + return CONV_ERROR_NONE; +} + +static void on_response(iotcon_remote_resource_h resource, iotcon_error_e err, + iotcon_request_type_e request_type, iotcon_response_h response, void *user_data) +{ + int ret; + iotcon_response_result_e response_result; + iotcon_representation_h repr; + + ret = iotcon_response_get_result(response, &response_result); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_response_get_result() Fail(%d)", ret); + return; + } + + if (IOTCON_RESPONSE_OK != response_result) { + _E("_on_response_observe Response error(%d)", response_result); + return; + } + + ret = iotcon_response_get_representation(response, &repr); + + int req_id = -1; + iotcon_state_h state; + iotcon_representation_get_state(repr, &state); + iotcon_state_get_int(state, CONV_JSON_REQ_ID, &req_id); + + std::map::iterator find_iter = response_cb_map.find(req_id); + + IF_FAIL_VOID_TAG(find_iter != response_cb_map.end(), _E, "No callback found for response"); + + response_cb_info_s cb_info = find_iter->second; + + char* appctl_char; + + ret = iotcon_state_get_str(state, CONV_JSON_APP_CONTROL, &appctl_char); + if (IOTCON_ERROR_NONE != ret) { + _E("iotcon_state_get_str() Fail(%d)", ret); + return; + } + + _D(RED("publishing_response")); + json result; + json payload; + json description; + + payload.set(NULL, CONV_JSON_APP_CONTROL, appctl_char); + + result.set(NULL, CONV_JSON_DESCRIPTION, cb_info.request_obj->get_description()); + result.set(NULL, CONV_JSON_PAYLOAD, payload); + + if ( cb_info.request_obj ) + { + cb_info.request_obj->publish(CONV_ERROR_NONE, result); + _D("response published"); + } + response_cb_map.erase(find_iter); +} + +int conv::remote_app_control_service_provider::set_request(request* request_obj) +{ + remote_app_control_service_info *svc_info = reinterpret_cast(request_obj->service_info); + int error; + + request_obj->communication_info = &(svc_info->iotcon_info_obj); + + iotcon_representation_h representation; + iotcon_representation_create(&representation); + + json payload; + request_obj->get_payload_from_description(&payload); + + string app_control; + int reply; + + payload.get(NULL, CONV_JSON_APP_CONTROL, &app_control); + payload.get(NULL, CONV_JSON_REPLY, &reply); + + iotcon_state_h state; + iotcon_state_create(&state); + + iotcon_state_add_str(state, CONV_JSON_APP_CONTROL, (char*)app_control.c_str()); + iotcon_state_add_int(state, CONV_JSON_REPLY, reply); + + if ( reply == 1 ) + { + int req_id = get_req_id(); + iotcon_state_add_int(state, CONV_JSON_REQ_ID, req_id); + + response_cb_info_s cb_info; + cb_info.req_id = req_id; + cb_info.request_obj = svc_info->registered_request; + response_cb_map[req_id] = cb_info; + } + + iotcon_representation_set_state(representation, state); + svc_info->iotcon_info_obj.iotcon_representation_handle = representation; + + iotcon_state_destroy(state); + + error = iotcon_remote_resource_put(svc_info->iotcon_info_obj.iotcon_resource_handle, representation, NULL, on_response, NULL); + + IF_FAIL_RETURN_TAG(error == IOTCON_ERROR_NONE, CONV_ERROR_INVALID_OPERATION, _E, "iotcon_remote_resource_put failed"); + + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::register_request(request* request_obj) +{ + _D("communcation/recv requested"); + remote_app_control_service_info *svc_info = reinterpret_cast(request_obj->service_info); + svc_info->registered_request = request_obj; + + request_obj->reply(CONV_ERROR_NONE); + _D("subscribe requested"); + + return CONV_ERROR_NONE; +} + + +int conv::remote_app_control_service_provider::load_service_info(request* request_obj) +{ + string client; + conv::client* client_obj = NULL; + + client = request_obj->get_sender(); + _D("client id : %s", client.c_str()); + client_obj = conv::client_manager::get_client(client); + IF_FAIL_RETURN_TAG(client_obj, CONV_ERROR_OUT_OF_MEMORY, _E, "client info alloc failed"); + + json description = request_obj->get_description(); + json service; + json device; + + string device_id; + string device_name; + string device_address; + string uri; + + description.get(NULL, CONV_JSON_SERVICE, &service); + description.get(NULL, CONV_JSON_DEVICE, &device); + + service.get(NULL, CONV_SERVICE_ID, &uri); + + device.get(NULL, CONV_DEVICE_ID, &device_id); + device.get(NULL, CONV_DEVICE_NAME, &device_name); + device.get(NULL, CONV_JSON_DEVICE_ADDRESS, &device_address); + + remote_app_control_service_info *svc_info = NULL; + service_info_base* svc_info_base = client_obj->get_service_info(_type, device_id); + + if ( svc_info_base != NULL ) { + _D("service instance already exists"); + svc_info = reinterpret_cast(svc_info_base); + + if (svc_info == NULL) + { + _D("casting failed"); + return CONV_ERROR_INVALID_OPERATION; + } + } + else + { + _D("allocating new service instance"); + svc_info = new remote_app_control_service_info(); + + svc_info->device_id = device_id; + svc_info->device_name = device_name; + svc_info->device_address = device_address; + + svc_info->iotcon_info_obj.address = device_address; + svc_info->iotcon_info_obj.uri = CONV_URI_SMARTVIEW_REMOTE_APP_CONTROL; + svc_info->iotcon_info_obj.resource_type = _resource_type; + + //save service info + client_obj->add_service_info(_type, device_id, (service_info_base*)svc_info); + + _D("remote app control service is created"); + } + + request_obj->service_info = svc_info; + return CONV_ERROR_NONE; +} + +int conv::remote_app_control_service_provider::get_service_info_for_discovery(json* json_obj) +{ + json_obj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_TYPE, CONV_SERVICE_REMOTE_APP_CONTROL); + + // set data for service handle + json info; + info.set(NULL, CONV_SERVICE_ID, _uri); + info.set(NULL, CONV_SERVICE_VERSION, "1.0"); + + json_obj->set(NULL, CONV_JSON_DISCOVERY_SERVICE_INFO, info); + + return CONV_ERROR_NONE; +} diff --git a/daemon/service_provider/remote_app_control_service_provider.h b/daemon/service_provider/remote_app_control_service_provider.h new file mode 100644 index 0000000..939e9e4 --- /dev/null +++ b/daemon/service_provider/remote_app_control_service_provider.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REMOTE_APP_CONTROL_SERVICE_PROVIDER_H__ +#define __REMOTE_APP_CONTROL_SERVICE_PROVIDER_H__ + +#include +#include +#include +#include "../service_provider_base.h" +#include "remote_app_control_service_info.h" + +namespace conv { + class remote_app_control_service_provider : public service_provider_base { + public: + remote_app_control_service_provider(); + ~remote_app_control_service_provider(); + + int init(); + int release(); + + int start_request(request* request_obj); + int stop_request(request* request_obj); + int get_request(request* request_obj); + int set_request(request* request_obj); + int register_request(request* request_obj); + int load_service_info(request* request_obj); + int get_service_info_for_discovery(json* json_obj); + + private: + iotcon_resource_h iotcon_resource; + int send_response(json payload, request* request_obj); + + static void iotcon_request_cb(iotcon_resource_h resource, iotcon_request_h request, void *user_data); + }; +} +#endif /* __REMOTE_APP_CONTROL_SERVICE_PROVIDER_H__ */ diff --git a/daemon/service_provider_base.h b/daemon/service_provider_base.h new file mode 100644 index 0000000..10f1dcb --- /dev/null +++ b/daemon/service_provider_base.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SERVICE_PROVIDER_BASE_H__ +#define __SERVICE_PROVIDER_BASE_H__ + +#include +#include "request.h" +#include "conv_json.h" + +namespace conv { + class service_provider_base { + public: + virtual ~service_provider_base() {} + virtual int init() = 0; + virtual int release() = 0; + + virtual int start_request(request* request_obj) = 0; + virtual int stop_request(request* request_obj) = 0; + virtual int get_request(request* request_obj) = 0; + virtual int set_request(request* request_obj) = 0; + virtual int register_request(request* request_obj) = 0; + virtual int load_service_info(request* request_obj) = 0; + virtual int get_service_info_for_discovery(json* json_obj) = 0; + + std::string get_type() { + return _type; + } + + std::string get_resource_type() { + return _resource_type; + } + + std::string get_uri() { + return _uri; + } + + protected: + std::string _type; + std::string _resource_type; + std::string _uri; + }; /* class service_provider_base */ +} + +#endif /* End of __SERVICE_PROVIDER_BASE_H__ */ diff --git a/daemon/util.cpp b/daemon/util.cpp new file mode 100644 index 0000000..8dc4510 --- /dev/null +++ b/daemon/util.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "util.h" +#include +#include +#include +#include "log.h" + +#include +#include + +using namespace std; + +std::string conv::util::get_bt_mac_address() +{ + static std::string g_mac_address; + if(g_mac_address.empty()){ + bt_initialize(); + char* mac_address; + bt_adapter_enable(); + int ret = bt_adapter_get_address(&mac_address); + IF_FAIL_RETURN_TAG(ret == 0, NULL, _E, "bluetooth get mac address failed : %d", ret); + _D("bluetooth get mac address : %s", mac_address); + g_mac_address = mac_address; + free(mac_address); + bt_deinitialize(); + } + _D("mac address:%s", g_mac_address.c_str()); + return g_mac_address; +} + + +std::string conv::util::get_device_name() +{ + static std::string g_device_name; + if(g_device_name.empty()) { + char* device_name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR); + //jhp27.park + if (device_name == NULL) + { + g_device_name = "Tizen"; + } else { + g_device_name = device_name; + } + _D("device_name: %s", g_device_name.c_str()); + } + + return g_device_name; +} + +static char make_p2p_mac(char c) +{ + char convert_c = c; + if ((convert_c >= 'A') && (convert_c <= 'F')) { + convert_c = ((((convert_c - 'A') + 10) | 0x02) - 10) + 'A'; + } else if ((convert_c >= '0') && (convert_c <= '9')) { + convert_c = ((convert_c - '0') | 0x02); + if (convert_c < 10) + convert_c = convert_c + '0'; + else + convert_c = 'A' + (convert_c - 10); + } else { + _E("wrong byte for mac!"); + } + return convert_c; +} + +std::string conv::util::get_p2p_mac_address() +{ + static std::string g_p2p_mac_address; + if(g_p2p_mac_address.empty()){ + char p2p_mac[MAC_ADDR_STR_LEN]; + memset(p2p_mac, 0x0, MAC_ADDR_STR_LEN); + + char* temp_addr = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS); + if (temp_addr == NULL) + { + _E("vconf_get_str Failed for %s", VCONFKEY_WIFI_BSSID_ADDRESS); + } + else + { + memcpy(p2p_mac, temp_addr, MAC_ADDR_STR_LEN-1); + p2p_mac[1] = make_p2p_mac(p2p_mac[1]); + _I("P2P mac is %s", p2p_mac); + free(temp_addr); + + g_p2p_mac_address = p2p_mac; + } + } + _D("p2p mac address:%s", g_p2p_mac_address.c_str()); + return g_p2p_mac_address; +} + +static gboolean misc_timer_worker(gpointer ud) +{ + _D("timer_work.."); + gpointer *tdata = (gpointer*)ud; + if (tdata[0]) + { + ((conv::util::timer_function)tdata[0])(tdata[1]); + } + return TRUE; +} + +void* conv::util::misc_start_timer(timer_function function, unsigned int interval, void *data) +{ + guint id = 0; + GSource *src = NULL; + gpointer *tdata = NULL; + + _D("misc_start_timer with interval[%d]", interval); + src = g_timeout_source_new(interval*1000); + //ASSERT(src != NULL); + + tdata = g_new0(gpointer, 2); + //ASSERT(tdata != NULL); + + tdata[0] = (void*)function; + tdata[1] = data; + + g_source_set_callback(src, misc_timer_worker, tdata, g_free); + id = g_source_attach(src, NULL); + g_source_unref(src); + + _D("Done with id[%d] in misc_start_timer", id); + return (void*)id; +} + +void conv::util::misc_stop_timer(void *timer) +{ + guint id = (guint) timer; + _D("Requested Stop Timer[%d]", id); + if (id) + { + if (!g_source_remove(id)) + { + _E("g_source_remove is fail (timer)"); + } + } +} diff --git a/daemon/util.h b/daemon/util.h new file mode 100644 index 0000000..3ba6279 --- /dev/null +++ b/daemon/util.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __D2D_SERVICE_UTIL_H__ +#define __D2D_SERVICE_UTIL_H__ +#include + +using namespace std; + +#define MAC_ADDR_STR_LEN 18 + +namespace conv { + namespace util { + std::string get_bt_mac_address(); + std::string get_device_name(); + std::string get_p2p_mac_address(); + + typedef void (*timer_function)(void *data); + void* misc_start_timer(timer_function function, unsigned int interval, void *data); + void misc_stop_timer(void *timer); + } +} +#endif + diff --git a/doc/d2d_conv_manager_doc.h b/doc/d2d_conv_manager_doc.h new file mode 100644 index 0000000..1e6b8aa --- /dev/null +++ b/doc/d2d_conv_manager_doc.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_MANAGER_DOC_H__ +#define __TIZEN_D2D_CONV_MANAGER_DOC_H__ + +/** + * @ingroup CAPI_CONVERGENCE_FRAMEWORK + * + * @defgroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK Convergence Manager + * + * @brief D2D Convergence Manager provides APIs to manage device-to-device convergence service. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK_OVERVIEW Overview + * Convergence Manager provides functions to discover services provided by near-by devices and to execute the services remotely. + * The services includes the communication between applications of remote devices, application control to the remote device, or user interaction method to the remote devices. \n + * + * Using Convergence Manager APIs, a feature to control the remote devices can be implemented, which is a basic function for the Internet of Things (IoT). + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/convergence.d2d\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +/** + * @ingroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @defgroup CAPI_D2D_CONVERGENCE_MANAGER_CHANNEL_MODULE Channel + * + * @brief D2D Convergence Manager Channel APIs to manage channel information which is service-specific. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_CHANNEL_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_CHANNEL_MODULE_OVERVIEW Overview + * Channel is a logically separated communication channel for each service, and thus the channel should be defined for each service. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_CHANNEL_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/convergence.d2d\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +/** + * @ingroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @defgroup CAPI_D2D_CONVERGENCE_MANAGER_DEVICE_MODULE Device + * + * @brief D2D Convergence Manager Device APIs to access device information. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_DEVICE_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_DEVICE_MODULE_OVERVIEW Overview + * Device is a representative of a separate hardware device. Device handle includes an identification (ID), a name, a type, and a service list. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_DEVICE_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/convergence.d2d\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +/** + * @ingroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @defgroup CAPI_D2D_CONVERGENCE_MANAGER_PAYLOAD_MODULE Payload + * + * @brief D2D Convergence Manager Payload APIs to write payload to send data or retrieve values from payload. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_PAYLOAD_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_PAYLOAD_MODULE_OVERVIEW Overview + * Payload is a set of data to transmit to or receive from the other devices, in order to perform the service. The fields of payload are defined based on the services. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_PAYLOAD_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/convergence.d2d\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +/** + * @ingroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @defgroup CAPI_D2D_CONVERGENCE_MANAGER_SERVICE_MODULE Service + * + * @brief D2D Convergence Manager Service APIs to connect and communicate to remote/local service. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_SERVICE_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_SERVICE_MODULE_OVERVIEW Overview + * Service is a core functioning implementation entity to process the requests of the users. Currently, three serivces are provided:\n + * + * - App Communication Service: provides functions to launch applications and to communicate with applications of remote devices.\n + * + * - App Control Service: provides Tizen application control feature between remote devices.\n + * + * - Remote Interaction: provides user interaction to remote devices.\n + * + * For more details, please refer to API guide page. + * + * @section CAPI_D2D_CONVERGENCE_MANAGER_SERVICE_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/convergence.d2d\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +#endif /* __TIZEN_D2D_CONV_MANAGER_DOC_H__ */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..8917534 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,36 @@ +INCLUDE_DIRECTORIES(include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common/) + +FILE(GLOB CLIENT_SRCS *.cpp) + +SET(client_depends "gio-2.0 dlog json-glib-1.0 capi-appfw-application bundle capi-system-info") + +IF("${PROFILE}" STREQUAL "mobile") +ADD_DEFINITIONS("-D_MOBILE_") +#SET(client_depends "${client_depends} security-server") +ENDIF("${PROFILE}" STREQUAL "mobile") + +IF("${PROFILE}" STREQUAL "tv") +ADD_DEFINITIONS("-D_TV_") +SET(client_depends "${client_depends}") +ENDIF("${PROFILE}" STREQUAL "tv") + +pkg_check_modules(client_pkgs REQUIRED ${client_depends}) +INCLUDE_DIRECTORIES(${client_pkgs_INCLUDE_DIRS}) +LINK_DIRECTORIES(${client_pkgs_LIBRARY_DIRS}) + +ADD_DEFINITIONS("-DBROKER_DBUS_INTERFACE=\"${DBUS_INTERFACE}\"") + +ADD_LIBRARY(${CLIENT} SHARED ${CLIENT_SRCS}) +TARGET_LINK_LIBRARIES(${CLIENT} ${client_pkgs_LIBRARIES}) +SET_TARGET_PROPERTIES(${CLIENT} PROPERTIES VERSION ${FULLVER} SOVERSION ${MAJORVER}) +INSTALL(TARGETS ${CLIENT} DESTINATION ${LIB_INSTALL_DIR}) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +CONFIGURE_FILE("${CLIENT}.pc.in" "${CLIENT}.pc" @ONLY) +INSTALL(FILES "${CLIENT}.pc" DESTINATION lib/pkgconfig) + +FILE(GLOB CLIENT_HEADER include/*.h) +FOREACH(hfile ${CLIENT_HEADER}) + INSTALL(FILES ${hfile} DESTINATION include) +ENDFOREACH(hfile) diff --git a/lib/conv_lib.cpp b/lib/conv_lib.cpp new file mode 100644 index 0000000..3faa678 --- /dev/null +++ b/lib/conv_lib.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "d2d_conv_service.h" +#include "conv_lib_json.h" +#include "internal_types.h" +#include "dbus_client.h" +#include "conv_lib_util.h" + +struct device_callback_info_s { + conv_discovery_cb cb; + void* user_data; + conv_h handle; +}; + +typedef std::map callback_map_t; +static callback_map_t callback_map; +//static device_callback_info_s* device_callback; + +static void conv_subject_cb(const char* subject, int req_id, int error, json data){ + _D("Callback response %d : subject[%s] json_data[%s]", req_id, subject, data.str().c_str()); + + + conv_device_h device = new (std::nothrow) _conv_device_handle_s(); + IF_FAIL_VOID_TAG(device, _E, "Memory Allocation Failed"); + + device->jbody = data; + + callback_map_t::iterator itor = callback_map.find(req_id); + if (itor == callback_map.end()) { + _D("No Callback found for the response[%d]", req_id); + return; + } + device_callback_info_s* callback_info = itor->second; + callback_info->cb(device, (conv_discovery_result_e)error, callback_info->user_data); +} + +static void register_subject_callbacks() +{ + static bool done = false; + + if (!done) { + conv::dbus_client::register_callback(CONV_SUBJECT_DISCOVERY_START, conv_subject_cb); + done = true; + } + _I("Done with registering subject callback"); +} + +EXTAPI int conv_create(conv_h* handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + *handle = new(std::nothrow) _conv_handle(); + ASSERT_ALLOC(*handle); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_destroy(conv_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + _D("conv_destroy.."); + conv::dbus_client::release(); + std::list::iterator itr_end = handle->request_ids.end(); + callback_map_t::iterator map_iter_end = callback_map.end(); + for (std::list::iterator iter_pos = handle->request_ids.begin(); iter_pos != itr_end; iter_pos++) + { + callback_map_t::iterator map_iter = callback_map.find(*iter_pos); + if (map_iter != map_iter_end) + callback_map.erase(map_iter); + } + delete handle; + return CONV_ERROR_NONE; +} + +EXTAPI int conv_discovery_start(conv_h handle, const int timeout_seconds, conv_discovery_cb callback, void* user_data) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(callback); + + //temp + //conv_set_discovery_cb(handle, callback, user_data); + + register_subject_callbacks(); + + device_callback_info_s *cb_info = new(std::nothrow)device_callback_info_s(); + cb_info->cb = callback; + cb_info->user_data = user_data; + cb_info->handle = handle; + + // input data when discovery requested.. + json input_data; + input_data.set(NULL, "timeout", timeout_seconds); + + int req_id; + const char* input = const_cast (input_data.str().c_str()); + _D("input:%s", input); + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_DISCOVERY_START, input_data.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + callback_map[req_id] = cb_info; + handle->request_ids.push_back(req_id); + _D("req_id:%d", req_id); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_discovery_stop(conv_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + int req_id; + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_DISCOVERY_STOP, NULL, NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + // unset callback.. + std::list::iterator req_itr = handle->request_ids.begin(); + for (; req_itr != handle->request_ids.end(); req_itr++) + { + int cur_req_id = *req_itr; + if (callback_map[cur_req_id] != NULL) + { + _D("free memory for callback[id:%d]", cur_req_id); + delete callback_map[cur_req_id]; + callback_map.erase(callback_map.find(cur_req_id)); + } + } + + return CONV_ERROR_NONE; +} + +// === Device +EXTAPI int conv_device_clone(conv_device_h original_handle, conv_device_h* target_handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(original_handle); + ASSERT_NOT_NULL(target_handle); + _conv_device_handle* device = new (std::nothrow) _conv_device_handle(); + device->jbody = original_handle->jbody; + + *target_handle = device; + return CONV_ERROR_NONE; +} + +EXTAPI int conv_device_destroy(conv_device_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + delete handle; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_device_get_property_string(conv_device_h handle, const char* key, char** value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key && value); + + std::string strval; + bool ret = handle->jbody.get(NULL, key, &strval); // path is NULL.. + if (ret == false || strval.empty()) return CONV_ERROR_NO_DATA; + *value = strdup(strval.c_str()); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_device_foreach_service(conv_device_h handle, conv_service_foreach_cb cb, void* user_data) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + json json_data = handle->jbody; + std::string strval; + + int service_count = 0; + service_count = json_data.array_get_size(CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA); // json data.. + + for (int index =0; index < service_count; index++) + { + _conv_service_handle* service = new (std::nothrow) _conv_service_handle(); + ASSERT_ALLOC(service); + + // service json data + json json_service; + std::string version, type, uri; + conv_service_e service_type; + /* + json_data.get_array_elem (CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA_VERSION, index, &version); + json_data.get_array_elem (CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA_TYPE, index, &type); + json_data.get_array_elem (CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA_URI, index, &uri); + json_data.get_array_elem (CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_TYPE, index, (int*)&service_type); + */ + json_data.get_array_elem(CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_DATA, index, &json_service); + json_data.get_array_elem(CONV_JSON_SERVICE_PATH, CONV_JSON_SERVICE_TYPE, index, (int*)&service_type); + + service->jservice = json_service; + service->service_type = service_type; + service->jdevice = handle->jbody; + service->connection_state = CONV_SERVICE_CONNECTION_STATE_CONNECTED; + + _D("index[%d] service json : %s", index, json_service.str().c_str()); + + //typedef void(* conv_service_foreach_cb)(conv_service_h service_handle, void* user_data); + cb(service, user_data); + delete service; + + // service json data includes features like name, version, type, uri and id.. + } + + return CONV_ERROR_NONE; +} + + diff --git a/lib/conv_lib_channel.cpp b/lib/conv_lib_channel.cpp new file mode 100644 index 0000000..28a72f5 --- /dev/null +++ b/lib/conv_lib_channel.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "d2d_conv_manager.h" +#include "conv_lib_json.h" +#include "internal_types.h" +#include "dbus_client.h" +#include "conv_lib_util.h" + +EXTAPI int conv_channel_create(conv_channel_h* handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + *handle = new(std::nothrow) _conv_channel_handle(); + ASSERT_ALLOC(*handle); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_channel_destroy(conv_channel_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + delete handle; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_channel_set_string(conv_channel_h handle, const char* key, const char* value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + handle->jchannel.set(NULL, key, value); + + return CONV_ERROR_NONE; +} + + +EXTAPI int conv_channel_get_string(conv_channel_h handle, const char* key, char** value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + std::list key_list; + handle->jchannel.get_keys(&key_list); + IF_FAIL_RETURN_TAG(key_list.size() > 0, CONV_ERROR_NO_DATA, _E, "No data"); + + // Check Invalid record key + std::string str; + IF_FAIL_RETURN_TAG(handle->jchannel.get(NULL, key, &str), CONV_ERROR_INVALID_PARAMETER, _E, "Value load failed"); + + *value = g_strdup(str.c_str()); + ASSERT_ALLOC(*value); + + return CONV_ERROR_NONE; +} + diff --git a/lib/conv_lib_json.cpp b/lib/conv_lib_json.cpp new file mode 100644 index 0000000..08d3141 --- /dev/null +++ b/lib/conv_lib_json.cpp @@ -0,0 +1,966 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "conv_lib_json.h" + +#define PATH_DELIM '.' +#define GVAR_VALUES "values" +#define GVAR_TYPES "types" + +static double string_to_double(const char* in) +{ + IF_FAIL_RETURN_TAG(in, 0, _E, "Parameter NULL"); + + // Locale-independent string-to-double conversion + double out; + std::istringstream istr(in); + istr.imbue(std::locale("C")); + istr >> out; + return out; +} + +static std::string double_to_string(double in, int prec) +{ + // Locale-independent double-to-string conversion + std::ostringstream ostr; + ostr.imbue(std::locale("C")); + ostr << std::setprecision(prec) << std::fixed << in; + return ostr.str(); +} + +json::json() +{ + 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); +} + +json::json(const json& j) +{ + json_node = json_node_copy(j.json_node); + IF_FAIL_VOID_TAG(json_node, _E, "Json object construction failed"); +} + +json::json(const char* s) +{ + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } +} + +json::json(const std::string& s) +{ + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } +} + +json::~json() +{ + release(); +} + +void json::parse(const char* s) +{ + gboolean result; + JsonParser *parser = NULL; + JsonNode *root = NULL; + + parser = json_parser_new(); + IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed"); + + result = json_parser_load_from_data(parser, s, -1, NULL); + IF_FAIL_CATCH_TAG(result, _E, "Parsing failed"); + + root = json_parser_get_root(parser); + IF_FAIL_CATCH_TAG(root, _E, "Getting root failed"); + + json_node = json_node_copy(root); + IF_FAIL_CATCH_TAG(json_node, _E, "Copying failed"); + +CATCH: + if (parser) + g_object_unref(parser); +} + +void json::release() +{ + if (json_node) { + json_node_free(json_node); + json_node = NULL; + } +} + +json& json::operator=(const json& j) +{ + release(); + json_node = json_node_copy(j.json_node); + if (!json_node) { + _E("Json object copy failed"); + } + return *this; +} + +json& json::operator=(const char* s) +{ + release(); + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } + return *this; +} + +json& json::operator=(const std::string& s) +{ + release(); + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } + return *this; +} + +bool json::operator==(const json& rhs) +{ + return node_equals(json_node, rhs.json_node); +} + +bool json::operator!=(const json& rhs) +{ + return !operator==(rhs); +} + +/* TODO +bool json::contains(const json& subset) const +{ + return false; +} +*/ + +char* 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 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; j < i; j++) { + g_free(tokens[j]); + } + g_free(tokens); + return NULL; +} + +static void free_tokenized_path(int length, char** tokens) +{ + int i; + if (tokens) { + for (i = 0; i < length; i++) { + g_free(tokens[i]); + } + g_free(tokens); + } +} + +static JsonObject* traverse(JsonNode* jnode, const char* path, bool force) +{ + IF_FAIL_RETURN_TAG(jnode, NULL, _E, "Invalid parameter"); + + int length = 0; + int depth = 0; + char **path_token = NULL; + JsonObject *jobj = NULL; + JsonObject *child_obj = NULL; + JsonNode *child_node = NULL; + + jobj = json_node_get_object(jnode); + IF_FAIL_RETURN(jobj, NULL); + + if (path) { + path_token = tokenize_path(path, &length); + IF_FAIL_RETURN_TAG(path_token, NULL, _E, "Invalid path"); + } + + for (depth = 0; depth < length; depth++) { + if (!json_object_has_member(jobj, path_token[depth])) { + if (force) { + child_obj = json_object_new(); + IF_FAIL_CATCH_TAG(child_obj, _E, "Memory allocation failed"); + json_object_set_object_member(jobj, path_token[depth], child_obj); + } else { + goto CATCH; + } + } + child_node = json_object_get_member(jobj, path_token[depth]); + IF_FAIL_CATCH(child_node && json_node_get_node_type(child_node) == JSON_NODE_OBJECT); + + jobj = json_node_get_object(child_node); + IF_FAIL_CATCH(jobj); + } + + free_tokenized_path(length, path_token); + return jobj; + +CATCH: + free_tokenized_path(length, path_token); + return NULL; +} + +bool json::set(const char* path, const char* key, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_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 json::set(const char* path, const char* key, int val) +{ + return set(path, key, static_cast(val)); +} + +bool 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 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 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 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 json::remove(const char* path, const char* key) +{ + 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); + } + + return true; +} + +bool 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 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 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 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 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 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 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 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 json::array_append(const char* path, const char* key, int val) +{ + return array_append(path, key, static_cast(val)); +} + +bool 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 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 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 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 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 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 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 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 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 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 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 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 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 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 json::get_keys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return get_member_list(json_node, *list); +} + +bool 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 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 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 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 < size; ++i) { + json_node_t *lhs_child = json_array_get_element(larr, i); + json_node_t *rhs_child = json_array_get_element(rarr, i); + IF_FAIL_RETURN(node_equals(lhs_child, rhs_child), false); + } + + return true; +} diff --git a/lib/conv_lib_json.h b/lib/conv_lib_json.h new file mode 100644 index 0000000..9edcf08 --- /dev/null +++ b/lib/conv_lib_json.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_LIB_JSON_H__ +#define __CONV_LIB_JSON_H__ + +#include +#include +#include +#include +#include "common.h" + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while (0) + +#define EMPTY_JSON_OBJECT "{}" +#define DEFAULT_PRECISION 3 + +class json { +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); + + bool remove(const char* path, const char* key); + + 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); +}; + +#endif // __CONV_LIB_JSON_H__ + diff --git a/lib/conv_lib_payload.cpp b/lib/conv_lib_payload.cpp new file mode 100644 index 0000000..fa9fa55 --- /dev/null +++ b/lib/conv_lib_payload.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "d2d_conv_manager.h" +#include "conv_lib_json.h" +#include "internal_types.h" +#include "dbus_client.h" +#include "conv_lib_util.h" + +EXTAPI int conv_payload_create(conv_payload_h* handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + *handle = new(std::nothrow) _conv_payload_handle(); + ASSERT_ALLOC(*handle); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_destroy(conv_payload_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + delete handle; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_set_string(conv_payload_h handle, const char* key, const char* value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + handle->jpayload.set(NULL, key, value); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_get_string(conv_payload_h handle, const char* key, char** value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + std::list key_list; + handle->jpayload.get_keys(&key_list); + IF_FAIL_RETURN_TAG(key_list.size() > 0, CONV_ERROR_NO_DATA, _E, "No data"); + + // Check Invalid record key + std::string str; + IF_FAIL_RETURN_TAG(handle->jpayload.get(NULL, key, &str), CONV_ERROR_INVALID_PARAMETER, _E, "Value load failed"); + + *value = g_strdup(str.c_str()); + ASSERT_ALLOC(*value); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_set_app_control(conv_payload_h handle, const char* key, app_control_h app_control) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(app_control); + + bundle* appctl_bundle = NULL; + int error = app_control_to_bundle(app_control, &appctl_bundle); + IF_FAIL_RETURN_TAG(error == APP_CONTROL_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "App_control to bundle failed"); + + bundle_raw* appctl_raw; + int raw_length; + error = bundle_encode(appctl_bundle, &appctl_raw, &raw_length); + IF_FAIL_RETURN_TAG(error == BUNDLE_ERROR_NONE, CONV_ERROR_INVALID_PARAMETER, _E, "Bundle encode failed"); + + std::string appctl_str = reinterpret_cast(appctl_raw); + handle->jpayload.set(NULL, key, appctl_str); + + bundle_free(appctl_bundle); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_get_app_control(conv_payload_h handle, const char* key, app_control_h* app_control) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(app_control); + + std::list key_list; + handle->jpayload.get_keys(&key_list); + IF_FAIL_RETURN_TAG(key_list.size() > 0, CONV_ERROR_NO_DATA, _E, "No data"); + + // Check Invalid record key + std::string appctl_str; + IF_FAIL_RETURN_TAG(handle->jpayload.get(NULL, key, &appctl_str), CONV_ERROR_INVALID_PARAMETER, _E, "Value load failed"); + + char* str = static_cast(malloc(appctl_str.length())); + + IF_FAIL_RETURN_TAG(str, CONV_ERROR_INVALID_PARAMETER, _E, "Memory allocation failed"); + + appctl_str.copy(str, appctl_str.length(), 0); + bundle_raw* encoded = reinterpret_cast(str); + bundle* appctl_bundle = bundle_decode(encoded, appctl_str.length()); + + app_control_create(app_control); + app_control_import_from_bundle(*app_control, appctl_bundle); + + bundle_free(appctl_bundle); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_set_byte(conv_payload_h handle, const char* key, int length, unsigned char* value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + std::string str_value(reinterpret_cast(value), length); + + handle->jpayload.set(NULL, key, str_value); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_payload_get_byte(conv_payload_h handle, const char* key, int* length, unsigned char** value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + std::list key_list; + handle->jpayload.get_keys(&key_list); + IF_FAIL_RETURN_TAG(key_list.size() > 0, CONV_ERROR_NO_DATA, _E, "No data"); + + // Check Invalid record key + std::string str; + IF_FAIL_RETURN_TAG(handle->jpayload.get(NULL, key, &str), CONV_ERROR_INVALID_PARAMETER, _E, "Value load failed"); + + *value = reinterpret_cast(g_strdup(str.c_str())); + *length = str.size(); + + ASSERT_ALLOC(*value); + + return CONV_ERROR_NONE; +} diff --git a/lib/conv_lib_service.cpp b/lib/conv_lib_service.cpp new file mode 100644 index 0000000..112e1c5 --- /dev/null +++ b/lib/conv_lib_service.cpp @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "d2d_conv_manager.h" +#include "conv_lib_json.h" +#include "internal_types.h" +#include "dbus_client.h" +#include "conv_lib_util.h" + +static std::map callback_map; +static std::map connect_callback_map; + +std::string convert_type_to_string(conv_service_e service_type); +conv_service_e convert_string_to_type(std::string type_name); + +static void conv_subject_cb(const char* subject, int req_id, int error, json data){ + _D("Callback response %d", req_id); + + json description; + json service; + json channel; + std::string service_type; + json payload; + json key; + int is_local = 0; + + data.get(NULL, CONV_JSON_DESCRIPTION, &description); + + _D("description:%s", description.str().c_str()); + description.get(NULL, CONV_JSON_SERVICE, &service); + description.get(NULL, CONV_JSON_CHANNEL, &channel); + description.get(NULL, CONV_JSON_TYPE, &service_type); + description.get(NULL, CONV_JSON_IS_LOCAL, &is_local); + + data.get(NULL, CONV_JSON_PAYLOAD, &payload); + _D("payload:%s", payload.str().c_str()); + + key.set(NULL, CONV_JSON_SERVICE, service); + key.set(NULL, CONV_JSON_TYPE, service_type); + + std::map::iterator it = callback_map.find(key.str()); + if (it == callback_map.end()) { + _D("No callback found for response."); + return; + } + + _conv_service_callback_info* callback_info = it->second; + + conv_service_h service_handle = new(std::nothrow) _conv_service_handle(); + IF_FAIL_VOID_TAG(service_handle, _E, "Memory allocation failed"); + + service_handle->jservice = service; + service_handle->service_type = convert_string_to_type(service_type); + service_handle->is_local = is_local; + service_handle->connection_state = CONV_SERVICE_CONNECTION_STATE_CONNECTED; + + conv_channel_h channel_handle = new(std::nothrow) _conv_channel_handle(); + IF_FAIL_VOID_TAG(channel_handle, _E, "Memory allocation failed"); + + channel_handle->jchannel = channel; + + conv_payload_h payload_handle = new(std::nothrow) _conv_payload_handle(); + IF_FAIL_VOID_TAG(payload_handle, _E, "Memory allocation failed"); + + payload_handle->jpayload = payload; + + callback_info->cb(service_handle, channel_handle, CONV_ERROR_NONE, payload_handle, callback_info->user_data); + + delete payload_handle; + delete channel_handle; + delete service_handle; +} + +static void conv_connect_subject_cb(const char* subject, int req_id, int error, json data){ + _D("Callback response %d", req_id); + + json description; + json service; + json channel; + json device; + std::string service_type; + json payload; + int is_local = 0; + + data.get(NULL, CONV_JSON_DESCRIPTION, &description); + description.get(NULL, CONV_JSON_SERVICE, &service); + description.get(NULL, CONV_JSON_TYPE, &service_type); + description.get(NULL, CONV_JSON_DEVICE, &device); + description.get(NULL, CONV_JSON_IS_LOCAL, &is_local); + + data.get(NULL, CONV_JSON_PAYLOAD, &payload); + _D("payload:%s", payload.str().c_str()); + + std::map::iterator it = connect_callback_map.find(description.str()); + if (it == connect_callback_map.end()) { + _D("No callback found for response."); + return; + } + + _conv_service_connect_callback_info* callback_info = it->second; + + conv_service_h service_handle = new(std::nothrow) _conv_service_handle(); + IF_FAIL_VOID_TAG(service_handle, _E, "Memory allocation failed"); + + service_handle->jservice = service; + service_handle->service_type = convert_string_to_type(service_type); + service_handle->is_local = is_local; + service_handle->connection_state = CONV_SERVICE_CONNECTION_STATE_CONNECTED; + + conv_payload_h payload_handle = new(std::nothrow) _conv_payload_handle(); + IF_FAIL_VOID_TAG(payload_handle, _E, "Memory allocation failed"); + + payload_handle->jpayload = payload; + + callback_info->cb(service_handle, CONV_ERROR_NONE, payload_handle, callback_info->user_data); + + delete payload_handle; + delete service_handle; +} + +static void register_subject_callbacks() +{ + static bool done = false; + + if (!done) { + conv::dbus_client::register_callback(CONV_SUBJECT_COMMUNICATION_RECV, conv_subject_cb); + conv::dbus_client::register_callback(CONV_SUBJECT_CONNECTION_START, conv_connect_subject_cb); + done = true; + } + _I("Done with registering subject callback"); +} + +EXTAPI int conv_service_create(conv_service_h* handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + *handle = new(std::nothrow) _conv_service_handle(); + ASSERT_ALLOC(*handle); + + (*handle)->is_local = 1; + (*handle)->connection_state = CONV_SERVICE_CONNECTION_STATE_CONNECTED; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_clone(conv_service_h original_handle, conv_service_h* target_handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(target_handle); + ASSERT_NOT_NULL(original_handle); + + *target_handle = new(std::nothrow) _conv_service_handle(); + ASSERT_ALLOC(*target_handle); + + (*target_handle)->jservice = original_handle->jservice; + (*target_handle)->service_type = original_handle->service_type; + (*target_handle)->is_local = original_handle->is_local; + (*target_handle)->jdevice = original_handle->jdevice; + (*target_handle)->connection_state = original_handle->connection_state; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_destroy(conv_service_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + if ( handle->callback ) + { + delete handle->callback; + } + + delete handle; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_set_listener_cb(conv_service_h handle, conv_service_listener_cb callback, void* user_data) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(callback); + + register_subject_callbacks(); + + json description; + + json service = handle->jservice; + + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_TYPE, type); + + _conv_service_callback_info *cb_info = new(std::nothrow)_conv_service_callback_info(); + cb_info->cb = callback; + cb_info->user_data = user_data; + cb_info->handle = handle; + cb_info->description = description; + + callback_map[description.str()] = cb_info; + + _D("key:%s", description.str().c_str()); + + int req_id; + + int err = conv::dbus_client::request(REQ_SUBSCRIBE, &req_id, CONV_SUBJECT_COMMUNICATION_RECV, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Getting list failed"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_unset_listener_cb(conv_service_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + json description; + + json service = handle->jservice; + + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_TYPE, type); + + int req_id; + int err = conv::dbus_client::request(REQ_UNSUBSCRIBE, &req_id, CONV_SUBJECT_COMMUNICATION_RECV, NULL, NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Unset observe failed"); + + std::map::iterator it = callback_map.find(description.str()); + if (it == callback_map.end()) { + _D("No callback found for response."); + return CONV_ERROR_INVALID_OPERATION; + } + + _conv_service_callback_info* callback_info = it->second; + + delete callback_info; + callback_map.erase(it); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_start(conv_service_h handle, conv_channel_h channel_handle, conv_payload_h payload) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + int req_id; + + json description; + json channel; + + if ( channel_handle != NULL ) + { + channel = channel_handle->jchannel; + } + + json service = handle->jservice; + json device = handle->jdevice; + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_CHANNEL, channel); + description.set(NULL, CONV_JSON_DEVICE, device); + description.set(NULL, CONV_JSON_TYPE, type); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_COMMUNICATION_START, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_get(conv_service_h handle, conv_channel_h channel_handle, conv_payload_h payload_handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + int req_id; + + json description; + json channel; + + if ( channel_handle != NULL ) + { + channel = channel_handle->jchannel; + } + + json payload; + + if ( payload_handle != NULL) { + payload = payload_handle->jpayload; + } + + json service = handle->jservice; + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_CHANNEL, channel); + description.set(NULL, CONV_JSON_PAYLOAD, payload); + description.set(NULL, CONV_JSON_TYPE, type); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_COMMUNICATION_GET, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_stop(conv_service_h handle, conv_channel_h channel_handle, conv_payload_h payload) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + int req_id; + + json description; + json channel; + + if ( channel_handle != NULL ) + { + channel = channel_handle->jchannel; + } + + json service = handle->jservice; + json device = handle->jdevice; + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_CHANNEL, channel); + description.set(NULL, CONV_JSON_DEVICE, device); + description.set(NULL, CONV_JSON_TYPE, type); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_COMMUNICATION_STOP, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_publish(conv_service_h handle, conv_channel_h channel_handle, conv_payload_h payload_handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + int req_id; + + json description; + json channel; + + if ( channel_handle != NULL ) + { + channel = channel_handle->jchannel; + } + + json payload = payload_handle->jpayload; + json service = handle->jservice; + json device = handle->jdevice; + std::string type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_CHANNEL, channel); + description.set(NULL, CONV_JSON_DEVICE, device); + description.set(NULL, CONV_JSON_PAYLOAD, payload); + description.set(NULL, CONV_JSON_TYPE, type); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_COMMUNICATION_SET, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +static int conv_service_set_connected_cb(conv_service_h handle, json description, conv_service_connected_cb callback, void* user_data) +{ + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(callback); + + register_subject_callbacks(); + + _conv_service_connect_callback_info *cb_info = new(std::nothrow)_conv_service_connect_callback_info(); + cb_info->cb = callback; + cb_info->user_data = user_data; + cb_info->handle = handle; + cb_info->description = description; + + connect_callback_map[description.str()] = cb_info; + + _D("key:%s", description.str().c_str()); + + int req_id; + + int err = conv::dbus_client::request(REQ_SUBSCRIBE, &req_id, CONV_SUBJECT_CONNECTION_START, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Getting list failed"); + + return CONV_ERROR_NONE; +} + +static int conv_service_unset_connected_cb(conv_service_h handle) +{ + ASSERT_NOT_NULL(handle); + + json description; + json service = handle->jservice; + + std::string service_type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_TYPE, service_type); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int req_id; + int err = conv::dbus_client::request(REQ_UNSUBSCRIBE, &req_id, CONV_SUBJECT_CONNECTION_START, NULL, NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Unset observe failed"); + + std::map::iterator it = connect_callback_map.find(description.str()); + if (it == connect_callback_map.end()) { + _D("No callback found for response."); + return CONV_ERROR_INVALID_OPERATION; + } + + _conv_service_connect_callback_info* callback_info = it->second; + + delete callback_info; + connect_callback_map.erase(it); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_get_connection_state(conv_service_h handle, conv_service_connection_state_e* state) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(state); + + *state = handle->connection_state; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_connect(conv_service_h handle, conv_service_connected_cb callback, void* user_data) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(callback); + + int req_id; + + json description; + json service = handle->jservice; + json device = handle->jdevice; + + std::string service_type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_TYPE, service_type); + description.set(NULL, CONV_JSON_DEVICE, device); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + //temp + conv_service_set_connected_cb(handle, description, callback, user_data); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_CONNECTION_START, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_disconnect(conv_service_h handle) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + //temp + conv_service_unset_connected_cb(handle); + + int req_id; + + json description; + json service = handle->jservice; + json device = handle->jdevice; + std::string service_type = convert_type_to_string(handle->service_type); + + description.set(NULL, CONV_JSON_SERVICE, service); + description.set(NULL, CONV_JSON_TYPE, service_type); + description.set(NULL, CONV_JSON_DEVICE, device); + description.set(NULL, CONV_JSON_IS_LOCAL, handle->is_local); + + int err = conv::dbus_client::request(REQ_WRITE, &req_id, CONV_SUBJECT_CONNECTION_STOP, description.str().c_str(), NULL, NULL); + IF_FAIL_RETURN_TAG(err == CONV_ERROR_NONE, err, _E, "Failed in starting flow service"); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_get_type(conv_service_h handle, conv_service_e* value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(value); + + *value = handle->service_type; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_get_property_string(conv_service_h handle, const char* key, char** value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key && value); + + std::string strval; + bool ret = handle->jservice.get(NULL, key, &strval); // path is NULL.. + if (ret == false || strval.empty()) return CONV_ERROR_NO_DATA; + *value = strdup(strval.c_str()); + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_set_type(conv_service_h handle, conv_service_e value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + + handle->service_type = value; + + return CONV_ERROR_NONE; +} + +EXTAPI int conv_service_set_property_string(conv_service_h handle, const char* key, const char* value) +{ + IF_FAIL_RETURN_TAG(conv::util::is_feature_supported(), CONV_ERROR_NOT_SUPPORTED, _E, "Not supported"); + ASSERT_NOT_NULL(handle); + ASSERT_NOT_NULL(key); + ASSERT_NOT_NULL(value); + + handle->jservice.set(NULL, key, value); + + return CONV_ERROR_NONE; +} + +std::string convert_type_to_string(conv_service_e service_type) +{ + std::string str; + switch (service_type) { + case CONV_SERVICE_APP_TO_APP_COMMUNICATION: + str = CONV_SERVICE_TYPE_SMARTVIEW_APP_COMMUNICATION; + break; + case CONV_SERVICE_REMOTE_APP_CONTROL: + str = CONV_SERVICE_TYPE_REMOTE_APP_CONTROL; + break; + default: + break; + } + return str; +} + +conv_service_e convert_string_to_type(std::string type_name) +{ + conv_service_e service_type = CONV_SERVICE_NONE; + + if ( !type_name.compare(CONV_SERVICE_TYPE_SMARTVIEW_APP_COMMUNICATION)) + { + service_type = CONV_SERVICE_APP_TO_APP_COMMUNICATION; + } else if ( !type_name.compare(CONV_SERVICE_TYPE_REMOTE_APP_CONTROL)) { + service_type = CONV_SERVICE_REMOTE_APP_CONTROL; + } + return service_type; +} diff --git a/lib/conv_lib_util.cpp b/lib/conv_lib_util.cpp new file mode 100644 index 0000000..4cf47db --- /dev/null +++ b/lib/conv_lib_util.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "conv_lib_util.h" +#include + +#define D2D_FEATURE "http://tizen.org/feature/convergence.d2d" + +bool conv::util::is_feature_supported() +{ +#if 0 + if (_feature_supported < 0) { + bool feature_supported = false; + system_info_get_platform_bool(D2D_FEATURE, &feature_supported); + _feature_supported = feature_supported ? 1 : 0; + } + return _feature_supported; +#else + return true; +#endif +} diff --git a/lib/conv_lib_util.h b/lib/conv_lib_util.h new file mode 100644 index 0000000..04e8147 --- /dev/null +++ b/lib/conv_lib_util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __D2D_SERVICE_LIB_UTIL_H__ +#define __D2D_SERVICE_LIB_UTIL_H__ +#include + +using namespace std; + +namespace conv { + namespace util { + bool is_feature_supported(); + } +} +#endif + diff --git a/lib/d2d-conv-manager.pc.in b/lib/d2d-conv-manager.pc.in new file mode 100644 index 0000000..73305fb --- /dev/null +++ b/lib/d2d-conv-manager.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=${prefix}/bin +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@/@CLIENT@ + +Name: @CLIENT@ +Description: D2D Convergence Manager Library +Version: @FULLVER@ +Requires: glib-2.0 +Libs: -L${libdir} -l@CLIENT@ +Cflags: -I${includedir} diff --git a/lib/dbus_client.cpp b/lib/dbus_client.cpp new file mode 100644 index 0000000..0e77a7b --- /dev/null +++ b/lib/dbus_client.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "internal_types.h" +#include "dbus_client.h" + +static GDBusConnection *dbus_connection = NULL; +static GDBusNodeInfo *dbus_node_info = NULL; + +typedef std::map response_cb_map_t; +static response_cb_map_t *response_cb_map = NULL; + +static const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static int get_req_id() +{ + static int req_id = 0; + + if (++req_id < 0) { + req_id = 1; + } + + return req_id; +} + +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); + + // conv::response_handler::deliver(subject, req_id, error, 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); + + 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) +{ + _D("handle_method_call"); + 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); + + _D("handle_method_call...sender[%s] obj_path[%s] iface[%s] method_name[%s]", + sender, obj_path, iface, method_name); + + if (STR_EQ(method_name, METHOD_RESPOND)) { + handle_response(sender, param, invocation); + } else { + _W("Invalid method: %s", method_name); + } +} + +bool conv::dbus_client::init() +{ +// static GMutex connection_mutex; +// conv::scope_mutex sm(&connection_mutex); + + _D("dbus_client init with dbus_connection %d response_cb_map:%x", dbus_connection, response_cb_map); + if (dbus_connection) { + return true; + } + + //response_cb_map = g_new0 (response_cb_map_t,1); + response_cb_map = new (std::nothrow) response_cb_map_t; + _D("dbus_client init with response_cb_map:%x", response_cb_map); + + 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_SESSION, 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 conv::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 conv::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, %s", type, subject); + IF_FAIL_RETURN_TAG(init(), CONV_ERROR_INVALID_OPERATION, _E, "Connection failed"); + IF_FAIL_RETURN_TAG(req_id != NULL, CONV_ERROR_INVALID_PARAMETER, _E, "Invalid parameter"); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + *req_id = get_req_id(); + + // second param is security cookie which is deprecated in 3.0 + GVariant *param = g_variant_new("(isiss)", type, "", *req_id, subject, input); + IF_FAIL_RETURN_TAG(param, CONV_ERROR_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, CONV_ERROR_INVALID_OPERATION, _E, "Method call failed"); + + gint _error = CONV_ERROR_INVALID_OPERATION; + 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 conv::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_FAIL_RETURN_TAG(init(), CONV_ERROR_INVALID_OPERATION, _E, "Connection failed"); + IF_FAIL_RETURN_TAG(req_id != NULL, CONV_ERROR_INVALID_PARAMETER, _E, "Invalid parameter"); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + *req_id = get_req_id(); + + // second param is security cookie which is deprecated in 3.0 + GVariant *param = g_variant_new("(isiss)", type, "", req_id, subject, input); + IF_FAIL_RETURN_TAG(param, CONV_ERROR_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 CONV_ERROR_INVALID_OPERATION; + } + + return CONV_ERROR_NONE; +} + +int conv::dbus_client::register_callback(const char* subject, subject_response_cb callback) +{ + IF_FAIL_RETURN_TAG(subject && callback, CONV_ERROR_INVALID_PARAMETER, _E, "Invalid parameter"); + IF_FAIL_RETURN_TAG(init(), CONV_ERROR_INVALID_OPERATION, _E, "Connection failed"); + + _I("Registering callback for subject '%s'", subject); + _I("response_cb_map : %x", response_cb_map); + + response_cb_map->insert(std::pair (subject, callback)); + + _D("registering done.."); + + return true; +} diff --git a/lib/dbus_client.h b/lib/dbus_client.h new file mode 100644 index 0000000..4c67516 --- /dev/null +++ b/lib/dbus_client.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 __CONV_DBUS_CLIENT_H__ +#define __CONV_DBUS_CLIENT_H__ + +#include + +typedef void(* subject_response_cb)(const char* subject, int req_id, int error, json response); + +namespace conv { + + namespace 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); + int register_callback(const char* subject, subject_response_cb callback); + } + +} /* namespace ctx */ + +#endif // __CONV_DBUS_CLIENT_H__ diff --git a/lib/include/d2d_conv_channel.h b/lib/include/d2d_conv_channel.h new file mode 100644 index 0000000..d967250 --- /dev/null +++ b/lib/include/d2d_conv_channel.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_CHANNEL_H__ +#define __TIZEN_D2D_CONV_CHANNEL_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file d2d_conv_channel.h + */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_CHANNEL_MODULE + * @{ + */ + +/** + * @brief Convergence channel handle to define channel information. + * @since_tizen 3.0 + */ +typedef struct _conv_channel_handle_s* conv_channel_h; + +/** + * @brief Creates D2D convergence manager channel handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_channel_destroy(). + * + * @param[out] handle Handle to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_channel_destroy() + */ +int conv_channel_create(conv_channel_h* handle); + +/** + * @brief Releases the resources occupied by a handle. + * @details This releases the memory allocated for the @a handle. + * + * @since_tizen 3.0 + * + * @param[in] handle Handle to be released + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_channel_create() + */ +int conv_channel_destroy(conv_channel_h handle); + +/** + * @brief Gets a string from channel. + * @since_tizen 3.0 + * @remarks The @a value must be released using free(). + * + * @param[in] handle The channel handle + * @param[in] key The key of attribute to get + * @param[out] value The result value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @see conv_channel_set_string() + */ +int conv_channel_get_string(conv_channel_h handle, const char* key, char** value); + +/** + * @brief Sets a string to channel. + * @since_tizen 3.0 + * + * @param[in] handle The channel handle + * @param[in] key The key of attribute to set + * @param[in] value The string value to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_channel_get_string() + */ +int conv_channel_set_string(conv_channel_h handle, const char* key, const char* value); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_CHANNEL_H__ */ diff --git a/lib/include/d2d_conv_device.h b/lib/include/d2d_conv_device.h new file mode 100644 index 0000000..a3e5a79 --- /dev/null +++ b/lib/include/d2d_conv_device.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_DEVICE_H__ +#define __TIZEN_D2D_CONV_DEVICE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file d2d_conv_device.h + */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_DEVICE_MODULE + * @{ + */ + +/** + * @brief The attribute key "device id" + * @since_tizen 3.0 + */ +#define CONV_DEVICE_ID "device_id" + +/** + * @brief The attribute key "device name" + * @since_tizen 3.0 + */ +#define CONV_DEVICE_NAME "device_name" + +/** + * @brief The attribute key "device type" + * @since_tizen 3.0 + */ +#define CONV_DEVICE_TYPE "device_type" + +/** + * @brief Convergence device handle for accessing device information and device-to-device services. + * @since_tizen 3.0 + */ +typedef struct _conv_device_handle_s* conv_device_h; + +/** + * @brief Called for each service available on the device. + * @details Specifies the type of function passed to conv_device_foreach_service() \n + * The @a service_handle value is only valid in the callback function.\n + * If you want to use it outside of the callback, you need to use a clone which can be obtained with conv_service_clone() + * + * + * @since_tizen 3.0 + * + * @param[in] service_handle The service handle to access discovered service information + * @param[in] user_data The user data passed to the foreach function + * + * @pre conv_device_foreach_service() calls this callback + * @see conv_device_foreach_service() + */ +typedef void(* conv_service_foreach_cb)(conv_service_h service_handle, void* user_data); + +/** + * @brief Clones D2D convergence manager device handle from discovered device handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_device_destroy(). + * + * @param[in] original_handle Source handle + * @param[out] target_handle Clone handle + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_device_destroy() + */ +int conv_device_clone(conv_device_h original_handle, conv_device_h* target_handle); + +/** + * @brief Releases the resources occupied by the device handle. + * @details This releases the memory allocated for the @a handle. + * + * @since_tizen 3.0 + * @remarks This must only called for cloned device handle by conv_device_clone(). + * + * @param[in] handle Handle to be released + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_device_clone() + */ +int conv_device_destroy(conv_device_h handle); + +/** + * @brief Gets a string from device property. + * @since_tizen 3.0 + * @remarks The @a value must be released using free(). + * + * @param[in] handle The device handle + * @param[in] key The key of property to get + * @param[out] value The result value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @see conv_discovery_start() + */ +int conv_device_get_property_string(conv_device_h handle, const char* key, char** value); + +/** + * @brief Gets all service handles available on the device by invoking the callback function. + * @details conv_service_foreach_cb() will be called for each service. + * + * @since_tizen 3.0 + * + * @param[in] handle The device handle contains service list + * @param[in] cb The callback function to get each service handle + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value. + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * + * @post conv_service_foreach_cb() will be called for each item. + * + * @see conv_service_foreach_cb() + */ +int conv_device_foreach_service(conv_device_h handle, conv_service_foreach_cb cb, void* user_data); + +#ifdef __cplusplus +} +#endif/* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_DEVICE_H__ */ + diff --git a/lib/include/d2d_conv_error.h b/lib/include/d2d_conv_error.h new file mode 100644 index 0000000..bd23471 --- /dev/null +++ b/lib/include/d2d_conv_error.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_ERROR_H__ +#define __TIZEN_D2D_CONV_ERROR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file d2d_conv_error.h + */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @{ + */ + +/** + * @brief Enumeration for errors. + * @since_tizen 3.0 + */ +typedef enum { + CONV_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + CONV_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + CONV_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */ + CONV_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Memory allocation failed */ + CONV_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + CONV_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + CONV_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA /**< No Data */ +} conv_error_e; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_ERROR_H__ */ diff --git a/lib/include/d2d_conv_manager.h b/lib/include/d2d_conv_manager.h new file mode 100644 index 0000000..be3a98d --- /dev/null +++ b/lib/include/d2d_conv_manager.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_MANAGER_H__ +#define __TIZEN_D2D_CONV_MANAGER_H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_FRAMEWORK + * @{ + */ + +/** + * @brief Enumeration for discovery results. + * @since_tizen 3.0 + */ +typedef enum { + CONV_DISCOVERY_RESULT_ERROR = -1, /**< Discovery Error */ + CONV_DISCOVERY_RESULT_SUCCESS = 0, /**< Discovery Success */ + CONV_DISCOVERY_RESULT_FINISHED /**< Discovery finished */ +} conv_discovery_result_e; + +/** + * @brief Convergence manager handle for discovering D2D services. + * @since_tizen 3.0 + */ +typedef struct _conv_handle_s* conv_h; + +/** + * @brief Called when a nearby device which provides D2D services has been discovered. + * @details Specifies the type of function passed to conv_discovery_start() \n + * The @a device_handle value is only valid in the callback function and in case result is @c CONV_DISCOVERY_RESULT_SUCCESS.\n + * If you want to use it outside of the callback, you need to use a clone which can be obtained with conv_service_clone()\n + * The following results can be delivered. \n + * #CONV_DISCOVERY_RESULT_ERROR, \n + * #CONV_DISCOVERY_RESULT_SUCCESS, \n + * #CONV_DISCOVERY_RESULT_FINISHED + * + * @since_tizen 3.0 + * + * @param[in] device The device discovered + * @param[in] result The result value for discovery + * @param[in] user_data The user data to pass to the function + * + * @see conv_discovery_start() + * @see conv_discovery_stop() + */ +typedef void(* conv_discovery_cb)(conv_device_h device_handle, conv_discovery_result_e result, void* user_data); + +/** + * @brief Creates a D2D convergence manager handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_destroy(). + * + * @param[out] handle Handle to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @post conv_destroy() + */ +int conv_create(conv_h* handle); + +/** + * @brief Releases the resources occupied by a handle. + * @details This releases the memory allocated for the @a handle. + * + * @since_tizen 3.0 + * + * @param[in] handle Handle to be released + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_create() + */ +int conv_destroy(conv_h handle); + +/** + * @brief Starts discovery near-by devices. + * @details Discovers device-to-device services supported devices. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * + * @remarks The @a callback is called when each near-by device has been found. + * + * @param[in] handle Handle for controlling discovery requests + * @param[in] timeout_seconds Seconds for discovery timeout. 0 will use default timeout value + * @param[in] callback Callback function to receive discovered device information. This can not be @c NULL + * @param[in] user_data The user data to pass to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @pre conv_create() + * @post conv_discovery_stop() + */ +int conv_discovery_start(conv_h handle, const int timeout_seconds, conv_discovery_cb callback, void* user_data); + +/** + * @brief Stops discovery near-by devices. + * @details Stops discovery for device-to-device services supported devices. + * @since_tizen 3.0 + * + * @param[in] handle Handle for controlling discovery requests + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_discovery_start() + */ +int conv_discovery_stop(conv_h handle); + +#ifdef __cplusplus +} +#endif/* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_MANAGER_H__ */ diff --git a/lib/include/d2d_conv_payload.h b/lib/include/d2d_conv_payload.h new file mode 100644 index 0000000..1376c56 --- /dev/null +++ b/lib/include/d2d_conv_payload.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_PAYLOAD_H__ +#define __TIZEN_D2D_CONV_PAYLOAD_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file d2d_conv_payload.h + */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_PAYLOAD_MODULE + * @{ + */ + +/** + * @brief Convergence payload handle to manage payload data. + * @since_tizen 3.0 + */ +typedef struct _conv_payload_handle_s* conv_payload_h; + +/** + * @brief Creates D2D convergence manager payload handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_payload_destroy(). + * + * @param[out] handle Handle to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_payload_destroy() + */ +int conv_payload_create(conv_payload_h* handle); + +/** + * @brief Releases the resources occupied by a handle. + * @details This releases the memory allocated for the @a handle. + * + * @since_tizen 3.0 + * + * @param[in] handle Handle to be released + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_payload_create() + */ +int conv_payload_destroy(conv_payload_h handle); + +/** + * @brief Sets a string to payload. + * @since_tizen 3.0 + * + * @param[in] handle The payload handle + * @param[in] key The key of attribute to set + * @param[in] value The string value to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_payload_get_string() + */ +int conv_payload_set_string(conv_payload_h handle, const char* key, const char* value); + +/** + * @brief Gets a string from payload. + * @since_tizen 3.0 + * @remarks The @a value must be released using free(). + * + * @param[in] handle The payload handle + * @param[in] key The key of attribute to get + * @param[out] value The result value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @see conv_payload_set_string() + */ +int conv_payload_get_string(conv_payload_h handle, const char* key, char** value); + +/** + * @brief Sets an app-control to payload. + * @since_tizen 3.0 + * + * @param[in] handle The payload handle + * @param[in] key The key of property to set + * @param[in] app_control The app-control handle to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_payload_get_app_control() + */ +int conv_payload_set_app_control(conv_payload_h handle, const char* key, app_control_h app_control); + +/** + * @brief Gets an app-control handle from payload. + * @since_tizen 3.0 + * @remarks The @a app_control must be released using app_control_destroy(). + * + * @param[in] handle The payload handle + * @param[in] key The key of attribute to get + * @param[out] app_control The app-control handle + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @see conv_payload_set_app_control() + */ +int conv_payload_get_app_control(conv_payload_h handle, const char* key, app_control_h* app_control); + +/** + * @brief Sets byte array to payload. + * @since_tizen 3.0 + * + * @param[in] handle The payload handle + * @param[in] key The key of property to set + * @param[in] length The length of byte array to set + * @param[in] value The byte array to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_payload_get_byte() + */ +int conv_payload_set_byte(conv_payload_h handle, const char* key, int length, unsigned char* value); + +/** + * @brief Gets byte array from payload. + * @since_tizen 3.0 + * @remarks The @a value must be released using free(). + * + * @param[in] handle The payload handle + * @param[in] key The key of attribute to get + * @param[out] length The length of byte array + * @param[out] value The result value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * + * @see conv_payload_set_byte() + */ +int conv_payload_get_byte(conv_payload_h handle, const char* key, int* length, unsigned char** value); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_PAYLOAD_H__ */ diff --git a/lib/include/d2d_conv_service.h b/lib/include/d2d_conv_service.h new file mode 100644 index 0000000..40997bd --- /dev/null +++ b/lib/include/d2d_conv_service.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_D2D_CONV_SERVICE_H__ +#define __TIZEN_D2D_CONV_SERVICE_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @file d2d_conv_service.h + */ + +/** + * @addtogroup CAPI_D2D_CONVERGENCE_MANAGER_SERVICE_MODULE + * @{ + */ + +/** + * @brief The attribute key "service id" + * @since_tizen 3.0 + */ +#define CONV_SERVICE_ID "service_id" + +/** + * @brief The attribute key "service version" + * @since_tizen 3.0 + */ +#define CONV_SERVICE_VERSION "service_version" + +/** + * @brief Enumeration for service types. + * @since_tizen 3.0 + */ +typedef enum { + CONV_SERVICE_NONE = -1, /**< Undefined service */ + CONV_SERVICE_APP_TO_APP_COMMUNICATION = 0, /**< App-to-app communication service */ + CONV_SERVICE_REMOTE_APP_CONTROL /**< Remote app-control service */ +} conv_service_e; + +/** + * @brief Enumeration for connection states. + * @since_tizen 3.0 + */ +typedef enum { + CONV_SERVICE_CONNECTION_STATE_NONE = -1, /**< Undefined state */ + CONV_SERVICE_CONNECTION_STATE_CONNECTED = 0, /**< Connected state */ + CONV_SERVICE_CONNECTION_STATE_NOT_CONNECTED, /**< Not connected state */ + CONV_SERVICE_CONNECTION_STATE_CONNECTING /**< Connecting state */ +} conv_service_connection_state_e; + +/** + * @brief Convergence service handle for connecting and communicating D2D services. + * @since_tizen 3.0 + */ +typedef struct _conv_service_handle_s* conv_service_h; + +/** + * @brief Called when the connection state with the remote service is changed. + * @details Specifies the type of function passed to conv_service_connect() \n + * The following error codes can be delivered. \n + * #CONV_ERROR_NONE, \n + * #CONV_ERROR_INVALID_OPERATION, \n + * #CONV_ERROR_INVALID_PARAMETER + * + * @since_tizen 3.0 + * + * @param[in] service_handle The service handle tried to connect to + * @param[in] error The error value + * @param[in] result The payload handle contains result data + * @param[in] user_data The user data to pass to the foreach function + * + * @see conv_service_connect() + */ +typedef void(* conv_service_connected_cb)(conv_service_h service_handle, conv_error_e error, conv_payload_h result, void* user_data); + +/** + * @brief Called when the service is started or stopped, and when data is received or published. + * @details Specifies the type of function passed to conv_service_set_listener_cb() \n + * The following error codes can be delivered. \n + * #CONV_ERROR_NONE, \n + * #CONV_ERROR_INVALID_OPERATION, \n + * #CONV_ERROR_INVALID_PARAMETER + * + * @since_tizen 3.0 + * + * @param[in] service_handle The service handle called from + * @param[in] channel_handle The channel handle contains channel identifiers + * @param[in] error The error value + * @param[in] result The payload handle contains result data + * @param[in] user_data The user data to pass to the foreach function + * + * @pre conv_service_set_listener_cb() + * @post conv_service_unset_listener_cb() + * @see conv_service_start() + * @see conv_service_read() + * @see conv_service_publish() + * @see conv_service_stop() + */ +typedef void(* conv_service_listener_cb)(conv_service_h service_handle, conv_channel_h channel_handle, conv_error_e error, conv_payload_h result, void* user_data); + +/** + * @brief Creates D2D convergence manager service handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_service_destroy(). + * + * @param[out] handle Handle to be initialized + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_service_destroy() + */ +int conv_service_create(conv_service_h* handle); + +/** + * @brief Clones D2D convergence manager service handle from discovered service handle. + * @since_tizen 3.0 + * @remarks The @a handle must be released using conv_service_destroy(). + * + * @param[in] original_handle Source handle + * @param[out] target_handle Clone handle + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_service_destroy() + */ +int conv_service_clone(conv_service_h original_handle, conv_service_h* target_handle); + +/** + * @brief Releases the resources occupied by a handle. + * @details This releases the memory allocated for the @a handle. + * + * @since_tizen 3.0 + * + * @param[in] handle Handle to be released + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_service_create() + * @pre conv_service_clone() + */ +int conv_service_destroy(conv_service_h handle); + +/** + * @brief Gets a string from service property. + * @since_tizen 3.0 + * @remarks The @a value must be released using free(). + * + * @param[in] handle The service handle + * @param[in] key The key of property to get + * @param[out] value The result value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_NO_DATA No Data + * @retval #CONV_ERROR_OUT_OF_MEMORY Out of memory + * + * @see conv_service_set_property_string() + */ +int conv_service_get_property_string(conv_service_h handle, const char* key, char** value); + +/** + * @brief Sets a string to service property. + * @since_tizen 3.0 + * + * @param[in] handle The service handle + * @param[in] key The key of property to set + * @param[in] value The string value to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_service_get_property_string() + */ +int conv_service_set_property_string(conv_service_h handle, const char* key, const char* value); + +/** + * @brief Gets connection state from service. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/network.get + * + * @param[in] handle The service handle + * @param[out] state The connection state value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + */ +int conv_service_get_connection_state(conv_service_h handle, conv_service_connection_state_e* state); + +/** + * @brief Gets service type from service handle. + * @since_tizen 3.0 + * + * @param[in] handle The service handle + * @param[out] value The service type value + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_service_set_type() + */ +int conv_service_get_type(conv_service_h handle, conv_service_e* value); + +/** + * @brief Sets service type to service handle. + * @since_tizen 3.0 + * + * @param[in] handle The service handle + * @param[in] value The service type value to set + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @see conv_service_get_type() + */ +int conv_service_set_type(conv_service_h handle, conv_service_e value); + +/** + * @brief Connects to remote service asynchronously. + * @details Makes physical connections such as WiFi-Direct or Bluetooth to remote service. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * + * @remarks The @a callback is called when the connection state is changed. + * + * @param[in] handle Service handle to connect + * @param[in] callback Callback function to receive connection result. This can not be @c NULL + * @param[in] user_data The user data to pass to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @post conv_service_disconnect() + * @post conv_service_connected_cb() will be invoked. + */ +int conv_service_connect(conv_service_h handle, conv_service_connected_cb callback, void* user_data); + +/** + * @brief Disconnects connected service asynchronously. + * @details Disconnects physical connection with remote service. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * + * @param[in] handle Service handle to disconnect + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @pre conv_service_connect() + * @post conv_service_connected_cb() will be invoked. + */ +int conv_service_disconnect(conv_service_h handle); + +/** + * @brief Starts and initiates remote service asynchronously. + * @details Invokes initialize and send start message to remote service to initialize. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * @privilege %http://tizen.org/privilege/d2d.datasharing + * + * @param[in] handle Service handle to manage + * @param[in] channel Channel handle to specify logical session in one service + * @param[in] payload Payload handle to contain additional data for start request + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @post conv_service_stop() + * @post conv_service_listener_cb() will be invoked. + */ +int conv_service_start(conv_service_h handle, conv_channel_h channel, conv_payload_h payload); + +/** + * @brief Reads from remote service asynchronously. + * @details Retrieves data from remote service or regarding to remote service. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * + * @param[in] handle Service handle to manage + * @param[in] channel Channel handle to specify logical session in one service + * @param[in] payload Payload handle to contain additional data for read request + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @pre conv_service_start() + * @post conv_service_listener_cb() will be invoked. + * @see conv_service_publish() + */ +int conv_service_read(conv_service_h handle, conv_channel_h channel, conv_payload_h payload); + +/** + * @brief Publishes message to remote service asynchronously. + * @details Publishes payload to remote service to send data or emit custom events. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * @privilege %http://tizen.org/privilege/d2d.datasharing + * + * @param[in] handle Service handle to manage + * @param[in] channel Channel handle to specify logical session in one service + * @param[in] payload Payload handle to contain additional data for publish + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @pre conv_service_start() + * @post conv_service_listener_cb() will be invoked. + * @see conv_service_read() + */ +int conv_service_publish(conv_service_h handle, conv_channel_h channel, conv_payload_h payload); + +/** + * @brief Stops remote service asynchronously. + * @details Stops and release internally allocated resources for remote service. + * @since_tizen 3.0 + * + * @privlevel public + * @privilege %http://tizen.org/privilege/internet + * @privilege %http://tizen.org/privilege/bluetooth + * + * @param[in] handle Service handle to manage + * @param[in] channel Channel handle to specify logical session in one service + * @param[in] payload Payload handle to contain additional data for stop request + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * @retval #CONV_ERROR_PERMISSION_DENIED Permission denied + * + * @pre conv_service_start() + * @post conv_service_listener_cb() will be invoked. + */ +int conv_service_stop(conv_service_h handle, conv_channel_h channel, conv_payload_h payload); + +/** + * @brief Registers listener to receive message from remote service. + * @details Listens any messages from remote service. + * @since_tizen 3.0 + * + * @remarks The @a callback is called any event occurred or any message is received from remote server. + * + * @param[in] handle Service handle to listen + * @param[in] callback Callback function to receive connection result. This can not be @c NULL + * @param[in] user_data The user data to pass to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @post conv_service_unset_listener_cb() + */ +int conv_service_set_listener_cb(conv_service_h handle, conv_service_listener_cb callback, void* user_data); + +/** + * @brief Unregisters listener for remote service. + * @since_tizen 3.0 + * + * @param[in] handle Service handle to unregister + * + * @return 0 on success, otherwise a negative error value + * @retval #CONV_ERROR_NONE Successful + * @retval #CONV_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CONV_ERROR_INVALID_OPERATION Operation failed + * @retval #CONV_ERROR_NOT_SUPPORTED Not supported + * + * @pre conv_service_set_listener_cb() + */ +int conv_service_unset_listener_cb(conv_service_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** +* @} +*/ + +#endif /* __TIZEN_D2D_CONV_SERVICE_H__ */ diff --git a/lib/internal_types.h b/lib/internal_types.h new file mode 100644 index 0000000..53530c5 --- /dev/null +++ b/lib/internal_types.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONV_INTERNAL_TYPES_H__ +#define __CONV_INTERNAL_TYPES_H__ + +#include +#include +#include "conv_lib_json.h" + +typedef struct _conv_handle_s { + std::list request_ids; +} _conv_handle; + +typedef struct service_callback_info_s { + conv_service_listener_cb cb; + void* user_data; + conv_service_h handle; + json description; +} _conv_service_callback_info; + +typedef struct service_connect_callback_info_s { + conv_service_connected_cb cb; + void* user_data; + conv_service_h handle; + json description; +} _conv_service_connect_callback_info; + +typedef struct _conv_channel_handle_s { + json jchannel; +} _conv_channel_handle; + +typedef struct _conv_payload_handle_s { + json jpayload; +} _conv_payload_handle; + +typedef struct _conv_service_handle_s { + json jservice; + conv_service_e service_type; + bool is_local; + conv_service_connection_state_e connection_state; + json jdevice; + _conv_service_callback_info* callback; +} _conv_service_handle; + +typedef struct _conv_device_handle_s { + json jbody; +} _conv_device_handle; + +#endif diff --git a/packaging/d2d-conv-manager-old.manifest b/packaging/d2d-conv-manager-old.manifest new file mode 100644 index 0000000..f38aaa6 --- /dev/null +++ b/packaging/d2d-conv-manager-old.manifest @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/d2d-conv-manager-old.service b/packaging/d2d-conv-manager-old.service new file mode 100644 index 0000000..57e12da --- /dev/null +++ b/packaging/d2d-conv-manager-old.service @@ -0,0 +1,17 @@ +[Unit] +Description=D2D Convergence Manager Daemon +#Wants=net-config.service,bt-service +#After=net-config.service,bt-service + +[Service] +Type=dbus +User=system +Group=system +SmackProcessLabel=d2d-conv-manager +BusName=org.tizen.d2d-conv-manager +ExecStart=/usr/bin/d2d-conv-managerd +Restart=always +RestartSec=1 + +[Install] +WantedBy=graphical.target \ No newline at end of file diff --git a/packaging/d2d-conv-manager.conf b/packaging/d2d-conv-manager.conf new file mode 100644 index 0000000..aed1008 --- /dev/null +++ b/packaging/d2d-conv-manager.conf @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/d2d-conv-manager.manifest b/packaging/d2d-conv-manager.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/d2d-conv-manager.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/d2d-conv-manager.service b/packaging/d2d-conv-manager.service new file mode 100644 index 0000000..b842679 --- /dev/null +++ b/packaging/d2d-conv-manager.service @@ -0,0 +1,14 @@ +[Unit] +Description=D2D Convergence Manager Daemon +#Wants=net-config.service,bt-service +#After=net-config.service,bt-service + +[Service] +Type=dbus +BusName=org.tizen.d2dconv +ExecStart=/usr/bin/d2d-conv-managerd +Restart=always +RestartSec=1 + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/packaging/d2d-conv-manager.spec b/packaging/d2d-conv-manager.spec new file mode 100644 index 0000000..b3065df --- /dev/null +++ b/packaging/d2d-conv-manager.spec @@ -0,0 +1,140 @@ +Name: d2d-conv-manager +Summary: D2D Convergence Manager +Version: 0.0.1 +Release: 0 +Group: Network & Connectivity/Service +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1: %{name}.service +Source2: %{name}.conf +Source1001: %{name}.manifest +Source1002: lib%{name}.manifest + +%define BUILD_PROFILE %{?profile}%{!?profile:%{?tizen_profile_name}} + +BuildRequires: cmake +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) + +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(iotcon) +#BuildRequires: pkgconfig(security-server) +BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(msf-api) +BuildRequires: pkgconfig(libwebsockets) +BuildRequires: pkgconfig(iotcon) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(capi-network-bluetooth) +BuildRequires: pkgconfig(capi-network-wifi-direct) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-network-connection) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(cynara-creds-gdbus) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(capi-appfw-package-manager) +BuildRequires: capi-network-nsd +BuildRequires: capi-network-nsd-devel + +%if "%{?BUILD_PROFILE}" == "mobile" + +%endif + +BuildRequires: boost-devel +BuildRequires: boost-thread +BuildRequires: boost-system +BuildRequires: boost-filesystem + +%description +D2D Convergence Manager Service + +%prep +%setup -q +cp %{SOURCE1001} . +cp %{SOURCE1002} . + +%package lib +Summary: Client library +Group: Network & Connectivity/Service + + +%description lib +D2D Convergence Manager client library for applications. + + +%package devel +Summary: Client library (devel) +Group: Network & Connectivity/Development +Requires: d2d-conv-manager-lib = %{version} + + +%description devel +D2D Convergence Manager development kit. + + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%cmake . -DMAJORVER=${MAJORVER} -DFULLVER=%{version} -DBIN_INSTALL_DIR:PATH=%{_bindir} -DPROFILE=%{?BUILD_PROFILE} + + +%install +rm -rf %{buildroot}/BUILD/d2d-conv-manager* +%make_install + +mkdir -p %{buildroot}%{_unitdir_user} +mkdir -p %{buildroot}%{_datadir}/license +#mkdir -p %{buildroot}%{_libdir}/systemd/system/graphical.target.wants +cp LICENSE %{buildroot}%{_datadir}/license/%{name} +install -m 0644 %{SOURCE1} %{buildroot}%{_unitdir_user} +#ln -s ../%{name}.service %{buildroot}%{_libdir}/systemd/system/graphical.target.wants/%{name}.service + +mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/session.d +install -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/dbus-1/session.d/ + +%post +mkdir -p %{_unitdir_user}/default.target.wants +ln -s ../%{name}.service %{_unitdir_user}/default.target.wants/ +/sbin/ldconfig + +#systemctl daemon-reload +#if [ $1 == 1 ]; then +# systemctl restart %{name}.service +#fi + +%postun +rm -f %{_unitdir_user}/default.target.wants/%{name}.service +/sbin/ldconfig + +#if [ $1 == 0 ]; then +# systemctl stop %{name}.service +#fi +#systemctl daemon-reload + +%post lib -p /sbin/ldconfig + +%postun lib -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%config %{_sysconfdir}/dbus-1/session.d/d2d-conv-manager.conf +%{_unitdir_user}/%{name}.service +%{_bindir}/%{name}d +%{_datadir}/dbus-1/services/org.tizen.d2dconv.service +%{_bindir}/%{name}-test +%{_datadir}/license/%{name} + +%files lib +%manifest lib%{name}.manifest +%defattr(-,root,root,-) +%{_libdir}/lib%{name}.so.* +%{_datadir}/license/%{name} + + +%files devel +%defattr(-,root,root,-) +%{_libdir}/lib%{name}.so +%{_libdir}/pkgconfig/%{name}.pc +%{_includedir}/*.h diff --git a/packaging/libd2d-conv-manager.manifest b/packaging/libd2d-conv-manager.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/libd2d-conv-manager.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..572e9c1 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,18 @@ +LINK_DIRECTORIES(${CMAKE_BINARY_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../lib/include) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../lib/disc_mgr/include) + +SET(TEST "d2d-conv-manager-test") + +FILE(GLOB TEST_SRCS *.c) + +pkg_check_modules(test_pkgs REQUIRED glib-2.0) +INCLUDE_DIRECTORIES(${test_pkgs_INCLUDE_DIRS}) +LINK_DIRECTORIES(${test_pkgs_LIBRARY_DIRS}) + +#SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +ADD_EXECUTABLE(${TEST} ${TEST_SRCS}) +TARGET_LINK_LIBRARIES(${TEST} ${test_pkgs_LIBRARIES} ${CLIENT}) + +INSTALL(TARGETS ${TEST} DESTINATION ${BIN_INSTALL_DIR}) diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..c4b31b4 --- /dev/null +++ b/test/test.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "d2d_conv_manager.h" + +#define CONV_JSON_DESCRIPTION "description" +#define CONV_JSON_PAYLOAD "payload" +#define CONV_JSON_SERVICE "service" +#define CONV_JSON_CHANNEL "channel" +#define CONV_JSON_IS_LOCAL "is_local" +#define CONV_JSON_DEVICE "device" +#define CONV_JSON_TYPE "type" + +#define CONV_JSON_SERVICE_PATH "service" +#define CONV_JSON_SERVICE_DATA "data" +#define CONV_JSON_SERVICE_TYPE "type" + +#define CONV_JSON_SERVICE_DATA_PATH NULL +#define CONV_JSON_SERVICE_DATA_NAME "name" +#define CONV_JSON_SERVICE_DATA_VERSION "version" +#define CONV_JSON_SERVICE_DATA_TYPE "type" +#define CONV_JSON_SERVICE_DATA_ID "id" +#define CONV_JSON_SERVICE_DATA_URI CONV_SERVICE_ID + +#define CONV_JSON_DEVICE_ID "device_id" +#define CONV_JSON_DEVICE_NAME "device_name" +#define CONV_JSON_DEVICE_ADDRESS "host_address" + +struct arg_data { + int type; + //.. +}; + +static GMainLoop *loop; + +void simple_test_conv_service_cb(conv_service_h handle, conv_channel_h channel, int error, conv_payload_h result, void* user_data) +{ + printf("callback for service..\n"); + char* test; + + conv_payload_get_string(result, "result_type", &test); + + printf("result type : %s\n", test); + + if (!strcmp(test, "getClient")) { + conv_service_h service_handle = (conv_service_h)user_data; + + printf("conv_service_stop called..\n"); + conv_service_stop(service_handle, channel, NULL); + printf("conv_service_destroy called..\n"); + conv_service_destroy(service_handle); + + g_main_loop_quit(loop); + } +} + +void service_remote_app_control_foreach_cb(conv_service_h handle, void* user_data) +{ + printf("==============================\n"); + printf("service_foreach_cb called"); + + if (handle != NULL) { + char *version = NULL, *type = NULL, *uri = NULL; + conv_service_e serv_type; + + conv_service_get_type(handle, &serv_type); + + printf("service type[%d]\n", serv_type); + + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_VERSION, &version); + if (version != NULL) printf("service version[%s]", version); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_TYPE, &type); + if (type != NULL) printf(" type[%s]", type); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_URI, &uri); + if (uri != NULL) printf(" uri[%s]\n", uri); + + if (serv_type == CONV_SERVICE_REMOTE_APP_CONTROL) { + + printf("app control test start\n"); + conv_service_start(handle, NULL, NULL); + printf("service start\n"); + conv_payload_h payload_handle; + + conv_payload_create(&payload_handle); + + app_control_h app_control = NULL; + app_control_create(&app_control); + app_control_set_app_id(app_control, "org.tizen.browser"); + app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN); + + printf("conv_payload_add_string called..\n"); + conv_payload_set_app_control(payload_handle, "app_control", app_control); + conv_payload_set_string(payload_handle, "reply", "0"); + printf("conv_service_publish called..\n"); + conv_service_publish(handle, NULL, payload_handle); + + sleep(3); + + printf("conv_service_stop called..\n"); + conv_service_stop(handle, NULL, NULL); + + printf("conv_payload_destroy called..\n"); + conv_payload_destroy(payload_handle); + + } + printf("next\n"); + + + } + +} + +void service_app_communication_foreach_cb(conv_service_h handle, void* user_data) +{ + + printf("==============================\n"); + printf("service_foreach_cb called"); + + if (handle != NULL) { + char *version = NULL, *type = NULL, *uri = NULL; + conv_service_e serv_type; + + conv_service_get_type(handle, &serv_type); + + printf("service type[%d]\n", serv_type); + + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_VERSION, &version); + if (version != NULL) printf("service version[%s]", version); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_TYPE, &type); + if (type != NULL) printf(" type[%s]", type); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_URI, &uri); + if (uri != NULL) printf(" uri[%s]\n", uri); + + if (serv_type == CONV_SERVICE_APP_TO_APP_COMMUNICATION) { + conv_channel_h channel_handle; + conv_payload_h payload_handle; + + printf("conv_channel_create called..\n"); + conv_channel_create(&channel_handle); + + printf("conv_payload_create called..\n"); + conv_payload_create(&payload_handle); + + printf("conv_channel_add called..\n"); + conv_channel_set_string(channel_handle, "uri", "http://www.tizen.org"); + conv_channel_set_string(channel_handle, "channel_id", "test_id"); + + printf("set service cb..\n"); + conv_service_set_listener_cb(handle, simple_test_conv_service_cb, (void*)handle); + + printf("conv_service_start called..\n"); + conv_service_start(handle, channel_handle, NULL); + + sleep(5); + + printf("conv_payload_add_string called..\n"); + conv_payload_set_string(payload_handle, "event", "send_message"); + conv_payload_set_string(payload_handle, "data", "hello. This is d2d conv manager test"); + + printf("conv_service_publish called..\n"); + conv_service_publish(handle, channel_handle, payload_handle); + + printf("conv_service_publish called..\n"); + conv_service_publish(handle, channel_handle, payload_handle); + + sleep(3); + + + printf("conv_service_stop called..\n"); + conv_service_stop(handle, channel_handle, NULL); + /* + printf("conv_service_get called..\n"); + conv_service_get(handle, channel_handle, NULL, NULL); + */ + printf("conv_payload_destroy called..\n"); + conv_payload_destroy(payload_handle); + + printf("conv_channel_destroy called..\n"); + conv_channel_destroy(channel_handle); + + } + printf("next\n"); + + + } + +} + +void service_foreach_cb(conv_service_h handle, void* user_data) +{ + printf("==============================\n"); + printf("service_foreach_cb called"); + + if (handle != NULL) { + char *version = NULL, *type = NULL, *uri = NULL; + conv_service_e serv_type; + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_VERSION, &version); + if (version != NULL) printf("service version[%s]", version); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_TYPE, &type); + if (type != NULL) printf(" type[%s]", type); + conv_service_get_property_string(handle, CONV_JSON_SERVICE_DATA_URI, &uri); + if (uri != NULL) printf(" uri[%s]\n", uri); + + conv_service_get_type(handle, &serv_type); + + printf("service type[%d]\n", serv_type); + } + +} + +void device_conv_remote_app_control_discovery_cb(conv_device_h device_h, int result, void* user_data) +{ + printf("Discovered!!!\n"); + char* device_id = NULL, *device_name = NULL; + + int ret; + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_ID, &device_id); + if (ret != CONV_ERROR_NONE || device_id == NULL) { + printf("device id is null %s\n", device_id); + return; + } + + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_NAME, &device_name); + if (ret != CONV_ERROR_NONE || device_name == NULL) { + printf("device name is null %s\n", device_name); + return; + } + + printf("the discovered device's info : id[%s] name[%s]\n", device_id, device_name); + ret = conv_device_foreach_service(device_h, service_remote_app_control_foreach_cb, user_data); + if (ret != CONV_ERROR_NONE) + printf("Error in conv_device_foreach_service\n"); +} + +void device_conv_app_communication_discovery_cb(conv_device_h device_h, int result, void* user_data) +{ + printf("Discovered!!!\n"); + char* device_id = NULL, *device_name = NULL; + + int ret; + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_ID, &device_id); + if (ret != CONV_ERROR_NONE || device_id == NULL) { + printf("device id is null %s\n", device_id); + return; + } + + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_NAME, &device_name); + if (ret != CONV_ERROR_NONE || device_name == NULL) { + printf("device name is null %s\n", device_name); + return; + } + + printf("the discovered device's info : id[%s] name[%s]\n", device_id, device_name); + ret = conv_device_foreach_service(device_h, service_app_communication_foreach_cb, user_data); + if (ret != CONV_ERROR_NONE) + printf("Error in conv_device_foreach_service\n"); +} + +void device_conv_discovery_cb(conv_device_h device_h, int result, void* user_data) +{ + printf("Discovered!!!\n"); + char* device_id = NULL, *device_name = NULL, *device_address; + + int ret; + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_ID, &device_id); + if (ret != CONV_ERROR_NONE || device_id == NULL) { + printf("device id is null %s\n", device_id); + return; + } + + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_NAME, &device_name); + if (ret != CONV_ERROR_NONE || device_name == NULL) { + printf("device name is null %s\n", device_name); + return; + } + + ret = conv_device_get_property_string(device_h, CONV_JSON_DEVICE_ADDRESS, &device_address); + if (ret != CONV_ERROR_NONE || device_name == NULL) { + printf("device name is null %s\n", device_name); + return; + } + + printf("the discovered device's info : id[%s] name[%s] address[%s]\n", device_id, device_name, device_address); + ret = conv_device_foreach_service(device_h, service_foreach_cb, user_data); + if (ret != CONV_ERROR_NONE) + printf("Error in conv_device_foreach_service\n"); +} + +void simple_test_conv_discovery_cb(conv_device_h device_h, int result, void* user_data) +{ + conv_channel_h channel_handle; + conv_payload_h payload_handle; + conv_service_h service_handle; + + printf("callback for discovery..\n"); + + service_handle = (conv_service_h)user_data; + + printf("conv_channel_create called..\n"); + conv_channel_create(&channel_handle); + + printf("conv_payload_create called..\n"); + conv_payload_create(&payload_handle); + + printf("conv_channel_add called..\n"); + conv_channel_set_string(channel_handle, "uri", "http://www.tizen.org"); + conv_channel_set_string(channel_handle, "channel_id", "test_id"); + + printf("set service cb..\n"); + conv_service_set_listener_cb(service_handle, simple_test_conv_service_cb, NULL); + + printf("conv_service_start called..\n"); + conv_service_start(service_handle, channel_handle, NULL); + + sleep(10); + +} + +void simple_test_conv_remote_app_control_start_stop_discovery() +{ + conv_h handle; + + printf("conv_create called..\n"); + conv_create(&handle); + + printf("conv_discovery_start called.."); + conv_discovery_start(handle, 10, device_conv_remote_app_control_discovery_cb, NULL); +} + +void simple_test_conv_app_communication_start_stop_discovery() +{ + conv_h handle; + + printf("conv_create called..\n"); + conv_create(&handle); + + printf("conv_discovery_start called.."); + conv_discovery_start(handle, 10, device_conv_app_communication_discovery_cb, NULL); +} + + +// Simple Test.. Start/Stop Discovery +void simple_test_conv_start_stop_discovery() +{ + conv_h handle; + + printf("conv_create called..\n"); + conv_create(&handle); + +/* + printf("set discovery cb..\n"); + //conv_set_discovery_cb (handle, simple_test_conv_discovery_cb, NULL); + conv_set_discovery_cb (handle, device_conv_discovery_cb, NULL); +*/ + + printf("conv_discovery_start called..\n"); + conv_discovery_start(handle, 10, device_conv_discovery_cb, NULL); + +#if 0 + sleep(20); + + printf("conv_discovery_stop called..\n"); + conv_discovery_stop(handle); + + printf("conv_destroy called..\n"); + conv_destroy(handle); +#endif + +} + +void simple_test_remote_app_control_service_start_stop(char* address) +{ + if (address == NULL) { + printf("no address entered\n"); + return; + } + + conv_service_h service_handle; + conv_payload_h payload_handle; + + printf("conv_service_create called..\n"); + conv_service_create(&service_handle); + + conv_service_set_property_string(service_handle, "id", "84:A4:66:BC:C9:86"); + conv_service_set_property_string(service_handle, CONV_SERVICE_ID, address); + conv_service_set_property_string(service_handle, "name", "Tizen TV"); + conv_service_set_type(service_handle, CONV_SERVICE_REMOTE_APP_CONTROL); + + printf("conv_payload_create called..\n"); + conv_payload_create(&payload_handle); + + printf("set service cb..\n"); + conv_service_set_listener_cb(service_handle, simple_test_conv_service_cb, (void*)service_handle); + + printf("conv_service_start called..\n"); + conv_service_start(service_handle, NULL, NULL); + + sleep(5); + + app_control_h app_control = NULL; + app_control_create(&app_control); + app_control_set_app_id(app_control, "org.tizen.browser"); + app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN); + + printf("conv_payload_add_string called..\n"); + conv_payload_set_app_control(payload_handle, "app_control", app_control); + conv_payload_set_string(payload_handle, "reply", 0); + printf("conv_service_publish called..\n"); + conv_service_publish(service_handle, NULL, payload_handle); + + sleep(3); + + printf("conv_service_stop called..\n"); + conv_service_stop(service_handle, NULL, NULL); + + printf("conv_payload_destroy called..\n"); + conv_payload_destroy(payload_handle); + +} + +int main(int argc, char** argv) +{ + loop = g_main_loop_new(NULL, FALSE); + + if (argc > 1) { + printf("1"); + int type = atoi(argv[1]); + struct arg_data* args = g_slice_alloc(sizeof(*args)); + args->type = type; + + switch (type) { + case 0: + simple_test_conv_start_stop_discovery(); + break; + case 1: + simple_test_conv_app_communication_start_stop_discovery(); + break; + case 2: + simple_test_conv_remote_app_control_start_stop_discovery(); + break; + default: + break; + }; + } + + g_main_loop_run(loop); + g_main_loop_unref(loop); + + + return 0; +} -- 2.7.4