From f96d39c89bfb281ccade623aaa2ee4f6e720d1ed Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Mon, 27 Nov 2017 20:30:27 +0900 Subject: [PATCH 02/16] Add interfaces for rpc-port and rpc-port-parcel APIs Change-Id: If5066f2cc92b6d472553204222452c4eea6bf047 Signed-off-by: Junghoon Park --- CMakeLists.txt | 62 ++++++++++++++ LICENSE.APLv2 | 202 ++++++++++++++++++++++++++++++++++++++++++++ NOTICE | 3 + capi-rpc-port.pc.in | 13 +++ include/rpc-port-parcel.h | 65 ++++++++++++++ include/rpc-port.h | 73 ++++++++++++++++ packaging/rpc-port.manifest | 5 ++ packaging/rpc-port.spec | 65 ++++++++++++++ rpc-port.pc.in | 13 +++ src/rpc_port.cc | 93 ++++++++++++++++++++ src/rpc_port_parcel.cc | 127 ++++++++++++++++++++++++++++ 11 files changed, 721 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE.APLv2 create mode 100644 NOTICE create mode 100644 capi-rpc-port.pc.in create mode 100644 include/rpc-port-parcel.h create mode 100755 include/rpc-port.h create mode 100644 packaging/rpc-port.manifest create mode 100755 packaging/rpc-port.spec create mode 100644 rpc-port.pc.in create mode 100755 src/rpc_port.cc create mode 100755 src/rpc_port_parcel.cc diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5b10bcd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +PROJECT(rpc-port CXX) +SET(this_target rpc-port) + +INCLUDE_DIRECTORIES ( + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_SOURCE_DIR}/src + ) + +SET(${this_target}_requires "dlog bundle glib-2.0 gio-2.0 aul openssl capi-base-common pkgmgr-info gio-unix-2.0") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${this_target} REQUIRED ${${this_target}_requires}) + +FOREACH(flag ${${this_target}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall" ) + +## SET C COMPILER FLAGS +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror -fvisibility=hidden") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +## SET CPP COMPILER FLAGS +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fvisibility=hidden -std=c++11") + +## Create Library +AUX_SOURCE_DIRECTORY(src SOURCES) +ADD_LIBRARY(${this_target} SHARED ${SOURCES}) + +## SET LINKER FLAGS +SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed -Wl,--no-undefined -Wl,--rpath=${LIB_INSTALL_DIR}") + +TARGET_LINK_LIBRARIES(${this_target} ${${this_target}_LDFLAGS}) + +SET_TARGET_PROPERTIES(${this_target} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 + ) + +# pkgconfig file +SET(PC_NAME ${this_target}) +SET(VERSION ${FULLVER}) +SET(PC_REQUIRED ${${this_target}_requires}) + +## OUTPUT PATHS +SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/cmake_build_tmp/output) +ADD_CUSTOM_COMMAND( + TARGET ${this_target} POST_BUILD + COMMAND ln -s ./librpc-port.so.${MAJORVER} ${LIBRARY_OUTPUT_PATH}/libcapi-rpc-port.so.${MAJORVER}) + +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/${this_target}.pc.in ${CMAKE_SOURCE_DIR}/${this_target}.pc @ONLY) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/${this_target}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/capi-${this_target}.pc.in ${CMAKE_SOURCE_DIR}/capi-${this_target}.pc @ONLY) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/capi-${this_target}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${this_target} DESTINATION ${LIB_INSTALL_DIR}) + +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/rpc-port FILES_MATCHING PATTERN "*.h") +INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/ DESTINATION ${LIB_INSTALL_DIR} FILES_MATCHING PATTERN "*.so*") diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..0e0f016 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/capi-rpc-port.pc.in b/capi-rpc-port.pc.in new file mode 100644 index 0000000..70f43da --- /dev/null +++ b/capi-rpc-port.pc.in @@ -0,0 +1,13 @@ + +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@/rpc-port + +Name: capi-rpc-port +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Libs: -L${libdir} -lrpc-port +Cflags: -I${includedir} diff --git a/include/rpc-port-parcel.h b/include/rpc-port-parcel.h new file mode 100644 index 0000000..b353510 --- /dev/null +++ b/include/rpc-port-parcel.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RPC_PORT_PARCEL_INCLUDE_H__ +#define __RPC_PORT_PARCEL_INCLUDE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *rpc_port_parcel_h; +typedef struct __rpc_port_parcelable { + void (*to)(rpc_port_parcel_h h, void *data); + void (*from)(rpc_port_parcel_h h, void *data); +} rpc_port_parcelable_t; + +int rpc_port_parcel_create(rpc_port_parcel_h *h); +int rpc_port_parcel_create_from_port(rpc_port_parcel_h *h, rpc_port_h port); +int rpc_port_parcel_send(rpc_port_parcel_h *h, rpc_port_h port); +int rpc_port_parcel_destroy(rpc_port_parcel_h h); +int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b); +int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i); +int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i); +int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i); +int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f); +int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d); +int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char *str); +int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b); +int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle *b); +int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count); +int rpc_port_parcel_write(rpc_port_parcel_h h, rpc_port_parcelable_t *parcelable, void *data); +int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char *b); +int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short *i); +int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int *i); +int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long *i); +int rpc_port_parcel_read_float(rpc_port_parcel_h h, float *f); +int rpc_port_parcel_read_double(rpc_port_parcel_h h, double *d); +int rpc_port_parcel_read_string(rpc_port_parcel_h h, char **str); +int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool *b); +int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle **b); +int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int *count); +int rpc_port_parcel_read(rpc_port_parcel_h h, rpc_port_parcelable_t *parcelable, void *data); + +#ifdef __cplusplus +} +#endif + +#endif // __RPC_PORT_PARCEL_INCLUDE_H__ diff --git a/include/rpc-port.h b/include/rpc-port.h new file mode 100755 index 0000000..87db927 --- /dev/null +++ b/include/rpc-port.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RPC_PORT_INCLUDE_H__ +#define __RPC_PORT_INCLUDE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* common */ +typedef void *rpc_port_h; +int rpc_port_open(int fd, rpc_port_h *h); +int rpc_port_close(rpc_port_h h); +int rpc_port_read(rpc_port_h h, char *buf, unsigned int size); +int rpc_port_write(rpc_port_h h, char *buf, unsigned int size); + +/* proxy */ +typedef void (*rpc_port_proxy_connected_event_cb)(const char *ep, + const char *port_name, rpc_port_h port, void *data); +typedef void (*rpc_port_proxy_disconnected_event_cb)(const char *ep, + const char *port_name, void *data); +typedef void (*rpc_port_proxy_rejected_event_cb)(const char *ep, + const char *port_name, void *data); +typedef void *rpc_port_proxy_h; +int rpc_port_proxy_create(rpc_port_proxy_h *h); +int rpc_port_proxy_destroy(rpc_port_proxy_h h); +int rpc_port_proxy_connect(rpc_port_proxy_h h, const char *appid, + const char *port); + +int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_connected_event_cb cb, void *data); +int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_disconnected_event_cb cb, void *data); +int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_rejected_event_cb cb, void *data); + +/* stub */ +typedef void *rpc_port_stub_h; +typedef void (*rpc_port_stub_connected_event_cb)(const char *sender, + void *data); +typedef void (*rpc_port_stub_disconnected_event_cb)(const char *sender, + void *data); +typedef void (*rpc_port_stub_received_event_cb)(const char *sender, + rpc_port_h port, void *data); +int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name); +int rpc_port_stub_destroy(rpc_port_stub_h h); +int rpc_port_stub_listen(rpc_port_stub_h h); +int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, + rpc_port_stub_connected_event_cb cb, void *data); +int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, + rpc_port_stub_disconnected_event_cb cb, void *data); +int rpc_port_stub_add_recevied_event_cb(rpc_port_stub_h h, + rpc_port_stub_received_event_cb cb, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* __RPC_PORT_INCLUDE_H__ */ diff --git a/packaging/rpc-port.manifest b/packaging/rpc-port.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/rpc-port.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec new file mode 100755 index 0000000..ecb09f4 --- /dev/null +++ b/packaging/rpc-port.spec @@ -0,0 +1,65 @@ +Name: rpc-port +Summary: RPC Port library +Version: 1.0.0 +Release: 0 +Group: Application Framework/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(pkgmgr) +BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(openssl) + +Requires(post): /sbin/ldconfig +Requires(post): coreutils +Requires(postun): /sbin/ldconfig + +Provides: capi-rpc-port +Provides: libcapi-rpc-port.so.1 + +%description +RPC Port library package. + +%package devel +Summary: RPC Port library (Development) +Group: Application Framework/Development +Requires: %{name} = %{version}-%{release} + +%description devel +RPC Port library (Development) package. + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER} +# Call make instruction with smp support +%__make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} + +%make_install + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%attr(0644,root,root) %{_libdir}/lib%{name}.so.* +%attr(0644,root,root) %{_libdir}/libcapi-rpc-port.so.* +%license LICENSE.APLv2 + +%files devel +%{_includedir}/rpc-port/*.h +%{_libdir}/pkgconfig/*.pc +%{_libdir}/lib%{name}.so diff --git a/rpc-port.pc.in b/rpc-port.pc.in new file mode 100644 index 0000000..efbec14 --- /dev/null +++ b/rpc-port.pc.in @@ -0,0 +1,13 @@ + +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@/rpc-port + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Libs: -L${libdir} -lrpc-port +Cflags: -I${includedir} diff --git a/src/rpc_port.cc b/src/rpc_port.cc new file mode 100755 index 0000000..1a543ae --- /dev/null +++ b/src/rpc_port.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "rpc-port.h" + +#undef RPC_API +#define RPC_API extern "C" __attribute__((visibility("default"))) + +RPC_API int rpc_port_open(int fd, rpc_port_h *h) { + return 0; +} + +RPC_API int rpc_port_close(rpc_port_h h) { + return 0; +} + +RPC_API int rpc_port_read(rpc_port_h h, char *buf, unsigned int size) { + return 0; +} + +RPC_API int rpc_port_write(rpc_port_h h, char *buf, unsigned int size) { + return 0; +} + +RPC_API int rpc_port_proxy_create(rpc_port_proxy_h *h) { + return 0; +} + +RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) { + return 0; +} + +RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char *appid, + const char *port) { + return 0; +} + +RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_connected_event_cb cb, void *data) { + return 0; +} + +RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_disconnected_event_cb cb, void *data) { + return 0; +} + +RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_rejected_event_cb cb, void *data) { + return 0; +} + +RPC_API int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name) { + return 0; +} + +RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) { + return 0; +} + +RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) { + return 0; +} + +RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, + rpc_port_stub_connected_event_cb cb, void *data) { + return 0; +} + +RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, + rpc_port_stub_disconnected_event_cb cb, void *data) { + return 0; +} + +RPC_API int rpc_port_stub_add_recevied_event_cb(rpc_port_stub_h h, + rpc_port_stub_received_event_cb cb, void *data) { + return 0; +} diff --git a/src/rpc_port_parcel.cc b/src/rpc_port_parcel.cc new file mode 100755 index 0000000..18953a1 --- /dev/null +++ b/src/rpc_port_parcel.cc @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rpc-port-parcel.h" + +#undef RPC_API +#define RPC_API extern "C" __attribute__((visibility("default"))) + +RPC_API int rpc_port_parcel_create(rpc_port_parcel_h *h) { + return 0; +} + +RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h *h, + rpc_port_h port) { + return 0; +} + +RPC_API int rpc_port_parcel_send(rpc_port_parcel_h *h, rpc_port_h port) { + return 0; +} + +RPC_API int rpc_port_parcel_destroy(rpc_port_parcel_h h) { + return 0; +} + +RPC_API int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b) { + return 0; +} + +RPC_API int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i) { + return 0; +} + +RPC_API int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i) { + return 0; +} + +RPC_API int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i) { + return 0; +} + +RPC_API int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f) { + return 0; +} + +RPC_API int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d) { + return 0; +} + +RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char *str) { + return 0; +} + +RPC_API int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b) { + return 0; +} + +RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle *b) { + return 0; +} + +RPC_API int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count) { + return 0; +} + +RPC_API int rpc_port_parcel_write(rpc_port_parcel_h h, + rpc_port_parcelable_t *parcelable, void *data) { + return 0; +} + +RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char *b) { + return 0; +} + +RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short *i) { + return 0; +} + +RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int *i) { + return 0; +} + +RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long *i) { + return 0; +} + +RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float *f) { + return 0; +} + +RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double *d) { + return 0; +} + +RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char **str) { + return 0; +} + +RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool *b) { + return 0; +} + +RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle **b) { + return 0; +} + +RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int *count) { + return 0; +} + +RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h, + rpc_port_parcelable_t *parcelable, void *data) { + return 0; +} -- 2.7.4 From e639d8ddf0e3c2c9426caa508fd984666c17605a Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Tue, 28 Nov 2017 11:42:44 +0900 Subject: [PATCH 03/16] Implement internal class for ipc-port-parcel APIs Change-Id: Iffff2ac8d991106d3a81cc8902a24aa07ba9d6ab Signed-off-by: Junghoon Park --- src/parcel-internal.cc | 133 +++++++++++++++++++++++++ src/parcel-internal.h | 81 +++++++++++++++ src/{rpc_port_parcel.cc => rpc-port-parcel.cc} | 0 src/{rpc_port.cc => rpc-port.cc} | 0 4 files changed, 214 insertions(+) create mode 100644 src/parcel-internal.cc create mode 100644 src/parcel-internal.h rename src/{rpc_port_parcel.cc => rpc-port-parcel.cc} (100%) rename src/{rpc_port.cc => rpc-port.cc} (100%) diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc new file mode 100644 index 0000000..9868c57 --- /dev/null +++ b/src/parcel-internal.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "parcel-internal.h" + +namespace rpc_port { + +Parcel::Parcel(const unsigned char* buf, unsigned int size) + : data_(buf, buf + size) { + reader_ = data_.begin(); +} + +void Parcel::WriteByte(char b) { + Write(b); +} + +void Parcel::WriteInt16(short i) { + Write(i); +} + +void Parcel::WriteInt32(int i) { + Write(i); +} + +void Parcel::WriteInt64(long long i) { + Write(i); +} + +void Parcel::WriteFloat(float f) { + Write(f); +} + +void Parcel::WriteDouble(double d) { + Write(d); +} + +void Parcel::WriteString(const char* str) { + int l = std::strlen(str) + 1; + + Write(l); + std::copy(str, str + l, std::back_inserter(data_)); +} + +void Parcel::WriteBool(bool b) { + Write(b); +} + +void Parcel::WriteBundle(bundle* b) { + bundle_raw *r; + int len; + bundle_encode(b, &r, &len); + unsigned char* c = reinterpret_cast(r); + + Write(len + 1); + std::copy(c, c + len + 1, std::back_inserter(data_)); +} + +void Parcel::WriteArrayCount(int count) { + Write(count); +} + +char Parcel::ReadByte() { + return Read(); +} + +short Parcel::ReadInt16() { + return Read(); +} + +int Parcel::ReadInt32() { + return Read(); +} + +long long Parcel::ReadInt64() { + return Read(); +} + +float Parcel::ReadFloat() { + return Read(); +} + +double Parcel::ReadDouble() { + return Read(); +} + +std::string Parcel::ReadString() { + int l = Read(); + + std::string str(reader_, reader_ + l); + reader_ += l; + + return str; +} + +bool Parcel::ReadBool() { + return Read(); +} + +bundle* Parcel::ReadBundle() { + int l = Read(); + + std::string str(reader_, reader_ + l); + reader_ += l; + + bundle* b = bundle_decode( + reinterpret_cast(str.c_str()), l - 1); + + return b; +} + +int Parcel::ReadArrayCount() { + return Read(); +} + +const std::vector& Parcel::GetRaw() { + return data_; +} + +} // namespace rpc_port \ No newline at end of file diff --git a/src/parcel-internal.h b/src/parcel-internal.h new file mode 100644 index 0000000..f63960e --- /dev/null +++ b/src/parcel-internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PARCEL_INTERNAL_H__ +#define __PARCEL_INTERNAL_H__ + +#include + +#include +#include +#include +#include + +namespace rpc_port { + +class Parcel { + public: + Parcel() = default; + Parcel(const unsigned char* buf, unsigned int size); + + void WriteByte(char b); + void WriteInt16(short i); + void WriteInt32(int i); + void WriteInt64(long long i); + void WriteFloat(float f); + void WriteDouble(double d); + void WriteString(const char* str); + void WriteBool(bool b); + void WriteBundle(bundle* b); + void WriteArrayCount(int count); + char ReadByte(); + short ReadInt16(); + int ReadInt32(); + long long ReadInt64(); + float ReadFloat(); + double ReadDouble(); + std::string ReadString(); + bool ReadBool(); + bundle* ReadBundle(); + int ReadArrayCount(); + const std::vector& GetRaw(); + + private: + template + void Write(T d) { + unsigned char* p = reinterpret_cast(&d); + + std::copy(p, p + sizeof(T), std::back_inserter(data_)); + } + + template + T Read() { + T d; + unsigned char* p = reinterpret_cast(&d); + + std::copy(reader_, reader_ + sizeof(T), p); + reader_ += sizeof(T); + return d; + } + + private: + std::vector data_; + std::vector::iterator reader_; +}; + +} + +#endif // __PARCEL_INTERNAL_H__ \ No newline at end of file diff --git a/src/rpc_port_parcel.cc b/src/rpc-port-parcel.cc similarity index 100% rename from src/rpc_port_parcel.cc rename to src/rpc-port-parcel.cc diff --git a/src/rpc_port.cc b/src/rpc-port.cc similarity index 100% rename from src/rpc_port.cc rename to src/rpc-port.cc -- 2.7.4 From a238308bdb1656324919fcae45c6f2a3b54c3172 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Tue, 28 Nov 2017 14:52:23 +0900 Subject: [PATCH 04/16] Implement APIs for rpc-port-parcel Change-Id: I325777c0f2f14f861abde2a3ab4292bc68081add Signed-off-by: Junghoon Park --- include/rpc-port-parcel.h | 6 +- include/rpc-port.h | 4 +- src/parcel-internal.h | 2 +- src/rpc-port-parcel.cc | 294 +++++++++++++++++++++++++++++++++++++++------- src/rpc-port.cc | 58 ++++----- 5 files changed, 285 insertions(+), 79 deletions(-) diff --git a/include/rpc-port-parcel.h b/include/rpc-port-parcel.h index b353510..847e0a5 100644 --- a/include/rpc-port-parcel.h +++ b/include/rpc-port-parcel.h @@ -27,13 +27,13 @@ extern "C" { typedef void *rpc_port_parcel_h; typedef struct __rpc_port_parcelable { - void (*to)(rpc_port_parcel_h h, void *data); - void (*from)(rpc_port_parcel_h h, void *data); + void (*to)(rpc_port_parcel_h h, void *data); + void (*from)(rpc_port_parcel_h h, void *data); } rpc_port_parcelable_t; int rpc_port_parcel_create(rpc_port_parcel_h *h); int rpc_port_parcel_create_from_port(rpc_port_parcel_h *h, rpc_port_h port); -int rpc_port_parcel_send(rpc_port_parcel_h *h, rpc_port_h port); +int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port); int rpc_port_parcel_destroy(rpc_port_parcel_h h); int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b); int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i); diff --git a/include/rpc-port.h b/include/rpc-port.h index 87db927..b66e677 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -25,8 +25,8 @@ extern "C" { typedef void *rpc_port_h; int rpc_port_open(int fd, rpc_port_h *h); int rpc_port_close(rpc_port_h h); -int rpc_port_read(rpc_port_h h, char *buf, unsigned int size); -int rpc_port_write(rpc_port_h h, char *buf, unsigned int size); +int rpc_port_read(rpc_port_h h, void *buf, unsigned int size); +int rpc_port_write(rpc_port_h h, const void *buf, unsigned int size); /* proxy */ typedef void (*rpc_port_proxy_connected_event_cb)(const char *ep, diff --git a/src/parcel-internal.h b/src/parcel-internal.h index f63960e..645cf36 100644 --- a/src/parcel-internal.h +++ b/src/parcel-internal.h @@ -76,6 +76,6 @@ class Parcel { std::vector::iterator reader_; }; -} +} // namespace rpc_port #endif // __PARCEL_INTERNAL_H__ \ No newline at end of file diff --git a/src/rpc-port-parcel.cc b/src/rpc-port-parcel.cc index 18953a1..0500268 100755 --- a/src/rpc-port-parcel.cc +++ b/src/rpc-port-parcel.cc @@ -14,114 +14,320 @@ * limitations under the License. */ +#include + #include "rpc-port-parcel.h" +#include "parcel-internal.h" + #undef RPC_API #define RPC_API extern "C" __attribute__((visibility("default"))) -RPC_API int rpc_port_parcel_create(rpc_port_parcel_h *h) { - return 0; +using namespace rpc_port; + +RPC_API int rpc_port_parcel_create(rpc_port_parcel_h* h) { + Parcel* p = new Parcel(); + + *h = p; + + return 0; } -RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h *h, - rpc_port_h port) { - return 0; +RPC_API int rpc_port_parcel_create_from_port(rpc_port_parcel_h* h, + rpc_port_h port) { + int len; + unsigned char* buf; + int ret; + + ret = rpc_port_read(port, &len, 4); + if (ret != 0) + return ret; + + buf = new unsigned char[len]; + ret = rpc_port_read(port, buf, len); + if (ret != 0) { + delete[] buf; + return ret; + } + + Parcel* p = new Parcel(buf, len); + delete[] buf; + + *h = p; + + return 0; } -RPC_API int rpc_port_parcel_send(rpc_port_parcel_h *h, rpc_port_h port) { - return 0; +RPC_API int rpc_port_parcel_send(rpc_port_parcel_h h, rpc_port_h port) { + Parcel* p = static_cast(h); + int len = p->GetRaw().size(); + int ret; + + if (len <= 0) + return -1; + + ret = rpc_port_write(port, &len, 4); + if (ret != 0) + return ret; + + ret = rpc_port_write(port, &*(p->GetRaw().cbegin()), len); + if (ret != 0) + return ret; + + return 0; } RPC_API int rpc_port_parcel_destroy(rpc_port_parcel_h h) { - return 0; + if (h == nullptr) + return -1; + + delete static_cast(h); + + return 0; } RPC_API int rpc_port_parcel_write_byte(rpc_port_parcel_h h, char b) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteByte(b); + + return 0; } RPC_API int rpc_port_parcel_write_int16(rpc_port_parcel_h h, short i) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteInt16(i); + + return 0; } RPC_API int rpc_port_parcel_write_int32(rpc_port_parcel_h h, int i) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteInt32(i); + + return 0; } RPC_API int rpc_port_parcel_write_int64(rpc_port_parcel_h h, long long i) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteInt64(i); + + return 0; } RPC_API int rpc_port_parcel_write_float(rpc_port_parcel_h h, float f) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteFloat(f); + + return 0; } RPC_API int rpc_port_parcel_write_double(rpc_port_parcel_h h, double d) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteDouble(d); + + return 0; } -RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char *str) { - return 0; +RPC_API int rpc_port_parcel_write_string(rpc_port_parcel_h h, const char* str) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteString(str); + + return 0; } RPC_API int rpc_port_parcel_write_bool(rpc_port_parcel_h h, bool b) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteBool(b); + + return 0; } -RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle *b) { - return 0; +RPC_API int rpc_port_parcel_write_bundle(rpc_port_parcel_h h, bundle* b) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteBundle(b); + + return 0; } RPC_API int rpc_port_parcel_write_array_count(rpc_port_parcel_h h, int count) { - return 0; + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + p->WriteArrayCount(count); + + return 0; } RPC_API int rpc_port_parcel_write(rpc_port_parcel_h h, - rpc_port_parcelable_t *parcelable, void *data) { - return 0; + rpc_port_parcelable_t* parcelable, void* data) { + if (parcelable == nullptr || parcelable->to == nullptr) + return -1; + + if (h == nullptr) + return -1; + + parcelable->to(h, data); + + return 0; } -RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char *b) { - return 0; +RPC_API int rpc_port_parcel_read_byte(rpc_port_parcel_h h, char* b) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *b = p->ReadByte(); + + return 0; } -RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short *i) { - return 0; +RPC_API int rpc_port_parcel_read_int16(rpc_port_parcel_h h, short* i) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *i = p->ReadInt16(); + + return 0; } -RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int *i) { - return 0; +RPC_API int rpc_port_parcel_read_int32(rpc_port_parcel_h h, int* i) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *i = p->ReadInt32(); + + return 0; } -RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long *i) { - return 0; +RPC_API int rpc_port_parcel_read_int64(rpc_port_parcel_h h, long long* i) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *i = p->ReadInt64(); + + return 0; } -RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float *f) { - return 0; +RPC_API int rpc_port_parcel_read_float(rpc_port_parcel_h h, float* f) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *f = p->ReadFloat(); + + return 0; } -RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double *d) { - return 0; +RPC_API int rpc_port_parcel_read_double(rpc_port_parcel_h h, double* d) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *d = p->ReadDouble(); + + return 0; } -RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char **str) { - return 0; +RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char** str) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *str = strdup(p->ReadString().c_str()); + + return 0; } -RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool *b) { - return 0; +RPC_API int rpc_port_parcel_read_bool(rpc_port_parcel_h h, bool* b) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *b = p->ReadBool(); + + return 0; } -RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle **b) { - return 0; +RPC_API int rpc_port_parcel_read_bundle(rpc_port_parcel_h h, bundle** b) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *b = p->ReadBundle(); + + return 0; } -RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int *count) { - return 0; +RPC_API int rpc_port_parcel_read_array_count(rpc_port_parcel_h h, int* count) { + if (h == nullptr) + return -1; + + Parcel* p = static_cast(h); + + *count = p->ReadArrayCount(); + + return 0; } RPC_API int rpc_port_parcel_read(rpc_port_parcel_h h, - rpc_port_parcelable_t *parcelable, void *data) { - return 0; + rpc_port_parcelable_t* parcelable, void* data) { + if (parcelable == nullptr || parcelable->from == nullptr) + return -1; + + if (h == nullptr) + return -1; + + parcelable->from(h, data); + + return 0; } diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 1a543ae..4292359 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -21,73 +21,73 @@ #undef RPC_API #define RPC_API extern "C" __attribute__((visibility("default"))) -RPC_API int rpc_port_open(int fd, rpc_port_h *h) { - return 0; +RPC_API int rpc_port_open(int fd, rpc_port_h* h) { + return 0; } RPC_API int rpc_port_close(rpc_port_h h) { - return 0; + return 0; } -RPC_API int rpc_port_read(rpc_port_h h, char *buf, unsigned int size) { - return 0; +RPC_API int rpc_port_read(rpc_port_h h, void* buf, unsigned int size) { + return 0; } -RPC_API int rpc_port_write(rpc_port_h h, char *buf, unsigned int size) { - return 0; +RPC_API int rpc_port_write(rpc_port_h h, const void* buf, unsigned int size) { + return 0; } -RPC_API int rpc_port_proxy_create(rpc_port_proxy_h *h) { - return 0; +RPC_API int rpc_port_proxy_create(rpc_port_proxy_h* h) { + return 0; } RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) { - return 0; + return 0; } -RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char *appid, - const char *port) { - return 0; +RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char* appid, + const char* port) { + return 0; } RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h, - rpc_port_proxy_connected_event_cb cb, void *data) { - return 0; + rpc_port_proxy_connected_event_cb cb, void *data) { + return 0; } RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, - rpc_port_proxy_disconnected_event_cb cb, void *data) { - return 0; + rpc_port_proxy_disconnected_event_cb cb, void* data) { + return 0; } RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, - rpc_port_proxy_rejected_event_cb cb, void *data) { - return 0; + rpc_port_proxy_rejected_event_cb cb, void* data) { + return 0; } -RPC_API int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name) { - return 0; +RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) { + return 0; } RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) { - return 0; + return 0; } RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) { - return 0; + return 0; } RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, - rpc_port_stub_connected_event_cb cb, void *data) { - return 0; + rpc_port_stub_connected_event_cb cb, void* data) { + return 0; } RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, - rpc_port_stub_disconnected_event_cb cb, void *data) { - return 0; + rpc_port_stub_disconnected_event_cb cb, void* data) { + return 0; } RPC_API int rpc_port_stub_add_recevied_event_cb(rpc_port_stub_h h, - rpc_port_stub_received_event_cb cb, void *data) { - return 0; + rpc_port_stub_received_event_cb cb, void* data) { + return 0; } -- 2.7.4 From 464d5830e9de24f2f8a95358aba073fda666ae6d Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Tue, 28 Nov 2017 16:50:46 +0900 Subject: [PATCH 05/16] Add unit tests Change-Id: I54bdfca90c792f69471f6644adf50e9961ae6ab9 Signed-off-by: Junghoon Park --- CMakeLists.txt | 2 + packaging/rpc-port.spec | 15 +++ src/parcel-internal.cc | 8 +- src/parcel-internal.h | 4 +- unit_tests/CMakeLists.txt | 30 +++++ unit_tests/src/main.cc | 23 ++++ unit_tests/src/rpc_port_parcel_test.cc | 225 +++++++++++++++++++++++++++++++++ 7 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 unit_tests/CMakeLists.txt create mode 100644 unit_tests/src/main.cc create mode 100644 unit_tests/src/rpc_port_parcel_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b10bcd..0c183bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,3 +60,5 @@ INSTALL(TARGETS ${this_target} DESTINATION ${LIB_INSTALL_DIR}) INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION include/rpc-port FILES_MATCHING PATTERN "*.h") INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/ DESTINATION ${LIB_INSTALL_DIR} FILES_MATCHING PATTERN "*.so*") + +ADD_SUBDIRECTORY(unit_tests) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index ecb09f4..18b8126 100755 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -14,6 +14,7 @@ BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(gmock) Requires(post): /sbin/ldconfig Requires(post): coreutils @@ -63,3 +64,17 @@ rm -rf %{buildroot} %{_includedir}/rpc-port/*.h %{_libdir}/pkgconfig/*.pc %{_libdir}/lib%{name}.so + +################################################# +# gtest-rpc-port +################################################# +%package -n gtest-rpc-port +Summary: GTest for rpc-port +Group: Development/Libraries +Requires: %{name} + +%description -n gtest-rpc-port +GTest for rpc-port + +%files -n gtest-rpc-port +%{_bindir}/gtest-rpc-port diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc index 9868c57..2f1ce25 100644 --- a/src/parcel-internal.cc +++ b/src/parcel-internal.cc @@ -20,9 +20,7 @@ namespace rpc_port { Parcel::Parcel(const unsigned char* buf, unsigned int size) - : data_(buf, buf + size) { - reader_ = data_.begin(); -} + : data_(buf, buf + size) {} void Parcel::WriteByte(char b) { Write(b); @@ -100,7 +98,7 @@ double Parcel::ReadDouble() { std::string Parcel::ReadString() { int l = Read(); - std::string str(reader_, reader_ + l); + std::string str(reinterpret_cast(&data_[reader_])); reader_ += l; return str; @@ -113,7 +111,7 @@ bool Parcel::ReadBool() { bundle* Parcel::ReadBundle() { int l = Read(); - std::string str(reader_, reader_ + l); + std::string str(reinterpret_cast(&data_[reader_])); reader_ += l; bundle* b = bundle_decode( diff --git a/src/parcel-internal.h b/src/parcel-internal.h index 645cf36..43a7819 100644 --- a/src/parcel-internal.h +++ b/src/parcel-internal.h @@ -66,14 +66,14 @@ class Parcel { T d; unsigned char* p = reinterpret_cast(&d); - std::copy(reader_, reader_ + sizeof(T), p); + std::copy(&data_[reader_], &data_[reader_] + sizeof(T), p); reader_ += sizeof(T); return d; } private: std::vector data_; - std::vector::iterator reader_; + unsigned int reader_ = 0; }; } // namespace rpc_port diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt new file mode 100644 index 0000000..ecbe1b6 --- /dev/null +++ b/unit_tests/CMakeLists.txt @@ -0,0 +1,30 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(gtest-rpc-port CXX) + +INCLUDE(FindPkgConfig) +pkg_check_modules(gtest-rpc-port REQUIRED + glib-2.0 + gmock + aul +) + +FOREACH(flag ${gtest-rpc-port_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") +SET(SOURCES "") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include) + +AUX_SOURCE_DIRECTORY(src SOURCES) +ADD_EXECUTABLE(${PROJECT_NAME} + ${SOURCES} +) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${gtest-rpc-port_LDFLAGS} rpc-port) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/) diff --git a/unit_tests/src/main.cc b/unit_tests/src/main.cc new file mode 100644 index 0000000..52756d2 --- /dev/null +++ b/unit_tests/src/main.cc @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int main(int argc, char** argv){ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/unit_tests/src/rpc_port_parcel_test.cc b/unit_tests/src/rpc_port_parcel_test.cc new file mode 100644 index 0000000..ee8d43c --- /dev/null +++ b/unit_tests/src/rpc_port_parcel_test.cc @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "rpc-port-parcel.h" + +using namespace std; +using ::testing::AtLeast; + +class ParcelTest : public ::testing::Test { + public: + virtual void SetUp() { + int ret = rpc_port_parcel_create(&handle_); + + ASSERT_NE(handle_, nullptr); + ASSERT_EQ(ret, 0); + } + + virtual void TearDown() { + int ret = rpc_port_parcel_destroy(handle_); + ASSERT_EQ(ret, 0); + } + + static void WriteParcelable(rpc_port_parcel_h h, void* data) { + const char str[] = "abcdef"; + int ret = rpc_port_parcel_write_string(h, str); + ASSERT_EQ(ret, 0); + + ret = rpc_port_parcel_write_double(h, 123.456f); + ASSERT_EQ(ret, 0); + + ret = rpc_port_parcel_write_int32(h, 123456); + ASSERT_EQ(ret, 0); + + ParcelTest* p = static_cast(data); + ASSERT_NE(p, nullptr); + p->touch_to_ = true; + } + + static void ReadParcelable(rpc_port_parcel_h h, void* data) { + char* s = nullptr; + int ret = rpc_port_parcel_read_string(h, &s); + ASSERT_EQ(ret, 0); + ASSERT_STREQ(s, "abcdef"); + + double b; + ret = rpc_port_parcel_read_double(h, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 123.456f); + + int i; + ret = rpc_port_parcel_read_int32(h, &i); + ASSERT_EQ(ret, 0); + ASSERT_EQ(i, 123456); + + ParcelTest* p = static_cast(data); + ASSERT_NE(p, nullptr); + p->touch_from_ = true; + } + + rpc_port_parcel_h handle_; + bool touch_from_ = false; + bool touch_to_ = false; +}; + +TEST(rpc_port_parcel, rpc_port_parcel_create_destroy) { + rpc_port_parcel_h handle; + + int ret = rpc_port_parcel_create(&handle); + + ASSERT_NE(handle, nullptr); + ASSERT_EQ(ret, 0); + + ret = rpc_port_parcel_destroy(handle); + ASSERT_EQ(ret, 0); +} + +TEST_F(ParcelTest, read_write_byte) { + int ret = rpc_port_parcel_write_byte(handle_, 'k'); + ASSERT_EQ(ret, 0); + + char b; + ret = rpc_port_parcel_read_byte(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 'k'); +} + +TEST_F(ParcelTest, read_write_int16) { + int ret = rpc_port_parcel_write_int16(handle_, 123); + ASSERT_EQ(ret, 0); + + short b; + ret = rpc_port_parcel_read_int16(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 123); +} + +TEST_F(ParcelTest, read_write_int32) { + int ret = rpc_port_parcel_write_int32(handle_, 123456); + ASSERT_EQ(ret, 0); + + int b; + ret = rpc_port_parcel_read_int32(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 123456); +} + +TEST_F(ParcelTest, read_write_int64) { + int ret = rpc_port_parcel_write_int64(handle_, 12345678); + ASSERT_EQ(ret, 0); + + long long b; + ret = rpc_port_parcel_read_int64(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 12345678); +} + +TEST_F(ParcelTest, read_write_float) { + int ret = rpc_port_parcel_write_float(handle_, 123.456f); + ASSERT_EQ(ret, 0); + + float b; + ret = rpc_port_parcel_read_float(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 123.456f); +} + +TEST_F(ParcelTest, read_write_double) { + int ret = rpc_port_parcel_write_double(handle_, 123.456f); + ASSERT_EQ(ret, 0); + + double b; + ret = rpc_port_parcel_read_double(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_EQ(b, 123.456f); +} + +TEST_F(ParcelTest, read_write_string) { + const char str[] = "abcdef"; + int ret = rpc_port_parcel_write_string(handle_, str); + ASSERT_EQ(ret, 0); + + char* s = nullptr; + ret = rpc_port_parcel_read_string(handle_, &s); + ASSERT_EQ(ret, 0); + ASSERT_STREQ(s, str); + free(s); +} + +TEST_F(ParcelTest, read_write_bool) { + int ret = rpc_port_parcel_write_bool(handle_, true); + ASSERT_EQ(ret, 0); + + bool b = false; + ret = rpc_port_parcel_read_bool(handle_, &b); + ASSERT_EQ(ret, 0); + ASSERT_TRUE(b); +} + +TEST_F(ParcelTest, read_write_bundle) { + bundle* b = bundle_create(); + ASSERT_NE(b, nullptr); + + int ret = bundle_add_str(b, "Test", "Value"); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + + ret = rpc_port_parcel_write_bundle(handle_, b); + ASSERT_EQ(ret, 0); + + bundle_free(b); + b = nullptr; + + ret = rpc_port_parcel_read_bundle(handle_, &b); + ASSERT_EQ(ret, 0); + + char* str; + ret = bundle_get_str(b, "Test", &str); + ASSERT_EQ(ret, BUNDLE_ERROR_NONE); + ASSERT_STREQ("Value", str); + + bundle_free(b); +} + +TEST_F(ParcelTest, read_write_array_count) { + int ret = rpc_port_parcel_write_array_count(handle_, 123); + ASSERT_EQ(ret, 0); + + int c; + ret = rpc_port_parcel_read_array_count(handle_, &c); + ASSERT_EQ(ret, 0); + ASSERT_EQ(c, 123); +} + +TEST_F(ParcelTest, read_write) { + rpc_port_parcelable_t p = { + .to = WriteParcelable, + .from = ReadParcelable + }; + + int ret = rpc_port_parcel_write(handle_, &p, this); + ASSERT_EQ(ret, 0); + ASSERT_TRUE(touch_to_); + + ret = rpc_port_parcel_read(handle_, &p, this); + ASSERT_EQ(ret, 0); + ASSERT_TRUE(touch_from_); +} -- 2.7.4 From 99d018cd19068c035fd1a8e55328f9fa5bccc9ec Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Wed, 29 Nov 2017 11:03:35 +0900 Subject: [PATCH 06/16] Change return-type of method ReadString to improve performance Change-Id: I34557a85d7458b47873e725fe533b36043239dc6 Signed-off-by: Junghoon Park --- src/parcel-internal.cc | 10 +++++----- src/parcel-internal.h | 2 +- src/rpc-port-parcel.cc | 2 +- unit_tests/src/rpc_port_parcel_test.cc | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/parcel-internal.cc b/src/parcel-internal.cc index 2f1ce25..e09b614 100644 --- a/src/parcel-internal.cc +++ b/src/parcel-internal.cc @@ -65,6 +65,7 @@ void Parcel::WriteBundle(bundle* b) { Write(len + 1); std::copy(c, c + len + 1, std::back_inserter(data_)); + free(r); } void Parcel::WriteArrayCount(int count) { @@ -95,10 +96,10 @@ double Parcel::ReadDouble() { return Read(); } -std::string Parcel::ReadString() { +const char* Parcel::ReadString() { int l = Read(); - std::string str(reinterpret_cast(&data_[reader_])); + const char* str = reinterpret_cast(&data_[reader_]); reader_ += l; return str; @@ -111,11 +112,10 @@ bool Parcel::ReadBool() { bundle* Parcel::ReadBundle() { int l = Read(); - std::string str(reinterpret_cast(&data_[reader_])); + const bundle_raw* str = reinterpret_cast(&data_[reader_]); reader_ += l; - bundle* b = bundle_decode( - reinterpret_cast(str.c_str()), l - 1); + bundle* b = bundle_decode(str, l - 1); return b; } diff --git a/src/parcel-internal.h b/src/parcel-internal.h index 43a7819..86f8e52 100644 --- a/src/parcel-internal.h +++ b/src/parcel-internal.h @@ -47,7 +47,7 @@ class Parcel { long long ReadInt64(); float ReadFloat(); double ReadDouble(); - std::string ReadString(); + const char* ReadString(); bool ReadBool(); bundle* ReadBundle(); int ReadArrayCount(); diff --git a/src/rpc-port-parcel.cc b/src/rpc-port-parcel.cc index 0500268..edc88a8 100755 --- a/src/rpc-port-parcel.cc +++ b/src/rpc-port-parcel.cc @@ -281,7 +281,7 @@ RPC_API int rpc_port_parcel_read_string(rpc_port_parcel_h h, char** str) { Parcel* p = static_cast(h); - *str = strdup(p->ReadString().c_str()); + *str = strdup(p->ReadString()); return 0; } diff --git a/unit_tests/src/rpc_port_parcel_test.cc b/unit_tests/src/rpc_port_parcel_test.cc index ee8d43c..12384c0 100644 --- a/unit_tests/src/rpc_port_parcel_test.cc +++ b/unit_tests/src/rpc_port_parcel_test.cc @@ -60,6 +60,7 @@ class ParcelTest : public ::testing::Test { int ret = rpc_port_parcel_read_string(h, &s); ASSERT_EQ(ret, 0); ASSERT_STREQ(s, "abcdef"); + free(s); double b; ret = rpc_port_parcel_read_double(h, &b); -- 2.7.4 From 912d485a787edca3de131d54b9a24d76d494f304 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Wed, 29 Nov 2017 16:20:34 +0900 Subject: [PATCH 07/16] Implement internal APIs for rpc-port Change-Id: I1cd72acc909afb06ecb908622161b1252e6933f9 Signed-off-by: Junghoon Park --- src/fdbroker-internal.cc | 373 +++++++++++++++++++++++++++++++++++++++++++++++ src/fdbroker-internal.h | 122 ++++++++++++++++ src/parcel-internal.h | 6 +- src/port-internal.cc | 134 +++++++++++++++++ src/port-internal.h | 49 +++++++ src/proxy-internal.cc | 98 +++++++++++++ src/proxy-internal.h | 67 +++++++++ src/stub-internal.cc | 139 ++++++++++++++++++ src/stub-internal.h | 81 ++++++++++ 9 files changed, 1066 insertions(+), 3 deletions(-) create mode 100644 src/fdbroker-internal.cc create mode 100644 src/fdbroker-internal.h create mode 100644 src/port-internal.cc create mode 100644 src/port-internal.h create mode 100644 src/proxy-internal.cc create mode 100644 src/proxy-internal.h create mode 100644 src/stub-internal.cc create mode 100644 src/stub-internal.h diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc new file mode 100644 index 0000000..8fce446 --- /dev/null +++ b/src/fdbroker-internal.cc @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include + +#include "fdbroker-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "RPC_PORT" + + +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" +#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" +#define RPC_PORT_OBJECT_PATH "/org/tizen/rpcport" +#define RPC_PORT_INTERFACE_PREFIX "org.tizen.rpcport._" + +namespace rpc_port { +namespace internal { + +FdBroker::DBusConnectionManager& FdBroker::DBusConnectionManager::GetInst() { + static DBusConnectionManager dm; + + if (dm.disposed_) { + dm.Init(); + } + + return dm; +} + +void FdBroker::DBusConnectionManager::Dispose() { + if (!disposed_) + Fini(); +} + +GDBusConnection* FdBroker::DBusConnectionManager::GetConnection() { + return gdbus_conn_; +} + +FdBroker::DBusConnectionManager::~DBusConnectionManager() { + if (!disposed_) + Fini(); +} + +void FdBroker::DBusConnectionManager::Init() { + GError* error = nullptr; + + gdbus_conn_ = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); + if (gdbus_conn_ == nullptr) { + if (error != nullptr) { + LOGE("Failed to get dbus [%s]", error->message); + g_error_free(error); + } + + return; + } + + disposed_ = false; +} + +void FdBroker::DBusConnectionManager::Fini() { + if (gdbus_conn_ != nullptr) { + g_object_unref(gdbus_conn_); + gdbus_conn_ = nullptr; + } + + disposed_ = true; +} + +FdBroker::SocketPair::SocketPair() { + socks_[SENDER] = 0; + socks_[RECEIVER] = 0; +} + +FdBroker::SocketPair::~SocketPair() { + if (socks_[SENDER] > 0) + close(socks_[SENDER]); + if (socks_[RECEIVER] > 0) + close(socks_[RECEIVER]); +} + +int FdBroker::SocketPair::Request() { + if (aul_request_message_port_socket_pair(socks_) != AUL_R_OK) { + LOGE("error create socket pair"); + return -1; + } + + return 0; +} + +int FdBroker::SocketPair::Get(Type t) const { + return socks_[t]; +} + +int FdBroker::SocketPair::Detach(Type t) { + int fd = socks_[t]; + + socks_[t] = 0; + return fd; +} + +FdBroker::FdList::FdList() { + fd_list_ = g_unix_fd_list_new(); +} + +FdBroker::FdList::~FdList() { + g_object_unref(fd_list_); +} + +int FdBroker::FdList::Add(int fd) { + GError *err = nullptr; + + g_unix_fd_list_append(fd_list_, fd, &err); + close(fd); + + if (err != NULL) { + LOGE("g_unix_fd_list_append [%s]", err->message); + g_error_free(err); + return -1; + } + + return 0; +} + +GUnixFDList* FdBroker::FdList::GetRaw() { + return fd_list_; +} + +FdBroker::~FdBroker() { + if (registration_id_ > 0) { + g_dbus_connection_unregister_object( + DBusConnectionManager::GetInst().GetConnection(), + registration_id_); + } +} + +std::string FdBroker::GetInterfaceName(const std::string& target_appid, + const std::string& port_name) { + std::string interface_name = RPC_PORT_INTERFACE_PREFIX; + + interface_name += target_appid; + interface_name += "_" + port_name; + + return interface_name; +} + +int FdBroker::Send(const std::string& target_appid, + const std::string& port_name) { + std::string interface_name = GetInterfaceName(target_appid, port_name); + GDBusMessage *msg; + GError *err = nullptr; + GVariant *body; + SocketPair sock_pair; + FdList fd_list; + char sender_appid[255]; + + if (aul_app_get_appid_bypid(getpid(), sender_appid, sizeof(sender_appid)) < 0) + return -1; + + if (sock_pair.Request() != 0) + return -1; + + if (fd_list.Add(sock_pair.Detach(SocketPair::RECEIVER)) != 0) + return -1; + + msg = g_dbus_message_new_method_call(interface_name.c_str(), + RPC_PORT_OBJECT_PATH, + interface_name.c_str(), "send_message"); + if (!msg) { + LOGE("Can't allocate new method call"); + return -1; + } + + body = g_variant_new("(s)", sender_appid); + g_dbus_message_set_unix_fd_list(msg, fd_list.GetRaw()); + g_dbus_message_set_body(msg, body); + g_dbus_connection_send_message(DBusConnectionManager::GetInst().GetConnection(), + msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, + nullptr, &err); + if (err != nullptr) { + LOGE("No reply. error = %s", err->message); + g_error_free(err); + g_object_unref(msg); + return -1; + } + + int fd = sock_pair.Detach(SocketPair::SENDER); + g_object_unref(msg); + + return fd; +} + +void FdBroker::ReceiveMessage(GVariant* parameters, + GDBusMethodInvocation* invocation) { + char* sender_appid = nullptr; + GDBusMessage* msg; + GUnixFDList* fd_list; + int fd_len; + int* returned_fds = nullptr; + + g_variant_get(parameters, "(&s)", &sender_appid); + + if (sender_appid == nullptr) { + LOGE("Invalid argument : sender_appid is NULL"); + return; + } + + msg = g_dbus_method_invocation_get_message(invocation); + fd_list = g_dbus_message_get_unix_fd_list(msg); + + if (fd_list == nullptr) + return; + + returned_fds = g_unix_fd_list_steal_fds(fd_list, &fd_len); + if (returned_fds == nullptr) { + LOGE("fail to get fds"); + return; + } + + listener_->OnFdReceived(sender_appid, returned_fds[0]); + free(returned_fds); +} + +void FdBroker::OnReceiveDbusMethod(GDBusConnection *conn, + const gchar *sender, const gchar *object_path, + const gchar *iface_name, const gchar *method_name, + GVariant *parameters, GDBusMethodInvocation *invocation, + gpointer user_data) { + FdBroker* broker = static_cast(user_data); + + broker->ReceiveMessage(parameters, invocation); + g_dbus_method_invocation_return_value(invocation, nullptr); +} + +int FdBroker::GetOwnerId(const std::string& interface_name) { + int owner_id = 0; + GError *error = NULL; + + GVariant* result = g_dbus_connection_call_sync( + DBusConnectionManager::GetInst().GetConnection(), + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName", + g_variant_new("(su)", interface_name.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE), + G_VARIANT_TYPE("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + &error); + + if (error) { + LOGE("RequestName fail : %s", error->message); + g_error_free(error); + return -1; + } + + if (result == nullptr) { + LOGE("fail to get name NULL"); + return -1; + } + + g_variant_get(result, "(u)", &owner_id); + if (owner_id == 0) { + LOGE("Acquiring the own name is failed"); + g_variant_unref(result); + return -1; + } + + LOGD("Acquiring the own name : %d", owner_id); + g_variant_unref(result); + + return owner_id; +} + +int FdBroker::RegisterDbusInterface(const std::string& port_name) { + static const GDBusInterfaceVTable interface_vtable = { + OnReceiveDbusMethod, + nullptr, + nullptr + }; + static const char introspection_prefix[] = + "" + " " + " " + " " + " " + " " + ""; + char appid[255]; + + if (aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)) < 0) + return -1; + + std::string interface_name = GetInterfaceName(appid, port_name); + + if (GetOwnerId(interface_name) < 0) { + LOGE("Failed to get owner id"); + return -1; + } + + std::string introspection_xml = introspection_prefix + + interface_name + + introspection_postfix; + + GDBusNodeInfo* introspection_data = g_dbus_node_info_new_for_xml( + introspection_xml.c_str(), nullptr); + if (!introspection_data) { + LOGE("g_dbus_node_info_new_for_xml() is failed."); + return -1; + } + + registration_id_ = g_dbus_connection_register_object( + DBusConnectionManager::GetInst().GetConnection(), + RPC_PORT_OBJECT_PATH, introspection_data->interfaces[0], + &interface_vtable, this, nullptr, nullptr); + + g_dbus_node_info_unref(introspection_data); + if (registration_id_ == 0) { + LOGE("Failed to g_dbus_connection_register_object"); + return -1; + } + + return 0; +} + +int FdBroker::Listen(IEventListener* ev, const std::string& port_name) { + if (listener_ != nullptr) { + LOGE("listener_ is not NULL"); + return -1; + } + + if (ev == nullptr) { + LOGE("ev is NULL"); + return -1; + } + + int ret = RegisterDbusInterface(port_name); + + if (ret != 0) { + LOGE("Failed to register dbus interface"); + return -1; + } + + listener_ = ev; + return 0; +} + +} // namespace internal +} // namespace rpc_port \ No newline at end of file diff --git a/src/fdbroker-internal.h b/src/fdbroker-internal.h new file mode 100644 index 0000000..9d2cb85 --- /dev/null +++ b/src/fdbroker-internal.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017 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 FDBROKER_INTERNAL_H_ +#define FDBROKER_INTERNAL_H_ + +#include +#include +#include +#include + +#include +#include + +namespace rpc_port { +namespace internal { + +class FdBroker { + public: + class IEventListener { + public: + virtual void OnFdReceived(const std::string& sender, int fd) = 0; + }; + + FdBroker() = default; + ~FdBroker(); + + static void Dispose() { + DBusConnectionManager::GetInst().Dispose(); + } + + int Send(const std::string& target_appid, const std::string& port_name); + int Listen(IEventListener* ev, const std::string& port_name); + + private: + class DBusConnectionManager { + public: + DBusConnectionManager(const DBusConnectionManager&) = delete; + DBusConnectionManager& operator = (const DBusConnectionManager&) = delete; + + static DBusConnectionManager& GetInst(); + void Dispose(); + GDBusConnection* GetConnection(); + + private: + DBusConnectionManager() = default; + ~DBusConnectionManager(); + + void Init(); + void Fini(); + + private: + bool disposed_ = true; + GDBusConnection* gdbus_conn_ = nullptr; + }; + + class SocketPair { + public: + enum Type { + SENDER = 0, + RECEIVER = 1 + }; + + SocketPair(); + ~SocketPair(); + + int Request(); + int Get(Type t) const; + int Detach(Type t); + + private: + int socks_[2]; + }; + + class FdList { + public: + FdList(); + ~FdList(); + + int Add(int fd); + GUnixFDList* GetRaw(); + + private: + GUnixFDList* fd_list_; + }; + + private: + static void OnReceiveDbusMethod(GDBusConnection *conn, const gchar *sender, + const gchar *object_path, + const gchar *iface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data); + int GetOwnerId(const std::string& interface_name); + int RegisterDbusInterface(const std::string& port_name); + void ReceiveMessage(GVariant* parameters, GDBusMethodInvocation* invocation); + std::string GetInterfaceName(const std::string& target_appid, + const std::string& port_name); + + private: + IEventListener* listener_ = nullptr; + int registration_id_ = 0; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // FDBROKER_INTERNAL_H_ diff --git a/src/parcel-internal.h b/src/parcel-internal.h index 86f8e52..c729a49 100644 --- a/src/parcel-internal.h +++ b/src/parcel-internal.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef __PARCEL_INTERNAL_H__ -#define __PARCEL_INTERNAL_H__ +#ifndef PARCEL_INTERNAL_H_ +#define PARCEL_INTERNAL_H_ #include @@ -78,4 +78,4 @@ class Parcel { } // namespace rpc_port -#endif // __PARCEL_INTERNAL_H__ \ No newline at end of file +#endif // PARCEL_INTERNAL_H_ \ No newline at end of file diff --git a/src/port-internal.cc b/src/port-internal.cc new file mode 100644 index 0000000..caa354c --- /dev/null +++ b/src/port-internal.cc @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +#include "port-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "RPC_PORT" + +#define MAX_RETRY_CNT 10 +#define SEND_TIMEOUT 500 + +namespace rpc_port { +namespace internal { + +Port::Port(int fd, const std::string& id) + : fd_(fd), id_(id) {} + +Port::~Port() { + close(fd_); +} + +int Port::Read(void* buf, unsigned int size) { + unsigned int left = size; + ssize_t nb; + int retry_cnt = 0; + const struct timespec TRY_SLEEP_TIME = { 0, 500 * 1000 * 1000 }; + int bytes_read = 0; + char* buffer = static_cast(buf); + + while (left && (retry_cnt < MAX_RETRY_CNT)) { + nb = read(fd_, buffer, left); + if (nb == 0) { + LOGE("read_socket: ...read EOF, socket closed %d: nb %d\n", fd_, nb); + return -1; + } else if (nb == -1) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + LOGE("read_socket: %d errno, sleep and retry ...", errno); + retry_cnt++; + nanosleep(&TRY_SLEEP_TIME, 0); + continue; + } + LOGE("read_socket: ...error fd %d: errno %d\n", fd_, errno); + return -1; + } + + left -= nb; + buffer += nb; + bytes_read += nb; + retry_cnt = 0; + } + + if (left != 0) { + LOGE("error fd %d: retry_cnt %d", fd_, retry_cnt); + return -1; + } + + return 0; +} + +int Port::Write(const void* buf, unsigned int size) { + unsigned int left = size; + ssize_t nb; + int retry_cnt = 0; + struct pollfd fds[1]; + int ret; + int bytes_write = 0; + const char* buffer = static_cast(buf); + + fds[0].fd = fd_; + fds[0].events = POLLOUT; + fds[0].revents = 0; + + ret = poll(fds, 1, SEND_TIMEOUT); + if (ret == 0) { + LOGE("write_socket: : fd %d poll timeout", fd_); + return -1; + } + + while (left && (retry_cnt < MAX_RETRY_CNT)) { + nb = write(fd_, buffer, left); + if (nb == -1) { + if (errno == EINTR) { + LOGE("write_socket: EINTR error continue ..."); + retry_cnt++; + continue; + } + + LOGE("write_socket: ...error fd %d: errno %d\n", fd_, errno); + return -1; + } + + left -= nb; + buffer += nb; + bytes_write += nb; + retry_cnt = 0; + } + + if (left != 0) { + LOGE("error fd %d: retry_cnt %d", fd_, retry_cnt); + return -1; + } + + return 0; +} + +} // namespace internal +} // namespace rpc_port \ No newline at end of file diff --git a/src/port-internal.h b/src/port-internal.h new file mode 100644 index 0000000..d612cb7 --- /dev/null +++ b/src/port-internal.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 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 PORT_INTERNAL_H_ +#define PORT_INTERNAL_H_ + +#include +#include + +namespace rpc_port { +namespace internal { + +class Port { + public: + Port(int fd, const std::string& id); + virtual ~Port(); + + int Read(void* buf, unsigned int size); + int Write(const void* buf, unsigned int size); + int GetFd() const { + return fd_; + } + + const std::string& GetId() const { + return id_; + } + + private: + int fd_; + std::string id_; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // PORT_INTERNAL_H_ diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc new file mode 100644 index 0000000..6cabd91 --- /dev/null +++ b/src/proxy-internal.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include + +#include "proxy-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "RPC_PORT" + +namespace rpc_port { +namespace internal { + +Proxy::~Proxy() { + if (src_id_ > 0) + g_source_remove(src_id_); + + if (gioc_ != nullptr) { + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + } +} + +gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, + gpointer data) { + Proxy* proxy = static_cast(data); + + proxy->listener_->OnDisconnected(proxy->target_appid_); + proxy->src_id_ = 0; + + return FALSE; +} + +int Proxy::Watch(int fd) { + char buf[1024]; + + gioc_ = g_io_channel_unix_new(fd); + if (!gioc_) { + LOGE("Error is %s\n", strerror_r(errno, buf, sizeof(buf))); + return -1; + } + + src_id_ = g_io_add_watch(gioc_, + (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL), + OnSocketDisconnected, this); + if (src_id_ == 0) { + LOGE("fail to add watch on socket"); + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + gioc_ = nullptr; + return -1; + } + + return 0; +} + +void Proxy::Connect(const std::string appid, const std::string& port_name, + IEventListener* ev) { + if (ev == nullptr || listener_ != nullptr) + return; + + listener_ = ev; + target_appid_ = appid; + int fd = fd_broker_.Send(appid, port_name); + + if (fd <= 0) { + listener_->OnRejected(appid); + listener_ = nullptr; + return; + } + + port_.reset(new Port(fd, port_name)); + listener_->OnConnected(appid, *port_); + Watch(fd); +} + +} // namespace internal +} // namespace rpc_port \ No newline at end of file diff --git a/src/proxy-internal.h b/src/proxy-internal.h new file mode 100644 index 0000000..caa683e --- /dev/null +++ b/src/proxy-internal.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017 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 PROXY_INTERNAL_H_ +#define PROXY_INTERNAL_H_ + +#include +#include +#include + +#include +#include + +#include "port-internal.h" +#include "fdbroker-internal.h" + +namespace rpc_port { +namespace internal { + +class Proxy { + public: + ~Proxy(); + + class IEventListener { + public: + virtual void OnConnected(const std::string& endpoint, Port& port) = 0; + virtual void OnDisconnected(const std::string& endpoint) = 0; + virtual void OnRejected(const std::string& endpoint) = 0; + }; + + void Connect(const std::string appid, const std::string& port_name, + IEventListener* ev); + std::shared_ptr GetPort() const { + return port_; + } + + private: + static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, + gpointer data); + int Watch(int fd); + + private: + std::shared_ptr port_; + IEventListener* listener_ = nullptr; + FdBroker fd_broker_; + std::string target_appid_; + GIOChannel* gioc_ = nullptr; + int src_id_ = 0; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // PROXY_INTERNAL_H_ diff --git a/src/stub-internal.cc b/src/stub-internal.cc new file mode 100644 index 0000000..109ae8d --- /dev/null +++ b/src/stub-internal.cc @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include + +#include "stub-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "RPC_PORT" + +namespace rpc_port { +namespace internal { + +Stub::Stub(const std::string& port_name) + : port_name_(port_name) {} + +Stub::~Stub() {} + +void Stub::Listen(IEventListener* ev) { + if (ev == nullptr) + return; + + listener_ = ev; + fd_broker_.Listen(this, port_name_); +} + +gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, + gpointer data) { + Stub* stub = static_cast(data); + int fd = g_io_channel_unix_get_fd(gio); + + for (auto& p : stub->ports_) { + if (p->GetFd() == fd) { + stub->listener_->OnReceived(p->GetId(), *p); + break; + } + } + + return TRUE; +} + +gboolean Stub::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, + gpointer data) { + Stub* stub = static_cast(data); + int fd = g_io_channel_unix_get_fd(gio); + + for (auto& p : stub->ports_) { + if (p->GetFd() == fd) { + stub->listener_->OnDisconnected(p->GetId()); + stub->ports_.remove(p); + break; + } + } + + return FALSE; +} + +void Stub::OnFdReceived(const std::string& sender, int fd) { + ports_.emplace_back(new AcceptedPort(this, fd, sender)); + listener_->OnConnected(sender); +} + +Stub::AcceptedPort::AcceptedPort(Stub* parent, int fd, const std::string& id) + : Port(fd, id), parent_(parent) { + Watch(); +} + +Stub::AcceptedPort::~AcceptedPort() { + if (disconn_src_ > 0) + g_source_remove(disconn_src_); + + if (src_ > 0) + g_source_remove(src_); + + if (gioc_ != nullptr) { + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + } +} + +int Stub::AcceptedPort::Watch() { + char buf[1024]; + int fd = GetFd(); + + gioc_ = g_io_channel_unix_new(fd); + if (!gioc_) { + LOGE("Error is %s", strerror_r(errno, buf, sizeof(buf))); + return -1; + } + + disconn_src_= g_io_add_watch(gioc_, + (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL), + Stub::OnSocketDisconnected, parent_); + if (disconn_src_ == 0) { + LOGE("fail to add watch on socket"); + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + gioc_ = nullptr; + return -1; + } + + src_= g_io_add_watch(gioc_, + (GIOCondition)(G_IO_IN), + Stub::OnDataReceived, parent_); + if (src_ == 0) { + LOGE("fail to add watch on socket"); + g_source_remove(disconn_src_); + disconn_src_ = 0; + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + gioc_ = nullptr; + return -1; + } + + return 0; +} + +} // namespace internal +} // namespace rpc_port \ No newline at end of file diff --git a/src/stub-internal.h b/src/stub-internal.h new file mode 100644 index 0000000..8c474ac --- /dev/null +++ b/src/stub-internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017 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 STUB_INTERNAL_H_ +#define STUB_INTERNAL_H_ + +#include +#include +#include + +#include +#include +#include + +#include "port-internal.h" +#include "fdbroker-internal.h" + +namespace rpc_port { +namespace internal { + +class Stub : private FdBroker::IEventListener { + public: + class IEventListener { + public: + virtual void OnConnected(const std::string& sender) = 0; + virtual void OnDisconnected(const std::string& sender) = 0; + virtual void OnReceived(const std::string& sender, Port& port) = 0; + }; + + Stub(const std::string& port_name); + ~Stub(); + + void Listen(IEventListener* ev); + + private: + class AcceptedPort : public Port { + public: + AcceptedPort(Stub* parent, int fd, const std::string& id); + virtual ~AcceptedPort(); + + private: + int Watch(); + + private: + GIOChannel* gioc_ = nullptr; + int disconn_src_ = 0; + int src_ = 0; + Stub* parent_; + }; + + static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond, + gpointer data); + static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, + gpointer data); + + void OnFdReceived(const std::string& sender, int fd) override; + + private: + std::list> ports_; + IEventListener* listener_; + FdBroker fd_broker_; + std::string port_name_; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // STUB_INTERNAL_H_ -- 2.7.4 From a24269d0f96d8956cca63965e1578ac42c5ad53b Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Mon, 4 Dec 2017 16:59:41 +0900 Subject: [PATCH 08/16] Implement rpc-port APIs Change-Id: I20443cce9b0396bd9fdcd46f99f24f1bf394a679 Signed-off-by: Junghoon Park --- include/rpc-port-internal.h | 36 +++++++ include/rpc-port.h | 4 +- src/fdbroker-internal.cc | 66 +++++++++++- src/fdbroker-internal.h | 27 ++++- src/proxy-internal.cc | 4 + src/proxy-internal.h | 8 +- src/rpc-port.cc | 226 ++++++++++++++++++++++++++++++++++++-- src/stub-internal.cc | 4 +- src/stub-internal.h | 4 +- unit_tests/src/rpc_port_test.cc | 232 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 589 insertions(+), 22 deletions(-) create mode 100644 include/rpc-port-internal.h create mode 100644 unit_tests/src/rpc_port_test.cc diff --git a/include/rpc-port-internal.h b/include/rpc-port-internal.h new file mode 100644 index 0000000..1f7db12 --- /dev/null +++ b/include/rpc-port-internal.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __RPC_PORT_INTERNAL_INCLUDE_H__ +#define __RPC_PORT_INTERNAL_INCLUDE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int rpc_port_proxy_create_mockup(rpc_port_proxy_h *h); +int rpc_port_stub_create_mockup(rpc_port_stub_h *h, const char *port_name); + +#ifdef __cplusplus +} +#endif + +#endif /* __RPC_PORT_INTERNAL_INCLUDE_H__ */ + + + diff --git a/include/rpc-port.h b/include/rpc-port.h index b66e677..efdae49 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -23,8 +23,6 @@ extern "C" { /* common */ typedef void *rpc_port_h; -int rpc_port_open(int fd, rpc_port_h *h); -int rpc_port_close(rpc_port_h h); int rpc_port_read(rpc_port_h h, void *buf, unsigned int size); int rpc_port_write(rpc_port_h h, const void *buf, unsigned int size); @@ -63,7 +61,7 @@ int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void *data); int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, rpc_port_stub_disconnected_event_cb cb, void *data); -int rpc_port_stub_add_recevied_event_cb(rpc_port_stub_h h, +int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h, rpc_port_stub_received_event_cb cb, void *data); #ifdef __cplusplus diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc index 8fce446..b65bdb6 100644 --- a/src/fdbroker-internal.cc +++ b/src/fdbroker-internal.cc @@ -18,6 +18,8 @@ #define _GNU_SOURCE #endif +#include +#include #include #include @@ -88,7 +90,36 @@ void FdBroker::DBusConnectionManager::Fini() { disposed_ = true; } -FdBroker::SocketPair::SocketPair() { +FdBroker::DBusMock& FdBroker::DBusMock::GetInst() { + static DBusMock mock; + + return mock; +} + +int FdBroker::DBusMock::Send(const std::string& sender, + const std::string& port, int fd) { + if (ports_.find(port) == ports_.end()) + return -1; + + ports_[port]->OnFdReceived(sender, fd); + return 0; +} + +int FdBroker::DBusMock::AddListener(const std::string& port, + FdBroker::IEventListener* listener) { + if (ports_.find(port) != ports_.end()) + return -1; + + ports_[port] = listener; + return 0; +} + +void FdBroker::DBusMock::Dispose() { + ports_.clear(); +} + +FdBroker::SocketPair::SocketPair(bool mock) + : mock_(mock) { socks_[SENDER] = 0; socks_[RECEIVER] = 0; } @@ -101,6 +132,10 @@ FdBroker::SocketPair::~SocketPair() { } int FdBroker::SocketPair::Request() { + if (mock_) { + return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socks_); + } + if (aul_request_message_port_socket_pair(socks_) != AUL_R_OK) { LOGE("error create socket pair"); return -1; @@ -153,6 +188,10 @@ FdBroker::~FdBroker() { DBusConnectionManager::GetInst().GetConnection(), registration_id_); } + + if (mock_) { + DBusMock::GetInst().Dispose(); + } } std::string FdBroker::GetInterfaceName(const std::string& target_appid, @@ -171,16 +210,28 @@ int FdBroker::Send(const std::string& target_appid, GDBusMessage *msg; GError *err = nullptr; GVariant *body; - SocketPair sock_pair; + SocketPair sock_pair(mock_); FdList fd_list; char sender_appid[255]; - if (aul_app_get_appid_bypid(getpid(), sender_appid, sizeof(sender_appid)) < 0) + if (!mock_ && aul_app_get_appid_bypid(getpid(), + sender_appid, sizeof(sender_appid)) < 0) { + LOGE("Can't get appid"); return -1; + } if (sock_pair.Request() != 0) return -1; + if (mock_) { + int ret = DBusMock::GetInst().Send("TestApp", port_name, + sock_pair.Detach(SocketPair::RECEIVER)); + if (ret < 0) + return ret; + + return sock_pair.Detach(SocketPair::SENDER); + } + if (fd_list.Add(sock_pair.Detach(SocketPair::RECEIVER)) != 0) return -1; @@ -358,6 +409,15 @@ int FdBroker::Listen(IEventListener* ev, const std::string& port_name) { return -1; } + if (mock_) { + int ret = DBusMock::GetInst().AddListener(port_name, ev); + + if (ret < 0) + return ret; + + return 0; + } + int ret = RegisterDbusInterface(port_name); if (ret != 0) { diff --git a/src/fdbroker-internal.h b/src/fdbroker-internal.h index 9d2cb85..8ae7451 100644 --- a/src/fdbroker-internal.h +++ b/src/fdbroker-internal.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace rpc_port { @@ -35,7 +36,7 @@ class FdBroker { virtual void OnFdReceived(const std::string& sender, int fd) = 0; }; - FdBroker() = default; + FdBroker(bool mock = false) : mock_(mock) {} ~FdBroker(); static void Dispose() { @@ -67,6 +68,25 @@ class FdBroker { GDBusConnection* gdbus_conn_ = nullptr; }; + class DBusMock { + public: + DBusMock(const DBusMock&) = delete; + DBusMock& operator = (const DBusMock&) = delete; + + static DBusMock& GetInst(); + int Send(const std::string& sender, const std::string& port, int fd); + int AddListener(const std::string& port, + FdBroker::IEventListener* listener); + void Dispose(); + + private: + DBusMock() = default; + ~DBusMock() = default; + + private: + std::map ports_; + }; + class SocketPair { public: enum Type { @@ -74,15 +94,17 @@ class FdBroker { RECEIVER = 1 }; - SocketPair(); + SocketPair(bool mock = false); ~SocketPair(); int Request(); + void RequestMock(); int Get(Type t) const; int Detach(Type t); private: int socks_[2]; + bool mock_; }; class FdList { @@ -114,6 +136,7 @@ class FdBroker { private: IEventListener* listener_ = nullptr; int registration_id_ = 0; + bool mock_; }; } // namespace internal diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index 6cabd91..3929df4 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -31,6 +31,9 @@ namespace rpc_port { namespace internal { +Proxy::Proxy(bool mock) + : fd_broker_(mock) {} + Proxy::~Proxy() { if (src_id_ > 0) g_source_remove(src_id_); @@ -81,6 +84,7 @@ void Proxy::Connect(const std::string appid, const std::string& port_name, listener_ = ev; target_appid_ = appid; + port_name_ = port_name; int fd = fd_broker_.Send(appid, port_name); if (fd <= 0) { diff --git a/src/proxy-internal.h b/src/proxy-internal.h index caa683e..2cb2c05 100644 --- a/src/proxy-internal.h +++ b/src/proxy-internal.h @@ -32,7 +32,8 @@ namespace internal { class Proxy { public: - ~Proxy(); + Proxy(bool mock = false); + virtual ~Proxy(); class IEventListener { public: @@ -47,12 +48,17 @@ class Proxy { return port_; } + const std::string& GetPortName() { + return port_name_; + } + private: static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, gpointer data); int Watch(int fd); private: + std::string port_name_; std::shared_ptr port_; IEventListener* listener_ = nullptr; FdBroker fd_broker_; diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 4292359..a0372fa 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -17,77 +17,285 @@ #include #include "rpc-port.h" +#include "port-internal.h" +#include "proxy-internal.h" +#include "stub-internal.h" #undef RPC_API #define RPC_API extern "C" __attribute__((visibility("default"))) -RPC_API int rpc_port_open(int fd, rpc_port_h* h) { - return 0; -} +namespace { +using namespace rpc_port::internal; -RPC_API int rpc_port_close(rpc_port_h h) { - return 0; -} +template +class Event { + public: + Event(T cb, void* user_data) + : cb_(cb), user_data_(user_data) {} + + T cb_; + void* user_data_; +}; + +class ProxyExt : public Proxy, public Proxy::IEventListener { + public: + ProxyExt(bool mock = false) : Proxy(mock) {} + virtual ~ProxyExt() = default; + + void AddConnectedEventListener(rpc_port_proxy_connected_event_cb cb, + void* user_data) { + connected_events_.emplace_back( + new Event(cb, user_data)); + } + + void AddDisconnectedEventListener(rpc_port_proxy_disconnected_event_cb cb, + void* user_data) { + disconnected_events_.emplace_back( + new Event(cb, user_data)); + } + + void AddRejectedEventListener(rpc_port_proxy_rejected_event_cb cb, + void* user_data) { + rejected_events_.emplace_back( + new Event(cb, user_data)); + } + + void OnConnected(const std::string& endpoint, Port& port) override { + for (auto& ev : connected_events_) { + ev->cb_(endpoint.c_str(), GetPortName().c_str(), &port, + ev->user_data_); + } + } + + void OnDisconnected(const std::string& endpoint) override { + for (auto& ev : disconnected_events_) { + ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_); + } + } + + void OnRejected(const std::string& endpoint) override { + for (auto& ev : rejected_events_) { + ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_); + } + } + + private: + std::list>> + connected_events_; + std::list>> + disconnected_events_; + std::list>> + rejected_events_; +}; + +class StubExt : public Stub, public Stub::IEventListener { + public: + StubExt(const std::string& port, bool mock = false) : Stub(port, mock) {} + virtual ~StubExt() = default; + + void AddConnectedEventListener(rpc_port_stub_connected_event_cb cb, + void* user_data) { + connected_events_.emplace_back( + new Event(cb, user_data)); + } + + void AddDisconnectedEventListener(rpc_port_stub_disconnected_event_cb cb, + void* user_data) { + disconnected_events_.emplace_back( + new Event(cb, user_data)); + } + + void AddReceivedEventListener(rpc_port_stub_received_event_cb cb, + void* user_data) { + received_events_.emplace_back( + new Event(cb, user_data)); + } + + void OnConnected(const std::string& sender) override { + for (auto& ev : connected_events_) { + ev->cb_(sender.c_str(), ev->user_data_); + } + } + + void OnDisconnected(const std::string& sender) override { + for (auto& ev : disconnected_events_) { + ev->cb_(sender.c_str(), ev->user_data_); + } + } + + void OnReceived(const std::string& sender, Port& port) override { + for (auto& ev : received_events_) { + ev->cb_(sender.c_str(), &port, ev->user_data_); + } + } + + private: + std::list>> + connected_events_; + std::list>> + disconnected_events_; + std::list>> + received_events_; +}; + +} // namespace RPC_API int rpc_port_read(rpc_port_h h, void* buf, unsigned int size) { - return 0; + if (h == nullptr) + return -1; + + auto port = static_cast(h); + + return port->Read(buf, size); } RPC_API int rpc_port_write(rpc_port_h h, const void* buf, unsigned int size) { - return 0; + if (h == nullptr) + return -1; + + auto port = static_cast(h); + + return port->Write(buf, size); } RPC_API int rpc_port_proxy_create(rpc_port_proxy_h* h) { + auto p = new ::ProxyExt(); + + *h = p; + return 0; +} + +RPC_API int rpc_port_proxy_create_mockup(rpc_port_proxy_h* h) { + auto p = new ::ProxyExt(true); + + *h = p; return 0; } RPC_API int rpc_port_proxy_destroy(rpc_port_proxy_h h) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + delete p; return 0; } RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char* appid, const char* port) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + p->Connect(appid, port, p); return 0; } RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_connected_event_cb cb, void *data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + p->AddConnectedEventListener(cb, data); return 0; } RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_disconnected_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + p->AddDisconnectedEventListener(cb, data); return 0; } RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_rejected_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + p->AddRejectedEventListener(cb, data); return 0; } RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) { + if (h == nullptr) + return -1; + + auto p = new ::StubExt(port_name); + + *h = p; + return 0; +} + +RPC_API int rpc_port_stub_create_mockup(rpc_port_stub_h* h, + const char* port_name) { + if (h == nullptr) + return -1; + + auto p = new ::StubExt(port_name, true); + + *h = p; return 0; } RPC_API int rpc_port_stub_destroy(rpc_port_stub_h h) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + + delete p; return 0; } RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + + p->Listen(p); return 0; } RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + + p->AddConnectedEventListener(cb, data); return 0; } RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, rpc_port_stub_disconnected_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + + p->AddDisconnectedEventListener(cb, data); return 0; } -RPC_API int rpc_port_stub_add_recevied_event_cb(rpc_port_stub_h h, +RPC_API int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h, rpc_port_stub_received_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + + p->AddReceivedEventListener(cb, data); return 0; } diff --git a/src/stub-internal.cc b/src/stub-internal.cc index 109ae8d..b4e7728 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -31,8 +31,8 @@ namespace rpc_port { namespace internal { -Stub::Stub(const std::string& port_name) - : port_name_(port_name) {} +Stub::Stub(const std::string& port_name, bool mock) + : fd_broker_(mock), port_name_(port_name) {} Stub::~Stub() {} diff --git a/src/stub-internal.h b/src/stub-internal.h index 8c474ac..eec8293 100644 --- a/src/stub-internal.h +++ b/src/stub-internal.h @@ -40,8 +40,8 @@ class Stub : private FdBroker::IEventListener { virtual void OnReceived(const std::string& sender, Port& port) = 0; }; - Stub(const std::string& port_name); - ~Stub(); + Stub(const std::string& port_name, bool mock = false); + virtual ~Stub(); void Listen(IEventListener* ev); diff --git a/unit_tests/src/rpc_port_test.cc b/unit_tests/src/rpc_port_test.cc new file mode 100644 index 0000000..92b86dd --- /dev/null +++ b/unit_tests/src/rpc_port_test.cc @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "rpc-port-internal.h" + +using namespace std; +using ::testing::AtLeast; + +class RpcPortBase : public ::testing::Test { + public: + virtual void SetUp() { + mainloop_ = g_main_loop_new(nullptr, FALSE); + + int ret = rpc_port_proxy_create_mockup(&proxy_handle_); + + ASSERT_NE(proxy_handle_, nullptr); + ASSERT_EQ(ret, 0); + + ret = rpc_port_stub_create_mockup(&stub_handle_, "test_port"); + ASSERT_NE(stub_handle_, nullptr); + ASSERT_EQ(ret, 0); + } + + virtual void TearDown() { + if (proxy_handle_) { + int ret = rpc_port_proxy_destroy(proxy_handle_); + ASSERT_EQ(ret, 0); + } + + if (stub_handle_) { + int ret = rpc_port_stub_destroy(stub_handle_); + ASSERT_EQ(ret, 0); + } + + g_main_loop_unref(mainloop_); + mainloop_ = nullptr; + } + + void RunMainLoop() { + g_main_loop_run(mainloop_); + } + + void Finish() { + g_main_loop_quit(mainloop_); + } + + void KillStub() { + int ret = rpc_port_stub_destroy(stub_handle_); + ASSERT_EQ(ret, 0); + stub_handle_ = nullptr; + } + + void KillProxy() { + int ret = rpc_port_proxy_destroy(proxy_handle_); + ASSERT_EQ(ret, 0); + proxy_handle_ = nullptr; + } + + rpc_port_proxy_h proxy_handle_; + rpc_port_stub_h stub_handle_; + bool touch_proxy_connected_event_cb_ = false; + bool touch_stub_connected_event_cb_ = false; + bool touch_proxy_rejected_event_cb_ = false; + + private: + static GMainLoop* mainloop_; + +}; + +GMainLoop* RpcPortBase::mainloop_ = nullptr; + +class RpcPortConnection : public RpcPortBase { + public: + virtual void SetUp() { + RpcPortBase::SetUp(); + StubSetup(); + ProxySetup(); + } + + virtual void TearDown() { + RpcPortBase::TearDown(); + } + + void StubSetup() { + int ret = rpc_port_stub_add_received_event_cb(stub_handle_, + [](const char* sender, rpc_port_h port, void *data) { + RpcPortConnection* p = static_cast(data); + p->stub_port_ = port; + p->Finish(); + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_stub_add_disconnected_event_cb(stub_handle_, + [](const char* sender, void *data) { + RpcPortConnection* p = static_cast(data); + p->touch_stub_disconnected_event_cb_ = true; + p->Finish(); + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_stub_listen(stub_handle_); + ASSERT_EQ(ret, 0); + } + + void ProxySetup() { + int ret = rpc_port_proxy_add_connected_event_cb(proxy_handle_, + [](const char *ep, const char *port_name, rpc_port_h port, void *data) { + RpcPortConnection* p = static_cast(data); + p->proxy_port_ = port; + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_add_disconnected_event_cb(proxy_handle_, + [](const char *ep, const char *port_name, void *data) { + RpcPortConnection* p = static_cast(data); + p->touch_proxy_disconnected_event_cb_ = true; + p->Finish(); + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_connect(proxy_handle_, "TestApp", "test_port"); + ASSERT_EQ(ret, 0); + } + + rpc_port_h proxy_port_ = nullptr; + rpc_port_h stub_port_ = nullptr; + bool touch_proxy_disconnected_event_cb_ = false; + bool touch_stub_disconnected_event_cb_ = false; +}; + +TEST_F(RpcPortBase, rpc_port_event_connect) { + int ret = rpc_port_stub_add_connected_event_cb(stub_handle_, + [](const char *sender, void *data) { + RpcPortBase* p = static_cast(data); + + p->touch_stub_connected_event_cb_ = true; + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_stub_listen(stub_handle_); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_add_connected_event_cb(proxy_handle_, + [](const char *ep, const char *port_name, rpc_port_h port, void *data) { + RpcPortBase* p = static_cast(data); + + p->touch_proxy_connected_event_cb_ = true; + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_connect(proxy_handle_, "TestApp", "test_port"); + ASSERT_EQ(ret, 0); + + ASSERT_TRUE(touch_proxy_connected_event_cb_); + ASSERT_TRUE(touch_stub_connected_event_cb_); +} + +TEST_F(RpcPortBase, rpc_port_proxy_event_reject) { + int ret = rpc_port_stub_listen(stub_handle_); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_add_rejected_event_cb(proxy_handle_, + [](const char *ep, const char *port_name, void *data) { + RpcPortBase* p = static_cast(data); + + p->touch_proxy_rejected_event_cb_ = true; + }, this); + ASSERT_EQ(ret, 0); + + ret = rpc_port_proxy_connect(proxy_handle_, "TestApp", "wrong_port"); + ASSERT_EQ(ret, 0); + + ASSERT_TRUE(touch_proxy_rejected_event_cb_); +} + +TEST_F(RpcPortConnection, rpc_port_read_write) { + char buf[] = "test message"; + char res[] = "OK"; + char r_buf[256]; + + ASSERT_NE(proxy_port_, nullptr); + int ret = rpc_port_write(proxy_port_, buf, sizeof(buf)); + ASSERT_EQ(ret, 0); + + RunMainLoop(); + ASSERT_NE(stub_port_, nullptr); + + ret = rpc_port_read(stub_port_, r_buf, sizeof(buf)); + ASSERT_EQ(ret, 0); + ASSERT_STREQ(buf, r_buf); + + ret = rpc_port_write(stub_port_, res, sizeof(res)); + ASSERT_EQ(ret, 0); + + ret = rpc_port_read(proxy_port_, r_buf, sizeof(res)); + ASSERT_EQ(ret, 0); + ASSERT_STREQ("OK", r_buf); +} + +TEST_F(RpcPortConnection, rpc_port_proxy_disconnected) { + KillStub(); + RunMainLoop(); + + ASSERT_TRUE(touch_proxy_disconnected_event_cb_); +} + +TEST_F(RpcPortConnection, rpc_port_stub_disconnected) { + KillProxy(); + RunMainLoop(); + + ASSERT_TRUE(touch_stub_disconnected_event_cb_); +} -- 2.7.4 From f148d094877275d641ff458097b402f14a1fa273 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Mon, 11 Dec 2017 11:39:34 +0900 Subject: [PATCH 09/16] Convert d-bus interface name to hexa string - Special letters such as '-' and '+' are not allowed as d-bus interface name Change-Id: I5c74bdef4321e83ed8e13410fe4b9a19b8c69d1e Signed-off-by: Junghoon Park --- CMakeLists.txt | 2 +- packaging/rpc-port.spec | 1 - src/fdbroker-internal.cc | 12 ++++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c183bc..a9527d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/src ) -SET(${this_target}_requires "dlog bundle glib-2.0 gio-2.0 aul openssl capi-base-common pkgmgr-info gio-unix-2.0") +SET(${this_target}_requires "dlog bundle glib-2.0 gio-2.0 aul capi-base-common pkgmgr-info gio-unix-2.0") INCLUDE(FindPkgConfig) pkg_check_modules(${this_target} REQUIRED ${${this_target}_requires}) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 18b8126..282fc9d 100755 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -13,7 +13,6 @@ BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) -BuildRequires: pkgconfig(openssl) BuildRequires: pkgconfig(gmock) Requires(post): /sbin/ldconfig diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc index b65bdb6..77ecf6f 100644 --- a/src/fdbroker-internal.cc +++ b/src/fdbroker-internal.cc @@ -196,12 +196,16 @@ FdBroker::~FdBroker() { std::string FdBroker::GetInterfaceName(const std::string& target_appid, const std::string& port_name) { - std::string interface_name = RPC_PORT_INTERFACE_PREFIX; + std::string interface_name = target_appid + "_" + port_name; + char c_buf[interface_name.length() * 2 + 1] = {0}; + char* temp = &c_buf[0]; - interface_name += target_appid; - interface_name += "_" + port_name; + for (int index = 0; index < interface_name.length(); index++) { + snprintf(temp, 3, "%02x", interface_name[index]); + temp += 2; + } - return interface_name; + return RPC_PORT_INTERFACE_PREFIX + std::string(c_buf); } int FdBroker::Send(const std::string& target_appid, -- 2.7.4 From 706a2d444b04a2680f8a16dc2d610c3b54129b60 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Tue, 12 Dec 2017 14:47:24 +0900 Subject: [PATCH 10/16] Change return type to handle exceptions Change-Id: Ibb2324bcc52f7215000c731cf7f17d00615e064e Signed-off-by: Junghoon Park --- include/rpc-port.h | 2 +- src/rpc-port.cc | 8 ++++++-- src/stub-internal.cc | 9 ++++++++- src/stub-internal.h | 2 +- unit_tests/src/rpc_port_test.cc | 3 ++- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/rpc-port.h b/include/rpc-port.h index efdae49..c20f07d 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -52,7 +52,7 @@ typedef void (*rpc_port_stub_connected_event_cb)(const char *sender, void *data); typedef void (*rpc_port_stub_disconnected_event_cb)(const char *sender, void *data); -typedef void (*rpc_port_stub_received_event_cb)(const char *sender, +typedef int (*rpc_port_stub_received_event_cb)(const char *sender, rpc_port_h port, void *data); int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name); int rpc_port_stub_destroy(rpc_port_stub_h h); diff --git a/src/rpc-port.cc b/src/rpc-port.cc index a0372fa..76db22f 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -123,10 +123,14 @@ class StubExt : public Stub, public Stub::IEventListener { } } - void OnReceived(const std::string& sender, Port& port) override { + int OnReceived(const std::string& sender, Port& port) override { for (auto& ev : received_events_) { - ev->cb_(sender.c_str(), &port, ev->user_data_); + int ret = ev->cb_(sender.c_str(), &port, ev->user_data_); + if (ret != 0) + return -1; } + + return 0; } private: diff --git a/src/stub-internal.cc b/src/stub-internal.cc index b4e7728..07c8497 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -51,7 +51,14 @@ gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, for (auto& p : stub->ports_) { if (p->GetFd() == fd) { - stub->listener_->OnReceived(p->GetId(), *p); + int ret = stub->listener_->OnReceived(p->GetId(), *p); + + if (ret != 0) { + stub->listener_->OnDisconnected(p->GetId()); + stub->ports_.remove(p); + return FALSE; + } + break; } } diff --git a/src/stub-internal.h b/src/stub-internal.h index eec8293..b6d8726 100644 --- a/src/stub-internal.h +++ b/src/stub-internal.h @@ -37,7 +37,7 @@ class Stub : private FdBroker::IEventListener { public: virtual void OnConnected(const std::string& sender) = 0; virtual void OnDisconnected(const std::string& sender) = 0; - virtual void OnReceived(const std::string& sender, Port& port) = 0; + virtual int OnReceived(const std::string& sender, Port& port) = 0; }; Stub(const std::string& port_name, bool mock = false); diff --git a/unit_tests/src/rpc_port_test.cc b/unit_tests/src/rpc_port_test.cc index 92b86dd..b1002b2 100644 --- a/unit_tests/src/rpc_port_test.cc +++ b/unit_tests/src/rpc_port_test.cc @@ -103,10 +103,11 @@ class RpcPortConnection : public RpcPortBase { void StubSetup() { int ret = rpc_port_stub_add_received_event_cb(stub_handle_, - [](const char* sender, rpc_port_h port, void *data) { + [](const char* sender, rpc_port_h port, void *data) -> int { RpcPortConnection* p = static_cast(data); p->stub_port_ = port; p->Finish(); + return 0; }, this); ASSERT_EQ(ret, 0); -- 2.7.4 From d4dd21b80718913ff5ad9db0458a569263b01ece Mon Sep 17 00:00:00 2001 From: Inkyun Kil Date: Tue, 9 Jan 2018 13:21:39 +0900 Subject: [PATCH 11/16] Add AccessController Class Change-Id: I787024d9195cf59ec4bd613f4815d004d3045e59 Signed-off-by: Inkyun Kil --- CMakeLists.txt | 2 +- include/rpc-port.h | 1 + packaging/rpc-port.spec | 2 + src/ac-internal.cc | 120 ++++++++++++++++++++++++++++++++++++++++ src/ac-internal.h | 64 +++++++++++++++++++++ src/fdbroker-internal.cc | 47 +++++++++++++--- src/fdbroker-internal.h | 4 ++ src/rpc-port.cc | 10 ++++ src/stub-internal.cc | 7 ++- src/stub-internal.h | 1 + unit_tests/src/rpc_port_test.cc | 4 ++ 11 files changed, 252 insertions(+), 10 deletions(-) create mode 100644 src/ac-internal.cc create mode 100644 src/ac-internal.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a9527d3..d787267 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/src ) -SET(${this_target}_requires "dlog bundle glib-2.0 gio-2.0 aul capi-base-common pkgmgr-info gio-unix-2.0") +SET(${this_target}_requires "dlog bundle glib-2.0 gio-2.0 aul capi-base-common pkgmgr-info gio-unix-2.0 cynara-client cynara-creds-gdbus") INCLUDE(FindPkgConfig) pkg_check_modules(${this_target} REQUIRED ${${this_target}_requires}) diff --git a/include/rpc-port.h b/include/rpc-port.h index c20f07d..70ee743 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -57,6 +57,7 @@ typedef int (*rpc_port_stub_received_event_cb)(const char *sender, int rpc_port_stub_create(rpc_port_stub_h *h, const char *port_name); int rpc_port_stub_destroy(rpc_port_stub_h h); int rpc_port_stub_listen(rpc_port_stub_h h); +int rpc_port_stub_add_privilege(rpc_port_stub_h h, const char *privilege); int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void *data); int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index 282fc9d..e449e27 100755 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -14,6 +14,8 @@ BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(gmock) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-creds-gdbus) Requires(post): /sbin/ldconfig Requires(post): coreutils diff --git a/src/ac-internal.cc b/src/ac-internal.cc new file mode 100644 index 0000000..7ce273c --- /dev/null +++ b/src/ac-internal.cc @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include + +#include "ac-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "RPC_PORT" + +namespace rpc_port { +namespace internal { + +AccessController::~AccessController() {} + +void AccessController::AddPrivilege(const std::string& privilege) { + privileges_.push_back(privilege); +} + +int AccessController::CheckPrivilege(GDBusConnection *connection, const char* sender_appid) { + Cynara c; + + if (c.FetchCredsFromDBus(connection, sender_appid) != 0 ) + return -1; + + for (auto& privilege : privileges_) { + if (c.Check(privilege) != 0) { + return -1; + } + } + + return 0; +} + +int AccessController::SetCache(const std::string& sender) { + return -1; +} + +AccessController::Cynara::Cynara() { + cynara_ = nullptr; + client_ = nullptr; + user_ = nullptr; + + if (cynara_initialize(&cynara_, NULL) != CYNARA_API_SUCCESS) { + LOGE("cynara_initialize() is failed"); + } +} + +AccessController::Cynara::~Cynara() { + if (client_) + free(client_); + if (user_) + free(user_); + if (cynara_) + cynara_finish(cynara_); +} + +int AccessController::Cynara::FetchCredsFromDBus(GDBusConnection *connection, const char *sender_appid) { + int ret; + + if (client_) { + free(client_); + client_ = nullptr; + } + + if (user_) { + free(user_); + user_ = nullptr; + } + + ret = cynara_creds_gdbus_get_user(connection, sender_appid, USER_METHOD_DEFAULT, &user_); + if (ret != CYNARA_API_SUCCESS) { + LOGE("cynara_creds_gdbus_get_user() is failed : %d", ret); + return -1; + } + + ret = cynara_creds_gdbus_get_client(connection, sender_appid, CLIENT_METHOD_DEFAULT, &client_); + if (ret != CYNARA_API_SUCCESS) { + LOGE("cynara_creds_gdbus_get_client() is failed : %d", ret); + return -1; + } + + LOGD("cred client : %s, cred user : %s", client_, user_); + return 0; +} + +int AccessController::Cynara::Check(const std::string& privilege) { + LOGD("check %s", privilege.c_str()); + if (cynara_check(cynara_, client_, "", user_, privilege.c_str()) != CYNARA_API_ACCESS_ALLOWED) { + LOGE("cynara_check() is failed : %s", privilege.c_str()); + return -1; + } + + return 0; +} + +} // namespace internal +} // namespace rpc_port diff --git a/src/ac-internal.h b/src/ac-internal.h new file mode 100644 index 0000000..1948ff0 --- /dev/null +++ b/src/ac-internal.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 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 AC_INTERNAL_H_ +#define AC_INTERNAL_H_ + +#include +#include +#include +#include + +#include +#include +#include + +namespace rpc_port { +namespace internal { + +class AccessController { + public: + virtual ~AccessController(); + + void AddPrivilege(const std::string& privilege); + int CheckPrivilege(GDBusConnection *connection, const char* sender_appid); + + private: + int SetCache(const std::string& sender); + + class Cynara { + public: + Cynara(); + ~Cynara(); + + int FetchCredsFromDBus(GDBusConnection *connection, const char *sender_appid); + int Check(const std::string& privilege); + + private: + cynara *cynara_; + char *client_; + char *user_; + }; + + private: + std::vector privileges_; + std::map cache_; +}; + +} // namespace internal +} // namespace rpc_port + +#endif // AC_INTERNAL_H_ diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc index 77ecf6f..26c08f3 100644 --- a/src/fdbroker-internal.cc +++ b/src/fdbroker-internal.cc @@ -200,7 +200,7 @@ std::string FdBroker::GetInterfaceName(const std::string& target_appid, char c_buf[interface_name.length() * 2 + 1] = {0}; char* temp = &c_buf[0]; - for (int index = 0; index < interface_name.length(); index++) { + for (unsigned int index = 0; index < interface_name.length(); index++) { snprintf(temp, 3, "%02x", interface_name[index]); temp += 2; } @@ -212,11 +212,14 @@ int FdBroker::Send(const std::string& target_appid, const std::string& port_name) { std::string interface_name = GetInterfaceName(target_appid, port_name); GDBusMessage *msg; + GDBusMessage *reply; GError *err = nullptr; GVariant *body; + GVariant *reply_body; SocketPair sock_pair(mock_); FdList fd_list; char sender_appid[255]; + int ret; if (!mock_ && aul_app_get_appid_bypid(getpid(), sender_appid, sizeof(sender_appid)) < 0) { @@ -250,16 +253,34 @@ int FdBroker::Send(const std::string& target_appid, body = g_variant_new("(s)", sender_appid); g_dbus_message_set_unix_fd_list(msg, fd_list.GetRaw()); g_dbus_message_set_body(msg, body); - g_dbus_connection_send_message(DBusConnectionManager::GetInst().GetConnection(), - msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, - nullptr, &err); - if (err != nullptr) { + reply = g_dbus_connection_send_message_with_reply_sync(DBusConnectionManager::GetInst().GetConnection(), + msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 500, + nullptr, nullptr, &err); + if (reply == nullptr) { LOGE("No reply. error = %s", err->message); g_error_free(err); g_object_unref(msg); return -1; } + reply_body = g_dbus_message_get_body(reply); + if (reply_body == nullptr) { + LOGE("g_dbus_message_get_body() is failed"); + g_object_unref(msg); + return -1; + } + + g_variant_get(reply_body, "(i)", &ret); + + if (ret != 0) { + LOGE("Access Denied[sender_appid : %s]", sender_appid); + g_object_unref(msg); + g_object_unref(reply); + return -1; + } + + LOGD("[Reply : %d]", ret); + int fd = sock_pair.Detach(SocketPair::SENDER); g_object_unref(msg); @@ -303,9 +324,14 @@ void FdBroker::OnReceiveDbusMethod(GDBusConnection *conn, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { FdBroker* broker = static_cast(user_data); + int ret; - broker->ReceiveMessage(parameters, invocation); - g_dbus_method_invocation_return_value(invocation, nullptr); + AccessController& ac = broker->GetAccessController(); + ret = ac.CheckPrivilege(conn, sender); + if (ret == 0) + broker->ReceiveMessage(parameters, invocation); + + g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret)); } int FdBroker::GetOwnerId(const std::string& interface_name) { @@ -362,6 +388,7 @@ int FdBroker::RegisterDbusInterface(const std::string& port_name) { "'>" " " " " + " " " " " " ""; @@ -433,5 +460,9 @@ int FdBroker::Listen(IEventListener* ev, const std::string& port_name) { return 0; } +AccessController& FdBroker::GetAccessController() { + return ac_; +} + } // namespace internal -} // namespace rpc_port \ No newline at end of file +} // namespace rpc_port diff --git a/src/fdbroker-internal.h b/src/fdbroker-internal.h index 8ae7451..d1f31b7 100644 --- a/src/fdbroker-internal.h +++ b/src/fdbroker-internal.h @@ -26,6 +26,8 @@ #include #include +#include "ac-internal.h" + namespace rpc_port { namespace internal { @@ -45,6 +47,7 @@ class FdBroker { int Send(const std::string& target_appid, const std::string& port_name); int Listen(IEventListener* ev, const std::string& port_name); + AccessController& GetAccessController(); private: class DBusConnectionManager { @@ -137,6 +140,7 @@ class FdBroker { IEventListener* listener_ = nullptr; int registration_id_ = 0; bool mock_; + AccessController ac_; }; } // namespace internal diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 76db22f..9aebc14 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -271,6 +271,16 @@ RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) { return 0; } +RPC_API int rpc_port_stub_add_privilege(rpc_port_stub_h h, + const char* privilege) { + if (h == nullptr) + return -1; + + auto p = static_cast<::StubExt*>(h); + p->AddPrivilege(privilege); + return 0; +} + RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, rpc_port_stub_connected_event_cb cb, void* data) { if (h == nullptr) diff --git a/src/stub-internal.cc b/src/stub-internal.cc index 07c8497..a1b963f 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -44,6 +44,11 @@ void Stub::Listen(IEventListener* ev) { fd_broker_.Listen(this, port_name_); } +void Stub::AddPrivilege(const std::string& privilege) { + AccessController& ac = fd_broker_.GetAccessController(); + ac.AddPrivilege(privilege); +} + gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, gpointer data) { Stub* stub = static_cast(data); @@ -143,4 +148,4 @@ int Stub::AcceptedPort::Watch() { } } // namespace internal -} // namespace rpc_port \ No newline at end of file +} // namespace rpc_port diff --git a/src/stub-internal.h b/src/stub-internal.h index b6d8726..13a809b 100644 --- a/src/stub-internal.h +++ b/src/stub-internal.h @@ -44,6 +44,7 @@ class Stub : private FdBroker::IEventListener { virtual ~Stub(); void Listen(IEventListener* ev); + void AddPrivilege(const std::string& privilege); private: class AcceptedPort : public Port { diff --git a/unit_tests/src/rpc_port_test.cc b/unit_tests/src/rpc_port_test.cc index b1002b2..f2dc9fc 100644 --- a/unit_tests/src/rpc_port_test.cc +++ b/unit_tests/src/rpc_port_test.cc @@ -119,6 +119,10 @@ class RpcPortConnection : public RpcPortBase { }, this); ASSERT_EQ(ret, 0); + ret = rpc_port_stub_add_privilege(stub_handle_, + "http://tizen.org/privilege/appmanager.launch"); + ASSERT_EQ(ret, 0); + ret = rpc_port_stub_listen(stub_handle_); ASSERT_EQ(ret, 0); } -- 2.7.4 From 2bf9714d19ff43f78b8a9faac461aa36933b2414 Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Thu, 11 Jan 2018 17:26:13 +0900 Subject: [PATCH 12/16] Add API to support async-call from stub Change-Id: I1375d638d687562544644394f6bf52a7b75a1c31 Signed-off-by: Junghoon Park --- include/rpc-port.h | 4 ++++ src/proxy-internal.cc | 39 ++++++++++++++++++++++++++++++++------- src/proxy-internal.h | 6 +++++- src/rpc-port.cc | 25 +++++++++++++++++++++++++ unit_tests/src/rpc_port_test.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 8 deletions(-) diff --git a/include/rpc-port.h b/include/rpc-port.h index 70ee743..7ba6e8e 100755 --- a/include/rpc-port.h +++ b/include/rpc-port.h @@ -33,6 +33,8 @@ typedef void (*rpc_port_proxy_disconnected_event_cb)(const char *ep, const char *port_name, void *data); typedef void (*rpc_port_proxy_rejected_event_cb)(const char *ep, const char *port_name, void *data); +typedef void (*rpc_port_proxy_received_event_cb)(const char *ep, + const char *port_name, void *data); typedef void *rpc_port_proxy_h; int rpc_port_proxy_create(rpc_port_proxy_h *h); int rpc_port_proxy_destroy(rpc_port_proxy_h h); @@ -45,6 +47,8 @@ int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_disconnected_event_cb cb, void *data); int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, rpc_port_proxy_rejected_event_cb cb, void *data); +int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_received_event_cb cb, void *data); /* stub */ typedef void *rpc_port_stub_h; diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index 3929df4..ba316d6 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -35,8 +35,11 @@ Proxy::Proxy(bool mock) : fd_broker_(mock) {} Proxy::~Proxy() { - if (src_id_ > 0) - g_source_remove(src_id_); + if (src_ > 0) + g_source_remove(src_); + + if (disconn_src_ > 0) + g_source_remove(disconn_src_); if (gioc_ != nullptr) { g_io_channel_shutdown(gioc_, TRUE, nullptr); @@ -49,11 +52,20 @@ gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, Proxy* proxy = static_cast(data); proxy->listener_->OnDisconnected(proxy->target_appid_); - proxy->src_id_ = 0; + proxy->disconn_src_ = 0; return FALSE; } +gboolean Proxy::OnDataReceived(GIOChannel *gio, GIOCondition cond, + gpointer data) { + Proxy* proxy = static_cast(data); + + proxy->listener_->OnReceived(proxy->target_appid_); + + return TRUE; +} + int Proxy::Watch(int fd) { char buf[1024]; @@ -63,11 +75,24 @@ int Proxy::Watch(int fd) { return -1; } - src_id_ = g_io_add_watch(gioc_, - (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL), - OnSocketDisconnected, this); - if (src_id_ == 0) { + disconn_src_ = g_io_add_watch(gioc_, + (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_NVAL), + OnSocketDisconnected, this); + if (disconn_src_ == 0) { + LOGE("fail to add watch on socket"); + g_io_channel_shutdown(gioc_, TRUE, nullptr); + g_io_channel_unref(gioc_); + gioc_ = nullptr; + return -1; + } + + src_= g_io_add_watch(gioc_, + (GIOCondition)(G_IO_IN), + OnDataReceived, this); + if (src_ == 0) { LOGE("fail to add watch on socket"); + g_source_remove(disconn_src_); + disconn_src_ = 0; g_io_channel_shutdown(gioc_, TRUE, nullptr); g_io_channel_unref(gioc_); gioc_ = nullptr; diff --git a/src/proxy-internal.h b/src/proxy-internal.h index 2cb2c05..3fe0f13 100644 --- a/src/proxy-internal.h +++ b/src/proxy-internal.h @@ -40,6 +40,7 @@ class Proxy { virtual void OnConnected(const std::string& endpoint, Port& port) = 0; virtual void OnDisconnected(const std::string& endpoint) = 0; virtual void OnRejected(const std::string& endpoint) = 0; + virtual void OnReceived(const std::string& endpoint) = 0; }; void Connect(const std::string appid, const std::string& port_name, @@ -55,6 +56,8 @@ class Proxy { private: static gboolean OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, gpointer data); + static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond, + gpointer data); int Watch(int fd); private: @@ -64,7 +67,8 @@ class Proxy { FdBroker fd_broker_; std::string target_appid_; GIOChannel* gioc_ = nullptr; - int src_id_ = 0; + int disconn_src_ = 0; + int src_ = 0; }; } // namespace internal diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 9aebc14..53e3d3a 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -60,6 +60,12 @@ class ProxyExt : public Proxy, public Proxy::IEventListener { new Event(cb, user_data)); } + void AddReceivedEventListener(rpc_port_proxy_received_event_cb cb, + void* user_data) { + received_events_.emplace_back( + new Event(cb, user_data)); + } + void OnConnected(const std::string& endpoint, Port& port) override { for (auto& ev : connected_events_) { ev->cb_(endpoint.c_str(), GetPortName().c_str(), &port, @@ -79,6 +85,12 @@ class ProxyExt : public Proxy, public Proxy::IEventListener { } } + void OnReceived(const std::string& endpoint) override { + for (auto& ev : received_events_) { + ev->cb_(endpoint.c_str(), GetPortName().c_str(), ev->user_data_); + } + } + private: std::list>> connected_events_; @@ -86,6 +98,8 @@ class ProxyExt : public Proxy, public Proxy::IEventListener { disconnected_events_; std::list>> rejected_events_; + std::list>> + received_events_; }; class StubExt : public Stub, public Stub::IEventListener { @@ -230,6 +244,17 @@ RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, return 0; } +RPC_API int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h, + rpc_port_proxy_received_event_cb cb, void* data) { + if (h == nullptr) + return -1; + + auto p = static_cast<::ProxyExt*>(h); + + p->AddReceivedEventListener(cb, data); + return 0; +} + RPC_API int rpc_port_stub_create(rpc_port_stub_h* h, const char* port_name) { if (h == nullptr) return -1; diff --git a/unit_tests/src/rpc_port_test.cc b/unit_tests/src/rpc_port_test.cc index f2dc9fc..d69c593 100644 --- a/unit_tests/src/rpc_port_test.cc +++ b/unit_tests/src/rpc_port_test.cc @@ -143,6 +143,14 @@ class RpcPortConnection : public RpcPortBase { }, this); ASSERT_EQ(ret, 0); + ret = rpc_port_proxy_add_received_event_cb(proxy_handle_, + [](const char *ep, const char *port_name, void *data) { + RpcPortConnection* p = static_cast(data); + p->touch_proxy_received_event_cb_ = true; + p->Finish(); + }, this); + ASSERT_EQ(ret, 0); + ret = rpc_port_proxy_connect(proxy_handle_, "TestApp", "test_port"); ASSERT_EQ(ret, 0); } @@ -151,6 +159,7 @@ class RpcPortConnection : public RpcPortBase { rpc_port_h stub_port_ = nullptr; bool touch_proxy_disconnected_event_cb_ = false; bool touch_stub_disconnected_event_cb_ = false; + bool touch_proxy_received_event_cb_ = false; }; TEST_F(RpcPortBase, rpc_port_event_connect) { @@ -198,6 +207,37 @@ TEST_F(RpcPortBase, rpc_port_proxy_event_reject) { ASSERT_TRUE(touch_proxy_rejected_event_cb_); } +TEST_F(RpcPortConnection, rpc_port_proxy_event_receive) { + char res[] = "OK"; + char r_buf[256]; + + ASSERT_NE(proxy_port_, nullptr); + int ret = rpc_port_write(proxy_port_, res, sizeof(res)); + ASSERT_EQ(ret, 0); + + RunMainLoop(); + ASSERT_NE(stub_port_, nullptr); + + ret = rpc_port_write(stub_port_, res, sizeof(res)); + ASSERT_EQ(ret, 0); + RunMainLoop(); + ASSERT_TRUE(touch_proxy_received_event_cb_); + + ret = rpc_port_read(proxy_port_, r_buf, sizeof(res)); + ASSERT_EQ(ret, 0); + ASSERT_STREQ(res, r_buf); + + touch_proxy_received_event_cb_ = false; + ret = rpc_port_write(stub_port_, res, sizeof(res)); + ASSERT_EQ(ret, 0); + RunMainLoop(); + ASSERT_TRUE(touch_proxy_received_event_cb_); + + ret = rpc_port_read(proxy_port_, r_buf, sizeof(res)); + ASSERT_EQ(ret, 0); + ASSERT_STREQ(res, r_buf); +} + TEST_F(RpcPortConnection, rpc_port_read_write) { char buf[] = "test message"; char res[] = "OK"; -- 2.7.4 From cfd63101c4cf1648000d9bf65bb4a7275f7d526d Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Mon, 22 Jan 2018 19:55:41 +0900 Subject: [PATCH 13/16] Detect EOF to call disconnected callback To detect disconnected socket by the other side, recv function with flag MSG_PEEK was used Change-Id: I02705a61120d55b11023711c84b4c56de080af93 Signed-off-by: Junghoon Park --- src/proxy-internal.cc | 13 +++++++++++++ src/stub-internal.cc | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index ba316d6..5c8f592 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -18,6 +18,8 @@ #define _GNU_SOURCE #endif +#include +#include #include #include "proxy-internal.h" @@ -35,6 +37,7 @@ Proxy::Proxy(bool mock) : fd_broker_(mock) {} Proxy::~Proxy() { + LOGD("Proxy::~Proxy"); if (src_ > 0) g_source_remove(src_); @@ -51,6 +54,7 @@ gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, gpointer data) { Proxy* proxy = static_cast(data); + LOGW("Socket was disconnected"); proxy->listener_->OnDisconnected(proxy->target_appid_); proxy->disconn_src_ = 0; @@ -60,6 +64,15 @@ gboolean Proxy::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, gboolean Proxy::OnDataReceived(GIOChannel *gio, GIOCondition cond, gpointer data) { Proxy* proxy = static_cast(data); + int fd = g_io_channel_unix_get_fd(gio); + char buffer[4]; + + if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) { + LOGW("Socket was disconnected by stub"); + proxy->listener_->OnDisconnected(proxy->target_appid_); + proxy->src_ = 0; + return FALSE; + } proxy->listener_->OnReceived(proxy->target_appid_); diff --git a/src/stub-internal.cc b/src/stub-internal.cc index a1b963f..cff9295 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -18,6 +18,8 @@ #define _GNU_SOURCE #endif +#include +#include #include #include "stub-internal.h" @@ -34,7 +36,9 @@ namespace internal { Stub::Stub(const std::string& port_name, bool mock) : fd_broker_(mock), port_name_(port_name) {} -Stub::~Stub() {} +Stub::~Stub() { + LOGD("Stub::~Stub"); +} void Stub::Listen(IEventListener* ev) { if (ev == nullptr) @@ -53,12 +57,21 @@ gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, gpointer data) { Stub* stub = static_cast(data); int fd = g_io_channel_unix_get_fd(gio); + char buffer[4]; for (auto& p : stub->ports_) { if (p->GetFd() == fd) { + if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) { + LOGW("Socket was disconnected from proxy"); + stub->listener_->OnDisconnected(p->GetId()); + stub->ports_.remove(p); + return FALSE; + } + int ret = stub->listener_->OnReceived(p->GetId(), *p); if (ret != 0) { + LOGW("Invalid protocol"); stub->listener_->OnDisconnected(p->GetId()); stub->ports_.remove(p); return FALSE; @@ -76,6 +89,7 @@ gboolean Stub::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, Stub* stub = static_cast(data); int fd = g_io_channel_unix_get_fd(gio); + LOGW("Socket was disconnected"); for (auto& p : stub->ports_) { if (p->GetFd() == fd) { stub->listener_->OnDisconnected(p->GetId()); -- 2.7.4 From 8446635cbf57ae193d43e64dd439cc224afda1db Mon Sep 17 00:00:00 2001 From: Junghoon Park Date: Thu, 25 Jan 2018 20:18:00 +0900 Subject: [PATCH 14/16] Modify rpc-port APIs to be thread-safe Change-Id: I3f27851e09491b3b2c7638c3b9dcf6419f57684f Signed-off-by: Junghoon Park --- src/port-internal.cc | 2 ++ src/port-internal.h | 3 +++ src/rpc-port.cc | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/port-internal.cc b/src/port-internal.cc index caa354c..695f617 100644 --- a/src/port-internal.cc +++ b/src/port-internal.cc @@ -53,6 +53,7 @@ int Port::Read(void* buf, unsigned int size) { const struct timespec TRY_SLEEP_TIME = { 0, 500 * 1000 * 1000 }; int bytes_read = 0; char* buffer = static_cast(buf); + std::lock_guard lock(mutex_); while (left && (retry_cnt < MAX_RETRY_CNT)) { nb = read(fd_, buffer, left); @@ -92,6 +93,7 @@ int Port::Write(const void* buf, unsigned int size) { int ret; int bytes_write = 0; const char* buffer = static_cast(buf); + std::lock_guard lock(mutex_); fds[0].fd = fd_; fds[0].events = POLLOUT; diff --git a/src/port-internal.h b/src/port-internal.h index d612cb7..5fd3a1a 100644 --- a/src/port-internal.h +++ b/src/port-internal.h @@ -17,6 +17,8 @@ #ifndef PORT_INTERNAL_H_ #define PORT_INTERNAL_H_ +#include +#include #include #include @@ -41,6 +43,7 @@ class Port { private: int fd_; std::string id_; + std::recursive_mutex mutex_; }; } // namespace internal diff --git a/src/rpc-port.cc b/src/rpc-port.cc index 53e3d3a..ba9ead2 100755 --- a/src/rpc-port.cc +++ b/src/rpc-port.cc @@ -16,6 +16,9 @@ #include +#include +#include + #include "rpc-port.h" #include "port-internal.h" #include "proxy-internal.h" @@ -91,6 +94,10 @@ class ProxyExt : public Proxy, public Proxy::IEventListener { } } + std::recursive_mutex& GetMutex() const { + return mutex_; + } + private: std::list>> connected_events_; @@ -100,6 +107,7 @@ class ProxyExt : public Proxy, public Proxy::IEventListener { rejected_events_; std::list>> received_events_; + mutable std::recursive_mutex mutex_; }; class StubExt : public Stub, public Stub::IEventListener { @@ -147,6 +155,10 @@ class StubExt : public Stub, public Stub::IEventListener { return 0; } + std::recursive_mutex& GetMutex() const { + return mutex_; + } + private: std::list>> connected_events_; @@ -154,6 +166,7 @@ class StubExt : public Stub, public Stub::IEventListener { disconnected_events_; std::list>> received_events_; + mutable std::recursive_mutex mutex_; }; } // namespace @@ -206,6 +219,7 @@ RPC_API int rpc_port_proxy_connect(rpc_port_proxy_h h, const char* appid, return -1; auto p = static_cast<::ProxyExt*>(h); + std::lock_guard lock(p->GetMutex()); p->Connect(appid, port, p); return 0; @@ -217,6 +231,7 @@ RPC_API int rpc_port_proxy_add_connected_event_cb(rpc_port_proxy_h h, return -1; auto p = static_cast<::ProxyExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddConnectedEventListener(cb, data); return 0; @@ -228,6 +243,7 @@ RPC_API int rpc_port_proxy_add_disconnected_event_cb(rpc_port_proxy_h h, return -1; auto p = static_cast<::ProxyExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddDisconnectedEventListener(cb, data); return 0; @@ -239,6 +255,7 @@ RPC_API int rpc_port_proxy_add_rejected_event_cb(rpc_port_proxy_h h, return -1; auto p = static_cast<::ProxyExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddRejectedEventListener(cb, data); return 0; @@ -250,6 +267,7 @@ RPC_API int rpc_port_proxy_add_received_event_cb(rpc_port_proxy_h h, return -1; auto p = static_cast<::ProxyExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddReceivedEventListener(cb, data); return 0; @@ -291,6 +309,7 @@ RPC_API int rpc_port_stub_listen(rpc_port_stub_h h) { return -1; auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); p->Listen(p); return 0; @@ -302,6 +321,8 @@ RPC_API int rpc_port_stub_add_privilege(rpc_port_stub_h h, return -1; auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); + p->AddPrivilege(privilege); return 0; } @@ -312,6 +333,7 @@ RPC_API int rpc_port_stub_add_connected_event_cb(rpc_port_stub_h h, return -1; auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddConnectedEventListener(cb, data); return 0; @@ -323,6 +345,7 @@ RPC_API int rpc_port_stub_add_disconnected_event_cb(rpc_port_stub_h h, return -1; auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddDisconnectedEventListener(cb, data); return 0; @@ -334,6 +357,7 @@ RPC_API int rpc_port_stub_add_received_event_cb(rpc_port_stub_h h, return -1; auto p = static_cast<::StubExt*>(h); + std::lock_guard lock(p->GetMutex()); p->AddReceivedEventListener(cb, data); return 0; -- 2.7.4 From 59683a63a5c77fb1e0115fd9955cbe3547477e96 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 16 Jan 2018 23:13:29 +0900 Subject: [PATCH 15/16] Watch rpc port and handle stub app lifecycle Before sending a connection request, a proxy watches a dbus interface for registering it. When a stub is getting disconnected event, the stub notifies it to the amd for background management feature. Change-Id: I50544ec188bf5f8e2907f35dd926aa944373ee1d Signed-off-by: Hwankyu Jhun --- src/fdbroker-internal.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++++- src/fdbroker-internal.h | 23 ++++++++++++++ src/proxy-internal.cc | 32 +++++++++++++++----- src/proxy-internal.h | 6 +++- src/stub-internal.cc | 13 ++++++++ 5 files changed, 143 insertions(+), 10 deletions(-) diff --git a/src/fdbroker-internal.cc b/src/fdbroker-internal.cc index 26c08f3..451ab34 100644 --- a/src/fdbroker-internal.cc +++ b/src/fdbroker-internal.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "fdbroker-internal.h" @@ -114,6 +115,13 @@ int FdBroker::DBusMock::AddListener(const std::string& port, return 0; } +int FdBroker::DBusMock::Watch(FdBroker::IEventWatcher* watcher, + const std::string& target_appid, + const std::string& port_name) { + watcher->OnPortAppeared(target_appid, port_name); + return 0; +} + void FdBroker::DBusMock::Dispose() { ports_.clear(); } @@ -136,7 +144,7 @@ int FdBroker::SocketPair::Request() { return socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socks_); } - if (aul_request_message_port_socket_pair(socks_) != AUL_R_OK) { + if (aul_rpc_port_create_socket_pair(&socks_) != AUL_R_OK) { LOGE("error create socket pair"); return -1; } @@ -183,6 +191,9 @@ GUnixFDList* FdBroker::FdList::GetRaw() { } FdBroker::~FdBroker() { + if (watcher_id_ > 0) + g_bus_unwatch_name(watcher_id_); + if (registration_id_ > 0) { g_dbus_connection_unregister_object( DBusConnectionManager::GetInst().GetConnection(), @@ -464,5 +475,71 @@ AccessController& FdBroker::GetAccessController() { return ac_; } +void FdBroker::OnNameAppeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) { + FdBroker* broker = static_cast(user_data); + broker->watcher_->OnPortAppeared(broker->watch_appid_, + broker->watch_port_name_); +} + +void FdBroker::OnNameVanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) { + FdBroker* broker = static_cast(user_data); + broker->watcher_->OnPortVanished(broker->watch_appid_, + broker->watch_port_name_); +} + +int FdBroker::Watch(IEventWatcher* ev, const std::string& target_appid, + const std::string& port_name) { + int r; + + if (watcher_ != nullptr) + return -1; + + if (ev == nullptr) + return -1; + + if (!mock_) { + r = aul_rpc_port_prepare_stub(target_appid.c_str(), port_name.c_str()); + if (r != AUL_R_OK) { + LOGE("Failed to prepare stub %s:%s", + target_appid.c_str(), port_name.c_str()); + return -1; + } + } + + watcher_ = ev; + watch_appid_ = target_appid; + watch_port_name_ = port_name; + + if (mock_) { + r = DBusMock::GetInst().Watch(ev, target_appid, port_name); + if (r < 0) + return -1; + + return 0; + } + + std::string interface_name = GetInterfaceName(target_appid, port_name); + watcher_id_ = g_bus_watch_name_on_connection( + DBusConnectionManager::GetInst().GetConnection(), + interface_name.c_str(), + G_BUS_NAME_WATCHER_FLAGS_NONE, + OnNameAppeared, + OnNameVanished, + this, + NULL); + if (watcher_id_ == 0) { + LOGE("Failed to watch connection(%s)", interface_name.c_str()); + watcher_ = nullptr; + return -1; + } + + return 0; +} + } // namespace internal } // namespace rpc_port diff --git a/src/fdbroker-internal.h b/src/fdbroker-internal.h index d1f31b7..77ff32d 100644 --- a/src/fdbroker-internal.h +++ b/src/fdbroker-internal.h @@ -38,6 +38,14 @@ class FdBroker { virtual void OnFdReceived(const std::string& sender, int fd) = 0; }; + class IEventWatcher { + public: + virtual void OnPortAppeared(const std::string& appid, + const std::string& port_name) = 0; + virtual void OnPortVanished(const std::string& appid, + const std::string& port_name) = 0; + }; + FdBroker(bool mock = false) : mock_(mock) {} ~FdBroker(); @@ -48,6 +56,8 @@ class FdBroker { int Send(const std::string& target_appid, const std::string& port_name); int Listen(IEventListener* ev, const std::string& port_name); AccessController& GetAccessController(); + int Watch(IEventWatcher* ev, const std::string& target_appid, + const std::string& port_name); private: class DBusConnectionManager { @@ -80,6 +90,8 @@ class FdBroker { int Send(const std::string& sender, const std::string& port, int fd); int AddListener(const std::string& port, FdBroker::IEventListener* listener); + int Watch(FdBroker::IEventWatcher* watcher, const std::string& target_appid, + const std::string& port_name); void Dispose(); private: @@ -135,12 +147,23 @@ class FdBroker { void ReceiveMessage(GVariant* parameters, GDBusMethodInvocation* invocation); std::string GetInterfaceName(const std::string& target_appid, const std::string& port_name); + static void OnNameAppeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data); + static void OnNameVanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data); private: IEventListener* listener_ = nullptr; int registration_id_ = 0; bool mock_; AccessController ac_; + IEventWatcher* watcher_ = nullptr; + guint watcher_id_ = 0; + std::string watch_appid_; + std::string watch_port_name_; }; } // namespace internal diff --git a/src/proxy-internal.cc b/src/proxy-internal.cc index 5c8f592..82fae45 100644 --- a/src/proxy-internal.cc +++ b/src/proxy-internal.cc @@ -115,16 +115,14 @@ int Proxy::Watch(int fd) { return 0; } -void Proxy::Connect(const std::string appid, const std::string& port_name, - IEventListener* ev) { - if (ev == nullptr || listener_ != nullptr) +void Proxy::OnPortAppeared(const std::string& appid, + const std::string& port_name) { + LOGD("endpoint(%s), port_name(%s)", appid.c_str(), port_name.c_str()); + + if (listener_ == nullptr) return; - listener_ = ev; - target_appid_ = appid; - port_name_ = port_name; int fd = fd_broker_.Send(appid, port_name); - if (fd <= 0) { listener_->OnRejected(appid); listener_ = nullptr; @@ -136,5 +134,23 @@ void Proxy::Connect(const std::string appid, const std::string& port_name, Watch(fd); } +void Proxy::OnPortVanished(const std::string& appid, + const std::string& port_name) { + LOGD("endpoint(%s), port_name(%s)", appid.c_str(), port_name.c_str()); +} + +void Proxy::Connect(const std::string appid, const std::string& port_name, + IEventListener* ev) { + if (ev == nullptr || listener_ != nullptr) + return; + + listener_ = ev; + target_appid_ = appid; + port_name_ = port_name; + int r = fd_broker_.Watch(this, appid, port_name); + if (r < 0) + listener_ = nullptr; +} + } // namespace internal -} // namespace rpc_port \ No newline at end of file +} // namespace rpc_port diff --git a/src/proxy-internal.h b/src/proxy-internal.h index 3fe0f13..7c12f9c 100644 --- a/src/proxy-internal.h +++ b/src/proxy-internal.h @@ -30,7 +30,7 @@ namespace rpc_port { namespace internal { -class Proxy { +class Proxy : public FdBroker::IEventWatcher { public: Proxy(bool mock = false); virtual ~Proxy(); @@ -59,6 +59,10 @@ class Proxy { static gboolean OnDataReceived(GIOChannel *gio, GIOCondition cond, gpointer data); int Watch(int fd); + void OnPortAppeared(const std::string& appid, + const std::string& port_name) override; + void OnPortVanished(const std::string& appid, + const std::string& port_name) override; private: std::string port_name_; diff --git a/src/stub-internal.cc b/src/stub-internal.cc index cff9295..994195b 100644 --- a/src/stub-internal.cc +++ b/src/stub-internal.cc @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "stub-internal.h" @@ -65,6 +67,10 @@ gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, LOGW("Socket was disconnected from proxy"); stub->listener_->OnDisconnected(p->GetId()); stub->ports_.remove(p); + + if (aul_rpc_port_notify_rpc_finished() != AUL_R_OK) + LOGW("Failed to notify rpc finished"); + return FALSE; } @@ -74,6 +80,10 @@ gboolean Stub::OnDataReceived(GIOChannel *gio, GIOCondition cond, LOGW("Invalid protocol"); stub->listener_->OnDisconnected(p->GetId()); stub->ports_.remove(p); + + if (aul_rpc_port_notify_rpc_finished() != AUL_R_OK) + LOGW("Failed to notify rpc finished"); + return FALSE; } @@ -98,6 +108,9 @@ gboolean Stub::OnSocketDisconnected(GIOChannel *gio, GIOCondition cond, } } + if (aul_rpc_port_notify_rpc_finished() != AUL_R_OK) + LOGW("Failed to notify rpc finished"); + return FALSE; } -- 2.7.4 From bf0a712e0a12147dbd60e8c355de6b12a52d75b8 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 30 Jan 2018 16:20:38 +0900 Subject: [PATCH 16/16] Add a dependency Requires: - amd-mod-rpc-port Change-Id: If8080d2d2d9bea4f878b5092117668f9de738064 Signed-off-by: Hwankyu Jhun --- packaging/rpc-port.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/rpc-port.spec b/packaging/rpc-port.spec index e449e27..8ac8896 100755 --- a/packaging/rpc-port.spec +++ b/packaging/rpc-port.spec @@ -21,6 +21,8 @@ Requires(post): /sbin/ldconfig Requires(post): coreutils Requires(postun): /sbin/ldconfig +Requires: amd-mod-rpc-port + Provides: capi-rpc-port Provides: libcapi-rpc-port.so.1 -- 2.7.4