diff options
Diffstat (limited to 'otherservice')
58 files changed, 14875 insertions, 0 deletions
diff --git a/otherservice/event_library/LICENSE b/otherservice/event_library/LICENSE new file mode 100755 index 0000000..f433b1a --- /dev/null +++ b/otherservice/event_library/LICENSE @@ -0,0 +1,177 @@ + + 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 diff --git a/otherservice/event_library/Makefile.client b/otherservice/event_library/Makefile.client new file mode 100755 index 0000000..f00b09d --- /dev/null +++ b/otherservice/event_library/Makefile.client @@ -0,0 +1,18 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# +SUBDIRS := library + +include ../other_service.mk diff --git a/otherservice/event_library/library/Makefile b/otherservice/event_library/library/Makefile new file mode 100755 index 0000000..3127439 --- /dev/null +++ b/otherservice/event_library/library/Makefile @@ -0,0 +1,37 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +INST_SHLIBS = libev +libev_SRCS := src/ev_lib.c +VPATH = ./src ./include/$(COMPONENT_NAME)/ +INST_HEADERS = ev_lib.h event_library.h + +CPPFLAGS = -I./include + +FDLAGS += -Wl,--no-undefined +CPPFLAGS += -Werror=implicit-function-declaration +CPPFLAGS += -Werror=format-security + +CPPFLAGS += -Wconversion +CPPFLAGS += -Wpointer-to-int-cast +CPPFLAGS += -Wint-to-pointer-cast +CPPFLAGS += -Wpointer-arith +CPPFLAGS += -Wformat + +LDFLAGS += -Wl,--no-as-needed +LDLIBS := -lpthread + +include ../../other_service.mk diff --git a/otherservice/event_library/library/include/other_service/ev_lib.h b/otherservice/event_library/library/include/other_service/ev_lib.h new file mode 100755 index 0000000..6b87ea2 --- /dev/null +++ b/otherservice/event_library/library/include/other_service/ev_lib.h @@ -0,0 +1,1856 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file ev_lib.h + * @brief \~english Event library -- API define head file + */ + +#ifndef OTHERSERVICE_EV_LIB_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_EV_LIB_H_ // NOLINT(build/header_guard) + +#include <agl_types_obsoluted.h> +#include <agldd/ev_common.h> +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup event_library + * @ingroup other_service + * @{ + */ + +#ifndef __KERNEL__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Create/Delete flag and message queue */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag +/// \~english @par Brief +/// Create flag for event flag by the flag_id. +/// \~english @param [in] flag_id +/// EV_ID - Flag ID of the flag event +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist Duplication Error +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id: The ID is not created by function of EV_moduleID_to_flagID(). +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - flag_id registered in launch thread +/// - Flag corresponding to flag_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Creates flag with ID specified by the argument. +/// An error occurs if flag of the specified ID already exists. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_create_flag, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag(EV_ID flag_id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag64 +/// \~english @par Brief +/// Create flag for event flag by the flag_id. +/// \~english @param [in] flag_id +/// EV_ID - Flag ID of the flag event +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist Duplication Error +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id: The ID is not created by function of EV_moduleID_to_flag64ID (). +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - flag_id registered in launch thread +/// - Flag corresponding to flag_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Creates flag with ID specified by the argument. +/// An error occurs if flag of the specified ID already exists. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_create_flag, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag64(EV_ID flag_id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_queue +/// \~english @par Brief +/// Create message queue with the queue_id. +/// \~english @param [in] queue_id +/// EV_ID - queue_id of message event +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [in] length +/// UINT8 - length of message queue (Maximum accumulated number of the messages) +/// \~english @param [in] max_bytes +/// UINT16 - the maximum number of bytes per 1 message(MAX 2048) +/// \~english @param [in] type +/// EV_Message_Queue_Type - classification of the processing when the queue received more event +/// - in the queue full state. +/// \~english @par +/// EV_Message_Queue_Type +/// \~english @code +/// typedef UINT8 EV_Message_Queue_Type; +/// - EV_MESSAGE_QUEUE_TYPE_BUSY = 0 // Return error(EV_ERR_Busy) to origin of message transmission +/// - EV_MESSAGE_QUEUE_TYPE_FIFO = 1 // Delete the top message of the queue, and shift message +/// // (Delete the oldest message) +/// - EV_MESSAGE_QUEUE_TYPE_REPLACE = 2 // Overwrite the last message of the queue +/// // (Overwrite the newest message) +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist Duplication Error +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id is not created by function of EV_moduleID_to_queueID (). +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - queue_id registered in launch thread +/// - Message queue corresponding to queue_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Message queue pool is NULL +/// - Message queue generation corresponding to queue_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Creates message queue with ID specified by the argument. +/// When queue is created, a memory area corresponding to "length" x "max_bytes" is dynamically secured. +/// An error occurs if queue of the specified ID already exists. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_create_message_queue, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_queue(EV_ID queue_id, // NOLINT (readability/nolint) + UINT8 length, // NOLINT (readability/nolint) + UINT16 max_bytes, // NOLINT (readability/nolint) + EV_Message_Queue_Type type); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag_auto_id +/// \~english @par Brief +/// Automatically assign flag ID, and creates flag with flag ID. +/// \~english @param [out] flag_id +/// EV_ID* - flag_id assigned automatically +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Automatically assign flag ID, and creates flag with flag ID. +/// It is the same as "EV_create_flag" except that flag ID is automatically allocated. +/// \~english @see EV_create_flag, evk_open, evk_close, evk_ioctl, evk_create_flag, evk_alloc_flag_id, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag_auto_id(/* OUT */EV_ID *flag_id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag64_auto_id +/// \~english @par Brief +/// Automatically assign flag ID, and creates flag with flag ID. +/// \~english @param [out] flag_id +/// EV_ID* - flag_id assigned automatically +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Automatically assign flag ID, and creates flag with flag ID. +/// It is the same as "EV_create_flag" except that flag ID is automatically allocated. +/// \~english @see EV_create_flag, evk_open, evk_close, evk_ioctl, evk_create_flag, evk_alloc_flag_id, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag64_auto_id(/* OUT */EV_ID *flag_id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_queue_auto_id +/// \~english @par Brief +/// Automatically assign queue ID, and creates message queue with queue ID. +/// It stores queue_id assigned automatically in argument. +/// \~english @param [out] queue_id +/// EV_ID* - queue_id assigned automatically +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [in] length +/// UINT8 - length of message queue (Maximum accumulated number of the messages) +/// \~english @param [in] max_bytes +/// UINT16 - the maximum number of bytes per 1 message(MAX 2048) +/// \~english @param [in] type +/// EV_Message_Queue_Type - classification of the processing when the queue received more event +/// in the queue full state. +/// \~english @par +/// EV_Message_Queue_Type +/// \~english @code +/// typedef UINT8 EV_Message_Queue_Type; +/// - EV_MESSAGE_QUEUE_TYPE_BUSY = 0 // Return error(EV_ERR_Busy) to origin of message transmission +/// - EV_MESSAGE_QUEUE_TYPE_FIFO = 1 // Delete the top message of the queue, and shift message +/// // (Delete the oldest message) +/// - EV_MESSAGE_QUEUE_TYPE_REPLACE = 2 // Overwrite the last message of the queue +/// // (Overwrite the newest message) +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Thread is unregistered and threads started up to the maximum of event thread(16 threads) +/// - EV_ERR_Thread_Over +/// - Message queue corresponding to queue_id already exists +/// - Securing free space of thread information management table (malloc) Failure +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Message queue pool is NULL +/// - Message queue generation corresponding to queue_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Automatically assign queue id, and creates message queue with queue id, It stores queue_id +/// assigned automatically in argument. +/// It is the same as "EV_queue_flag" except that queue ID is automatically allocated. +/// \~english @see EV_create_queue, evk_open, evk_close, evk_ioctl, evk_create_message_queue, +/// evk_alloc_queueID, evk_set_poll +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_queue_auto_id(/* OUT */EV_ID *queue_id, // NOLINT (readability/nolint) + UINT8 length, // NOLINT (readability/nolint) + UINT16 max_bytes, // NOLINT (readability/nolint) + EV_Message_Queue_Type type); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_destroy_flag +/// \~english @par Brief +/// Deletes flag with ID specified by the argument. +/// \~english @param [in] flag_id +/// EV_ID - Flag ID of the flag event +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Flag corresponding to queue_id doesn't exist +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Deletes flag with ID specified by the argument. +/// The user can only delete flag created by user process. +/// Due to deletion, program waiting for this flag (poll or wait) wakes up. +/// \~english @see evk_close, evk_ioctl, evk_destroy_queue +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_destroy_flag(EV_ID queue_id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_destroy_queue +/// \~english @par Brief +/// Delete queue for message event by the queue_id. +/// \~english @param [in] queue_id +/// EV_ID - queue_id of the message event +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Message queue corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Deletes message queue with ID specified by the argument. +/// The user can only delete message queue created by user process. +/// Due to deletion, program waiting for this message queue (poll or wait) wakes up. +/// \~english @see EV_destroy_flag, evk_close, evk_ioctl, evk_destroy_queue +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_destroy_queue(EV_ID queue_id); // NOLINT (readability/nolint) + +/* Send event */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_set_flag +/// \~english @par Brief +/// Set Event flag +/// \~english @param [in] flag_id +/// EV_ID - Flag ID of the event flag +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [in] bits +/// UINT32 - event flag bit pattern +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - Flag corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sets bit pattern specified by argument to flag of ID specified by argument. +/// When setting a plurality of bit patterns in the same flag, "only OR +/// operation result of all bit patterns" is held in flag. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_store_flag +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_set_flag(EV_ID flag_id, UINT32 bits); // NOLINT (readability/nolint) + +/* Send event */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_set_flag64 +/// \~english @par Brief +/// Set Event flag +/// \~english @param [in] flag_id +/// EV_ID - Flag ID of the event flag +/// \~english @par +/// EV_ID type parameter +/// @code + +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [in] bits +/// UINT32 - event flag bit pattern +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - Flag corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sets bit pattern specified by argument to flag of ID specified by argument. +/// When setting a plurality of bit patterns in the same flag, "only OR operation +/// result of all bit patterns" is held in flag. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_store_flag +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_set_flag64(EV_ID flag_id, UINT64 bits); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_send_message +/// \~english @par Brief +/// Send Message event +/// \~english @param [in] queue_id +/// EV_ID - Queue ID of the message destination +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [in] bytes +/// UINT16 - The bytes of the send message +/// \~english @param [in] message +/// const void * - Pointer to a transmitting byte line +/// \~english @param [in] senderInfo +/// UINT32 - Message Source(It is specified when it is used for application identification. +/// When do not use it, appoint 0.) +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Busy Queue overflow +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Message queue corresponding to queue_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Queue overflow in kernel space +/// - EV_ERR_Busy +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Invalid queue types +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sends message specified by argument to message queue of ID specified by argument. +/// An error occurs when message queue of the specified ID doesn't exist or +/// message size exceeds the specified size. +/// When message queue is FULL, the processing differs depending on the type of message queue specified +/// at the time of creation message queue. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_store_message +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_send_message(EV_ID queue_id, // NOLINT (readability/nolint) + UINT16 bytes, // NOLINT (readability/nolint) + const void *message, // NOLINT (readability/nolint) + UINT32 senderInfo); // NOLINT (readability/nolint) + +/* \~english Get events in the order of arrivals */ +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_next_event +/* \~english get events by reaching time */ +/// \~english @par Brief get the first reached event(non-block) +/// \~english @param [out] ev +/// event Structure +/// \~english @par +/// EV_Event struct +/// @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_Type; +/// typedef UINT32 EV_ID; +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// enum ev_message_queue_type { +/// EV_MESSAGE_QUEUE_TYPE_BUSY, +/// EV_MESSAGE_QUEUE_TYPE_FIFO, +/// EV_MESSAGE_QUEUE_TYPE_REPLACE, +/// }; +/// +/// typedef struct { +/// EV_ID flagID; +/// UINT32 bits; +/// } EV_Flag; +/// +/// typedef struct { +/// EV_ID flagID; +/// UINT64 bits; +/// } EV_Flag64; +/// +/// typedef struct { +/// EV_ID queueID; +/// UINT32 senderInfo; +/// UINT32 length; +/// UINT32 dummy; +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; +/// } EV_Message; +/// +/// typedef struct { +/// EV_Type type; // please reference ev_message_queue_type. +/// union { +/// EV_Flag flag; +/// EV_Flag64 flag64; +/// EV_Message message; +/// } u; +/// } EV_Event; +/// +/// @endcode + +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_Thread: unregistered thread +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - unregistered thread +/// - EV_ERR_Invalid_Thread +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Get the first reached event which occurred for +/// flags or message queues created in current process. +/// If there is no event, set ev->type to EV_EVENT_None, then return immediately. +/// The event is flag or message is decided by +/// the ev->type is EV_EVENT_Flag or EV_EVENT_Message. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_next_event(/* OUT */EV_Event *ev); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_peek_next_event +/// \~english @par Brief get the first reached event(non-destructive) +/// \~english @param [out] ev +/// event Structure +/// @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_Type; +/// typedef UINT32 EV_ID; +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// enum ev_message_queue_type { +/// EV_MESSAGE_QUEUE_TYPE_BUSY, +/// EV_MESSAGE_QUEUE_TYPE_FIFO, +/// EV_MESSAGE_QUEUE_TYPE_REPLACE, +/// }; +/// +/// typedef struct { +/// EV_ID flagID; +/// UINT32 bits; +/// } EV_Flag; +/// +/// typedef struct { +/// EV_ID flagID; +/// UINT64 bits; +/// } EV_Flag64; +/// +/// typedef struct { +/// EV_ID queueID; +/// UINT32 senderInfo; +/// UINT32 length; +/// UINT32 dummy; +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; +/// } EV_Message; +/// +/// typedef struct { +/// EV_Type type; // please reference ev_message_queue_type. +/// union { +/// EV_Flag flag; +/// EV_Flag64 flag64; +/// EV_Message message; +/// } u; +/// } EV_Event; +/// +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_Thread: unregistered thread +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - unregistered thread +/// - EV_ERR_Invalid_Thread +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Get the first reached event which occurred for +/// flags or message queues created in current process non-destructively. +/// If the event is not getted from other processes, then call the function of +/// EV_get_next_event() or EV_peek_next_event(), it will return a same event. +/// If there is no event, set ev->type to EV_EVENT_None, then return immediately. +/// The event is flag or message is decided by +/// ev->type is EV_EVENT_Flag or EV_EVENT_Message. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_peek_next_event(/* OUT */EV_Event *ev); // NOLINT (readability/nolint) + +/* Get eventflag (ID specified) */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_flag +/// \~english @par Brief +/// Get event flag(non-block) +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] flag +/// EV_Flag * - event flag structure +/// \~english @par +/// EV_Flag structure +/// \~english @code +/// typedef struct { +/// EV_ID flagID; // Flag ID +/// UINT32 bits; // event flag bit pattern +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets bit pattern specified by argument to flag of ID specified by argument. +/// The user can only get flag created by user process, and clear bit pattern of acquired flag. +/// An error occurs if flag of the specified ID doesn't exist. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_flag(EV_ID flag_id, /* OUT */EV_Flag *flag); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_wait_flag +/// \~english @par Brief +/// Get event flag(block) +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] flag +/// EV_Flag * - event flag structure +/// \~english @par +/// EV_Flag structure +/// \~english @code +/// typedef struct { +/// EV_ID flagID; // Flag ID +/// UINT32 bits; // event flag bit pattern +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Interrupted signal interrupt +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Task blocking was canceled by signal interrupt +/// - EV_ERR_Interrupted +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets bit pattern specified by argument to flag of ID specified by argument. +/// The user can only get flag created by user process, and clear bit pattern of acquired flag. +/// An error occurs if flag of the specified ID doesn't exist. +/// If bit pattern is not set in flag, block until bit pattern is set. +/// However, if a signal interrupt or corresponding flag is deleted, it will abort and return an error. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_wait_flag(EV_ID flag_id, /* OUT */EV_Flag *flag); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_peek_flag +/// \~english @par Brief get flag event(non-destructive) +/// \~english @param [in] flag_id +/// ID of message event queue +/// \~english @param [out] flag +/// flag struct +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @par +/// EV_Flag Structure +/// @code +/// typedef struct { +/// EV_ID flagID; +/// UINT32 bits; +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: The specified flag ID is not existing, +/// or it is not created in current process. +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Task blocking was canceled by signal interrupt +/// - EV_ERR_Interrupted +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Get a flag event whose ID is specified non-destructively. +/// If there is no event, just return. +/// If there is no event, set flag->flagID to EV_NO_ID. +/// You can judge that there is no event, even though flag->bits is 0. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_peek_flag(EV_ID flag_id, /* OUT */EV_Flag *flag); // NOLINT (readability/nolint) + +/* Get eventflag (ID specified) */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_flag64 +/// \~english @par Brief +/// Get event flag(non-block) +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] flag +/// EV_Flag * - event flag structure +/// \~english @par +/// EV_Flag structure +/// \~english @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_ID +/// +/// typedef struct { +/// EV_ID flagID; // Flag ID +/// UINT32 bits; // event flag bit pattern +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets bit pattern specified by argument to flag of ID specified by argument. +/// The user can only get flag created by user process, and clear bit pattern of acquired flag. +/// An error occurs if flag of the specified ID doesn't exist. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_flag64(EV_ID flag_id, /* OUT */EV_Flag64 *flag); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_wait_flag64 +/// \~english @par Brief +/// Get event flag(block) +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] flag +/// EV_Flag * - event flag structure +/// \~english @par +/// EV_Flag structure +/// \~english @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_ID +/// +/// typedef struct { +/// EV_ID flagID; // Flag ID +/// UINT32 bits; // event flag bit pattern +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Interrupted signal interrupt +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Task blocking was canceled by signal interrupt +/// - EV_ERR_Interrupted +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets bit pattern specified by argument to flag of ID specified by argument. +/// The user can only get flag created by user process, and clear bit pattern of acquired flag. +/// An error occurs if flag of the specified ID doesn't exist. +/// If bit pattern is not set in flag, block until bit pattern is set. +/// However, if a signal interrupt or corresponding flag is deleted, it will abort and return an error. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_wait_flag64(EV_ID flag_id, /* OUT */EV_Flag64 *flag); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_peek_flag64 +/// \~english @par Brief get flag event(non-destructive) +/// \~english @param [in] flag_id +/// ID of message event queue +/// \~english @param [out] flag +/// flag struct +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @par +/// EV_Flag Structure +/// @code +/// typedef struct { +/// EV_ID flagID; +/// UINT32 bits; +/// } EV_Flag; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: The specified flag ID is not existing, +/// or it is not created in current process. +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Flag corresponding to flag_id doesn't exist +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - EV_ERR_Invalid_ID +/// - Task blocking was canceled by signal interrupt +/// - EV_ERR_Interrupted +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Get a flag event whose ID is specified non-destructively. +/// If there is no event, just return. +/// If there is no event, set flag->flagID to EV_NO_ID. +/// You can judge that there is no event, even though flag->bits is 0. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_peek_flag64(EV_ID flag_id, /* OUT */EV_Flag64 *flag); // NOLINT (readability/nolint) + +/* Get Message Event (ID specified) */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_message +/// \~english @par Brief +/// Get message event(non-block) +/// \~english @param [in] queue_id +/// EV_ID - Message queue ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] message +/// EV_Message * - Message event structure +/// \~english @par +/// EV_Message structure +/// \~english @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_ID +/// +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// typedef struct { +/// EV_ID queueID; // ID of message queue +/// UINT32 senderInfo; // Message Source +/// UINT32 length; // length of message +/// UINT32 dummy; // dummy for padding +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; // message +/// } EV_Message; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Message queue corresponding to queue_id doesn't exist +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets 1 message specified by argument to message queue of ID specified by argument. +/// The user can only get message queue created by user process, and clear 1 message of acquired message queue. +/// An error occurs if message queue of the specified ID doesn't exist. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_message(EV_ID queue_id, /* OUT */EV_Message *message); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_wait_message +/// \~english @par Brief +/// Get message event(block) +/// \~english @param [in] queue_id +/// EV_ID - Message queue ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] message +/// EV_Message * - Message event structure +/// \~english @par +/// EV_Message structure +/// \~english @code +/// typedef unsigned int UINT32; +/// typedef UINT32 EV_ID +/// +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// typedef struct { +/// EV_ID queueID; // ID of message queue +/// UINT32 senderInfo; // Message Source +/// UINT32 length; // length of message +/// UINT32 dummy; // dummy for padding +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; // message +/// } EV_Message; +/// @endcode +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Interrupted signal interrupt +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Message queue corresponding to queue_id doesn't exist +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - EV_ERR_Invalid_ID +/// - Task blocking was canceled by signal interrupt +/// - EV_ERR_Interrupted +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets 1 message specified by argument to message queue of ID specified by argument. +/// The user can only get message queue created by user process, and clear 1 message of acquired message queue. +/// An error occurs if message queue of the specified ID doesn't exist. +/// If message is not set in message queue, block until message is sent. +/// However, if a signal interrupt or corresponding message queue is deleted, it will abort and return an error. +/// \~english @see +/// evk_ioctl, evk_get_event +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_wait_message(EV_ID queue_id, /* OUT */EV_Message *message); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_peek_message +/// \~english @par Brief get message event(non-destructive) +/// \~english @param [in] queue_id +/// ID of message event queue +/// \~english @param [out] message +/// message event queue struct +/// \~english @par +/// EV_ID define +/// @code +/// typedef UINT32 EV_ID +/// @endcode + +/// \~english @par +/// EV_Message struct +/// @code +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// typedef struct { +/// EV_ID queueID; +/// UINT32 senderInfo; +/// UINT32 length; +/// UINT32 dummy; +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; +/// } EV_Message; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: The specified queue ID is not existing, +/// or it is not created in current process. +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Message queue corresponding to queue_id doesn't exist +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Get a message event queue whose ID is specified non-destructively. +/// If there is no event, just return. +/// If there is no event, set message->queueID to EV_NO_ID. +/// It is the same with EV_get_message(), except the message is remained in the queue. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_peek_message(EV_ID queue_id, /* OUT */EV_Message *message); // NOLINT (readability/nolint) + +/* \~english Get events(with search criteria) */ + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_find_message_by_sender +/* \~english get event(with search sender infomation condition) */ +/// \~english @param [in] queue_id +/// ID of message event queue +/// \~english @param [in] senderInfo +/// sender information +/// \~english @param [out] message +/// message event struct +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @par +/// EV_Message struct +/// @code +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// typedef struct { +/// EV_ID queueID; +/// UINT32 senderInfo; +/// UINT32 length; +/// UINT32 dummy; +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; +/// } EV_Message; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: The specified queue ID is not existing, +/// or it is not created in current process. +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Not find same sender information's message according to input sender information information +/// - EV_ERR_Invalid_ID +/// - Securing free space of thread information management table (malloc) Failure +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Message queue pool is NULL +/// - Message queue generation corresponding to queue_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// If there is a event whose sender information is same with +/// any event in message event queue whose ID is specified, get the event and delete it from queue. +/// If such a message is not existing, +/// set message->queueID to EV_NO_ID, then return. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_find_message_by_sender(EV_ID queue_id, UINT32 senderInfo, EV_Message *message); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_find_message_by_content +/// \~english @par Brief get message event(search with contents) +/// \~english @param [in] queue_id +/// ID of message event queue +/// \~english @param [in] bytes +/// size of compare bytes +/// \~english @param [in] compare_bytes +/// bytes that used to campare the contents +/// \~english @param [out] message +/// message event struct +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @par +/// EV_Message struct +/// @code +/// #define EV_MAX_MESSAGE_LENGTH 2048 +/// typedef struct { +/// EV_ID queueID; +/// UINT32 senderInfo; +/// UINT32 length; +/// UINT32 dummy; +/// UINT8 message[EV_MAX_MESSAGE_LENGTH]; +/// } EV_Message; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: The specified queue ID is not existing, +/// or it is not created in current process. +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Not find contents's message according to input contents information +/// - EV_ERR_Invalid_ID +/// - Securing free space of thread information management table (malloc) Failure +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Message queue pool is NULL +/// - Message queue generation corresponding to queue_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// If the event in compare bytes is same with +/// any event in message event queue whose ID is specified, +/// get the event and delete it from queue. +/// If such a message is not existing, set message->queueID to EV_NO_ID, then return. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_find_message_by_content(EV_ID queue_id, // NOLINT (readability/nolint) + UINT16 length, // NOLINT (readability/nolint) + const void *compare_bytes, // NOLINT (readability/nolint) + /* OUT */EV_Message *message); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_flag_fd +/// \~english @par Brief +/// Obtain fd for polling flag event +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] fd +/// int * - event flag queue fd for Polling +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @par Prerequisite +/// Execute EV_create_flag(),EV_create_flag_auto_id() and flag has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - Flag corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets fd(File Descriptor) corresponding to flag of ID specified by argument. +/// The user can only get flag created by user process . +/// This fd(File Descriptor) can be used only for designation to poll / select, and operation when other +/// operations are performed is not guaranteed. +/// At the time of poll, only POLLIN can be specified, and at the time of select, +/// it is possible to check only whether it can be read. +/// Also, if flag is deleted in poll / select, it exits poll / select. * In case of poll, POLLERR is set. +/// When calling the same ID more than once, it returns the same fd(File Descriptor) +/// each time (unless destroy / create is done). +/// \~english @see +/// nothing +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_flag_fd(EV_ID flag_id, /* OUT */int *fd); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_get_queue_fd +/// \~english @par Brief +/// Obtain fd for polling message event +/// \~english @param [in] flag_id +/// EV_ID - Flag ID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @param [out] fd +/// int * - Message queue fd for Polling +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error +/// - Message queue corresponding to queue_id doesn't exist +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Gets fd(File Descriptor) corresponding to message queue of ID specified by argument. +/// The user can only get message queue created by user process . +/// This fd(File Descriptor) can be used only for designation to poll / select, +/// and operation when other operations are performed is not guaranteed. +/// At the time of poll, only POLLIN can be specified, and at the time of select, +/// it is possible to check only whether it can be read. +/// Also, if message queue is deleted in poll / select, it exits poll / select. +/// * In case of poll, POLLERR is set. +/// When calling the same ID more than once, it returns the same fd(File Descriptor) +/// each time (unless destroy / create is done). +/// \~english @see +/// nothing +//////////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_get_queue_fd(EV_ID queue_id, /* OUT */int *fd); // NOLINT (readability/nolint) + +/* \~english Functions that specify the module ID (16 bits) instead of the flag ID and queue ID */ + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_moduleID_to_flag_id +/* \~english function group used to specify moduleID(16bit) instead of flag_id, queue_id */ +/// \~english @par Brief change from moduleID to flag_id +/// \~english @param [in] m_id +/// moduleID +/// \~english @retval flag_id +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - none +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of flags with one moduleID. return error:EV_ERR_Exist. +/// This function is only used for generating one event by one module ID. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ID EV_moduleID_to_flagID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_moduleID_to_flag64ID +/// \~english @par Brief change from moduleID to 64bit flag_id +/// \~english @param [in] m_id +/// moduleID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval 64bit flag_id +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - none +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of flags with one moduleID. return error:EV_ERR_Exist. +/// This function is only used for generating one event by one module ID. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ID EV_moduleID_to_flag64ID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_moduleID_to_queueID +/// \~english @par Brief change from moduleID to queue_id +/// \~english @param [in] m_id +/// moduleID +/// \~english @par +/// EV_ID type parameter +/// @code +/// typedef UINT32 EV_ID +/// @endcode +/// \~english @retval queue_id +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - none +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of queues with one moduleID. +// \~english @see none +//////////////////////////////////////////////////////////////////////////////// + +EV_ID EV_moduleID_to_queueID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag_by_mID +/// \~english @par Brief create flag(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist Duplication Error +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The ID is not created by function of EV_moduleID_to_flagID (). +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - flag_id registered in launch thread +/// - Flag corresponding to flag_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of flags with one moduleID.return error:EV_ERR_Exist. +/// This function is only used for generating one event by one module ID. +// \~english @see EV_create_flag +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag_by_mID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_flag64_by_mID +/// \~english @par Brief create 64bit flag(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist Duplication Error +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The ID is not created by function of EV_moduleID_to_flag64ID (). +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - flag_id registered in launch thread +/// - Flag corresponding to flag_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Flag pool is NULL +/// - Flag generation corresponding to flag_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of flags with one moduleID. return error:EV_ERR_Exist. +/// This function is only used for generating one event by one module ID. +// \~english @see EV_create_flag64 +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_create_flag64_by_mID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_create_queue_by_mID +/// \~english @par Brief create queue(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @param [in] length +/// length of message queue +/// \~english @param [in] max_bytes +/// one max bytes for message +/// \~english @param [in] type +/// treat type of receiving events even though the queue is full +/// \~english @par +/// ev_message_queue_type struct +/// @code +/// enum ev_message_queue_type { +/// EV_MESSAGE_QUEUE_TYPE_BUSY, +/// EV_MESSAGE_QUEUE_TYPE_FIFO, +/// EV_MESSAGE_QUEUE_TYPE_REPLACE, +/// }; +/// @endcode +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: set en invalid flag ID +/// \~english @retval EV_ERR_Thread_Over The MAX of event thread. +/// \~english @retval EV_ERR_Exist: a same flag ID is existing +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// There is no prerequisite +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - EV_ERR_Invalid_ID +/// - Startup thread upper limit (16) error +/// - EV_ERR_Thread_Over +/// - queue_id registered in launch thread +/// - Message queue corresponding to queue_id already exists +/// - EV_ERR_Exist +/// - Securing free space of thread information management table (malloc) Failure +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Message queue pool is NULL +/// - Message queue generation corresponding to queue_id failed +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of queues with one moduleID. +// \~english @see EV_create_queue +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR +EV_create_queue_by_mID(UINT16 m_id, // NOLINT (readability/nolint) + UINT8 length, // NOLINT (readability/nolint) + UINT16 max_bytes, // NOLINT (readability/nolint) + EV_Message_Queue_Type type); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_destroy_flag_by_mID +/// \~english @par Brief delete flag(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @par length [in]length of message queue +/// \~english @par max_bytes [in]one max bytes for message +/// \~english @par type [in]treat type of receiving events even though the queue is full +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: set en invalid flag ID +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// - none +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The flag_id of event/message which has not been created. +/// - Flag corresponding to queue_id doesn't exist +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// \~english You can not use this function to +/// \~english create a multiple of flags with one moduleID. return error:EV_ERR_Exist. +/// This function is only used for generating one event by one module ID. +// \~english @see EV_destroy_flag +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_destroy_flag_by_mID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_destroy_queue_by_mID +/// \~english @par Brief delete queue(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Message queue corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// You can not use this function to +/// create a multiple of queues with one moduleID +// \~english @see EV_destroy_queue +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_destroy_queue_by_mID(UINT16 m_id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_set_flag_by_mID +/// \~english @par Brief send flag(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @param [in] bits +/// value of flag +/// \~english @retval EV_OK: normal termination +/// \~english @retval EV_ERR_Invalid_ID: set en invalid flag ID +/// \~english @retval EV_ERR_Fatal: Fatal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - Flag corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sets bit pattern specified by argument to flag of ID specified by argument. +/// When setting a plurality of bit patterns in the same flag, +/// "only OR operation result of all bit patterns" is held in flag. +// \~english @see EV_set_flag +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_set_flag_by_mID(UINT16 m_id, UINT32 bits); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_set_flag64_by_mID +/// \~english @par Brief send 64bit flag(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @param [in] bits +/// value of flag +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid flag_id +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// - none +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect flag_id) +/// --incorrect flag_id:The flag_id of event which has not been created. +/// - Flag corresponding to flag_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sets bit pattern specified by argument to flag of ID specified by argument. +/// When setting a plurality of bit patterns in the same flag, "only +/// OR operation result of all bit patterns" is held in flag. +// \~english @see EV_set_flag64 +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR EV_set_flag64_by_mID(UINT16 m_id, UINT64 bits); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup EV_send_message_by_mID +/// \~english @par Brief send message(moduleID specified) +/// \~english @param [in] m_id +/// moduleID +/// \~english @param [in] bytes +/// number of send bytes +/// \~english @param [in] message +/// pointer to sender contents +/// \~english @param [in] senderInfo +/// sender information +/// \~english @retval EV_OK Successful completion +/// \~english @retval EV_ERR_Invalid_ID Invalid queue_id +/// \~english @retval EV_ERR_Busy Queue overflow +/// \~english @retval EV_ERR_Fatal Abnormal error +/// \~english @par Prerequisite +/// Execute EV_create_queue(),EV_create_queue_auto_id() and message queue has already been created. +/// \~english @par Change of internal state +/// There is no change of the internal Status +/// \~english @par Conditions of processing failure +/// - Input parameter error (specifying incorrect queue_id) +/// --incorrect queue_id:The queue_id of essage which has not been created. +/// - Message queue corresponding to queue_id doesn't exist +/// - EV_ERR_Invalid_ID +/// - Queue overflow in kernel space +/// - EV_ERR_Busy +/// - Access failed from kernel space to user space reference area +/// - Failed to copy data from user space to kernel space +/// - Invalid queue types +/// - EV_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Sends message specified by argument to message moduleID specified by argument. +/// An error occurs when message queue of the specified ID doesn't exist +/// or message size exceeds the specified size. +/// When message queue is FULL, the processing differs depending on the type +/// of message queue specified at the time of creation message queue. +/// \~english @see evk_open, evk_close, evk_ioctl, evk_store_message +//////////////////////////////////////////////////////////////////////////////// + +EV_ERR +EV_send_message_by_mID(UINT16 m_id, // NOLINT (readability/nolint) + UINT16 bytes, // NOLINT (readability/nolint) + const void *message, // NOLINT (readability/nolint) + UINT32 senderInfo); // NOLINT (readability/nolint) + +/** @}*/ // end of event_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +/** + * + * @brief Method to specify module IDs as flag IDs and queue IDs + * + * The function with module ID as an argument directly can be used in the case of that created only + * one flag and queue in the module, other than using macros EV_Flag_ID_Base() or EV_Queue_ID_Base(). + * @see EV_create_flag_by_mID + * @see EV_create_queue_by_mID + * @see EV_destroy_flag_by_mID + * @see EV_destroy_queue_by_mID + * @see EV_set_flag_by_mID + * @see EV_send_message_by_mID + * + * So the following API can be used to convert IDs created using above method to flag IDs or queue ID + * when pass them to other modules. + * @see EV_moduleID_to_flagID(UINT16 m_id) + * @see EV_moduleID_to_queueID(UINT16 m_id) + * + * @see EV_ID_spec + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !__KERNEL__ */ + +#endif // OTHERSERVICE_EV_LIB_H_ diff --git a/otherservice/event_library/library/include/other_service/event_library.h b/otherservice/event_library/library/include/other_service/event_library.h new file mode 100755 index 0000000..ea6285c --- /dev/null +++ b/otherservice/event_library/library/include/other_service/event_library.h @@ -0,0 +1,39 @@ +/* + * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ +/** + * @file + * @brief \~english include all event_library head files + */ +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup event_library + * @ingroup other_service + * @{ + */ +#ifndef OTHERSERVICE_EVENTLIBRARY_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_EVENTLIBRARY_H_ // NOLINT(build/header_guard) + +#include <other_service/ev_lib.h> + +#endif // OTHERSERVICE_EVENTLIBRARY_H_ +/** @}*/ +/** @}*/ +/** @}*/ diff --git a/otherservice/event_library/library/libev.ver b/otherservice/event_library/library/libev.ver new file mode 100755 index 0000000..a361455 --- /dev/null +++ b/otherservice/event_library/library/libev.ver @@ -0,0 +1,41 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +###################### +# ev version script # +###################### +{ + global: + ### .text section ### + EV_*; + ev_lock_func; + ev_lock_line; + ev_lock_pid; + ev_process_global_mutex; + g_destory_message_invalid_id_wrapper_flag; + g_destory_message_fatal_wrapper_flag; + g_receive_message_no_exist_fatal_wrapper_flag; + g_receive_message_fatal_wrapper_flag; + g_send_message_invalid_id_wrapper_flag; + g_send_message_fatal_wrapper_flag; + g_create_event_fatal_wrapper_flag; + g_create_event_set_poll_fatal_wrapper_flag; + ### .data section ### + ### .bss section ### + local: + *; +}; + diff --git a/otherservice/event_library/library/src/ev_lib.c b/otherservice/event_library/library/src/ev_lib.c new file mode 100755 index 0000000..f6b784a --- /dev/null +++ b/otherservice/event_library/library/src/ev_lib.c @@ -0,0 +1,1551 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file ev_lib.c + * @brief Events Library -- Implementing API Functions + */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <sys/prctl.h> +#include <other_service/ev_lib.h> +#include <agldd/evk_lib.h> +#include <agldd/ev_common.h> +#include <assert.h> +#define EV_perror perror +#define EV_assert assert + +/* + * Not use dbg_output in the EV so that the DTV apps and semiconductor vendor use this function. + */ +#define ev_log(format, arg...) \ +{ \ + { \ + char procname[33]; \ + prctl(PR_GET_NAME, procname); \ + int pid = getpid(); \ + printf(format, procname, pid, ##arg); \ + } \ +} + +#define EV_DEBUG_INFO(format, arg...) \ +{ \ + if (getenv("EV_DEBUG") != NULL) { \ + ev_log("[EV: info](%s:%d) " format, ##arg); \ + } \ +} + +#define EV_DEBUG_WARNING(format, arg...) \ +{ \ + ev_log("[EV: warning](%s:%d) " format, ##arg); \ +} + +#define EV_DEBUG_ERR(format, arg...) \ +{ \ + ev_log("[EV: ERR](%s:%d) " format, ##arg); \ +} + +/** @brief Structures for managing ID and FD in use by processes + */ +typedef struct { + EV_ID id; /**< flag/queue ID */ + INT32 fd; /**< file descriptor */ +} +EV_Info; + +/*----------------------------------------*/ +/** @brief EV management information table per thread */ +/*----------------------------------------*/ +typedef struct { + /** Thread calling the EV library */ + pthread_t thread; + /** Registration information by ID */ + EV_Info ev_info[EV_MAX_IDS_IN_THREAD]; + /** Number of registered IDs */ + UINT8 num; +} +EV_thread_info_type; + +/** Thread information acquisition mode */ +#define EV_THREAD_INFO_CREATE 0 +#define EV_THREAD_INFO_PEEK 1 +#define EV_SEARCH_ALL_THREAD -1 + +/* Related process exclusion control in the process */ +const char *g_ev_lock_func; +int g_ev_lock_line; +int g_ev_lock_pid; +pthread_mutex_t g_ev_process_global_mutex = PTHREAD_MUTEX_INITIALIZER; + +#define EV_PROCESS_MUTEX_LOCK \ + pthread_mutex_lock(&g_ev_process_global_mutex); \ + g_ev_lock_func = __FUNCTION__; \ + g_ev_lock_line = __LINE__; \ + g_ev_lock_pid = getpid(); +#define EV_PROCESS_MUTEX_UNLOCK \ + pthread_mutex_unlock(&g_ev_process_global_mutex); + +/** @mainpage + * This document describes the following specifications: + * - Event Library (EV) API specifications + * - Event ID specifications + * + * In principle, the API specifications of the event library for kernel space (EVK) is + * the same as the event library for user space (EV) except for the function name prefixed ""EVK"". + * If there are differences between the EV and EVK, it is described as "difference in kernel version". + */ +/** @defgroup Event Library (EV) API specifications */ +/** @defgroup EV_ID_spec Event ID specifications */ +/** @defgroup EV_m_id Function specifying module ID instead of event ID */ +/** @defgroup EV_in internal specifications of the event library for user space (EV) */ +/** @defgroup EVK_in Internal specifications of the event library for kernel space (EVK) */ +/** @addtogroup EV_in + * @{ */ + +/** EV thread information management table */ +EV_thread_info_type *EV_thread_info[EV_MAX_THREADS_IN_PROCESS]; + +/*---------------------------------------------------------------------- + * Return the registered position of the thread ID + * Allocate and initialize space for unregistered threads + * @brief Sending message (specified module-ID) + * @param index [OUT] Thread index + * @param flag [IN] Operating Mode + ----------------------------------------------------------------------*/ +EV_ERR +EV_thread_id_check(int *index, int flag) { + int i, empty; + + /* Current threadID */ + pthread_t EV_self_thread_id; + + /* Get thread ID */ + EV_self_thread_id = pthread_self(); + + /* Control-process lock */ + EV_PROCESS_MUTEX_LOCK; + + /* Whether or not the thread has already been registered. */ + for(i = 0, empty = -1; i < EV_MAX_THREADS_IN_PROCESS; i++) { + /* Free space */ + if(EV_thread_info[i] == NULL) { + /* Set free space index */ + empty = (empty == -1) ? i: empty; + continue; + } + + if(EV_thread_info[i]->thread == EV_self_thread_id) { + *index = i; + + /* Cancel in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; + return EV_OK; + } + } + + if(flag == EV_THREAD_INFO_PEEK) { + EV_DEBUG_ERR("thread id is not found.\n"); + + /* Cancel in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; + return EV_ERR_Invalid_Thread; + } + + /* If there are no unregistered threads and there is no space */ + if(empty == -1) { + EV_DEBUG_ERR("thread id is full.\n"); + + /* Cancel in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; + return EV_ERR_Thread_Over; + } + + /* Set to free space */ + EV_thread_info[empty] = malloc(sizeof(*(EV_thread_info[empty]))); + EV_thread_info_type *th = EV_thread_info[empty]; + + /* malloc failed */ + if(th == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function malloc + /* Cancel in-process mutual exclusion */ + // LCOV_EXCL_START 5: fail safe for glibc function malloc + + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + + EV_PROCESS_MUTEX_UNLOCK; + return EV_ERR_Fatal; + } + // LCOV_EXCL_STOP + + /* Initialization */ + memset(th, '\0', sizeof(*th)); + th->thread = EV_self_thread_id; + /* th->num = 0; */ + + /* Cancel in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; + + /* Set registration position */ + *index = empty; + + return EV_OK; +} + +// free thread information when create event/message fail and no release thread buffer. +// If no release thread buffer will cause be error: +// Creation event's Thread count num less than MAX count(16) when one thread create event/message +// fail and no longer to create event/message. +static void +free_thread_buffer(int th_index) { + /* in-process mutual exclusion */ + EV_PROCESS_MUTEX_LOCK; + if ((th_index >= 0) + &&(th_index < EV_MAX_THREADS_IN_PROCESS) + && (NULL != EV_thread_info[th_index]) + && (0 == EV_thread_info[th_index]->num)) { + free(EV_thread_info[th_index]); + EV_thread_info[th_index] = NULL; + EV_DEBUG_ERR("Free thread buffer by th_index:%d.\n", th_index); + } + /* in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; +} + +/* EV_info update function */ +static void +add_ev_info(int th_index, EV_ID id, int fd) { + /* Check storage position of ID information */ + /* beginning of in-process mutual exclusion */ + EV_PROCESS_MUTEX_LOCK; + + int id_index = EV_thread_info[th_index]->num; + EV_assert(id_index < EV_MAX_IDS_IN_THREAD); + + /* Set information */ + EV_thread_info[th_index]->ev_info[id_index].id = id; + EV_thread_info[th_index]->ev_info[id_index].fd = fd; + EV_thread_info[th_index]->num++; + + /* end of in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; +} + +/* EV_info search function */ +static int +find_ev_info(int th_index, EV_ID id) { + int i, j, start, end; + int ret = -1; + + /* Search all threads */ + if(th_index == EV_SEARCH_ALL_THREAD) { + start = 0; + end = EV_MAX_THREADS_IN_PROCESS; + } else { + start = th_index; + end = th_index + 1; + } + + /* in-process mutual exclusion */ + EV_PROCESS_MUTEX_LOCK; + + for(j = start; j < end; j++) { + if(EV_thread_info[j] == NULL) { + continue; + } + + for(i = 0; i < EV_thread_info[j]->num; i++) { + if(id == EV_thread_info[j]->ev_info[i].id) { + ret = EV_thread_info[j]->ev_info[i].fd; + break; + } + } + } + + /* Cancel in-process mutual exclusion */ + EV_PROCESS_MUTEX_UNLOCK; + + return ret; +} + +static int +delete_ev_info(EV_ID id) { + int fd = -1; + int i, j; + int found_th_index = -1; + int found_idx = -1; + EV_thread_info_type *th = NULL; + + /* beginning of in-thread mutual exclusion */ + EV_PROCESS_MUTEX_LOCK; + + for(i = 0 ; i < EV_MAX_THREADS_IN_PROCESS && found_idx == -1 ; i++) { + th = EV_thread_info[i]; + if (th == NULL) { + continue; + } + for(j = 0 ; j < th->num ; j++) { + if (th->ev_info[j].id == id) { + fd = th->ev_info[j].fd; + found_th_index = i; + found_idx = j; + break; + } + } + } + + if(found_idx == -1) { + EV_PROCESS_MUTEX_UNLOCK; + return -1; + } + + if (found_idx < th->num - 1) { /* pgr0060 */ + memmove(&(th->ev_info[found_idx]), &(th->ev_info[found_idx+1]), + sizeof(th->ev_info[0]) * (size_t)(th->num - 1 - found_idx)); + } + th->num--; + + /* If everything is deleted */ + if(th->num == 0 && EV_thread_info[found_th_index] != NULL) { + free(EV_thread_info[found_th_index]); + EV_thread_info[found_th_index] = NULL; + } + EV_PROCESS_MUTEX_UNLOCK; + return fd; +} + +/** @} */ +/** @addtogroup EV + * @{ */ + +static EV_ERR +EV_create_flag_in(int th_index, EV_ID flag_id, int is64bit) { + int fd; + + /* Open device driver */ + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + int ret = ioctl(fd, is64bit ? EVK_IOC_CREATE_FLAG64: + EVK_IOC_CREATE_FLAG, flag_id); + int myerrno = errno; + + if(ret < 0) { + if(myerrno == EEXIST) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function ioctl + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + + close(fd); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + EV_DEBUG_ERR("flag_id %x already exists.\n", flag_id); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + return EV_ERR_Exist; // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + } else { + close(fd); + errno = myerrno; + return EV_ERR_Fatal; + } + } + + ret = ioctl(fd, EVK_IOC_SET_POLL, flag_id); + if(ret < 0) { + close(fd); + EV_DEBUG_ERR("set_poll: internal error\n"); + return EV_ERR_Fatal; + } + + add_ev_info(th_index, flag_id, fd); + return EV_OK; +} + +/** @brief Create flag + * + * Create a flag with the given ID. + * Return error if a flag with the same flag ID already exists + * + * @param flag_id [IN]flag ID + * @see EV_ID + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Specified an invalid flag ID + * @retval EV_ERR_Exist: A flag with the same ID already exists + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_create_flag (EV_ID flag_id) { + EV_ERR err; + int th_index; + + /* Flag ID check */ + if(!EV_ID_IS_FLAG(flag_id) || EV_ID_IS_AUTO_ID(flag_id)) { + EV_DEBUG_ERR("create_flag: Invalid flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + return err; + } + + EV_DEBUG_INFO("EV_create_flag (th_index=%d)\n", th_index); + + /* case of already created */ + int fd = find_ev_info(th_index, flag_id); + if(fd >= 0) { + EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id); + return EV_ERR_Exist; + } + + err = EV_create_flag_in(th_index, flag_id, 0); + if (EV_OK != err) { + free_thread_buffer(th_index); + } + + return err; +} + +/** @brief Create 64-bit flag + * + * Create a 64-bit flag with the given ID. + * Return error if a flag with the same flag ID already exists + * + * @param flag_id [IN]64-bit flag ID + * @see EV_ID + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Specified an invalid 64-bit flag ID + * @retval EV_ERR_Exist: A 64-bit flag with same ID already exists + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_create_flag64(EV_ID flag_id) { + EV_ERR err; + int th_index; + + if(!EV_ID_IS_FLAG64(flag_id) || EV_ID_IS_AUTO_ID(flag_id)) { + EV_DEBUG_ERR("create_flag: Invalid flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + return err; + } + + int fd = find_ev_info(th_index, flag_id); + if(fd >= 0) { + EV_DEBUG_ERR("create_flag: You already created flag_id %x.\n", flag_id); + return EV_ERR_Exist; + } + + err = EV_create_flag_in(th_index, flag_id, 1); + if (EV_OK != err) { + free_thread_buffer(th_index); + } + + return err; +} + +/** @brief Create flag (auto-assign ID) + * + * Automatically assign a flag ID and creates a flag. + * Same as EV_create_flag(), except that ID is automatically assigned. + * + * @param flag_id [OUT]Area for storing the assigned flag ID + * + * @see EV_create_flag + */ +EV_ERR +EV_create_flag_auto_id(EV_ID *flag_id) { + EV_assert(flag_id != NULL); + + EV_ERR err; + int fd, th_index; + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG_ID, flag_id); + close(fd); + EV_assert(ret == 0); + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + *flag_id = EV_NO_ID; + return err; + } + + err = EV_create_flag_in(th_index, *flag_id, 0); + if (err != EV_OK) { + free_thread_buffer(th_index); + + *flag_id = EV_NO_ID; + return EV_ERR_Fatal; + } + return EV_OK; +} + +/** @brief Create 64-bit flag(auto-assign ID) + * + * Automatically assign a 64-bit flag ID and creates a 64-bit flag. + * Same as EV_create_flag64(), except that ID is automatically assigned. + * + * @param flag_id [OUT]Area for storing the assigned 64-bit flag ID + * + * @see EV_create_flag64 + */ +EV_ERR +EV_create_flag64_auto_id(EV_ID *flag_id) { + EV_assert(flag_id != NULL); + + EV_ERR err; + int fd, th_index; + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + int ret = ioctl(fd, EVK_IOC_ALLOC_FLAG64_ID, flag_id); + close(fd); + EV_assert(ret == 0); + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + *flag_id = EV_NO_ID; + return err; + } + + err = EV_create_flag_in(th_index, *flag_id, 1); + if (err != EV_OK) { + free_thread_buffer(th_index); + + *flag_id = EV_NO_ID; + return EV_ERR_Fatal; + } + return EV_OK; +} + +static EV_ERR +EV_create_queue_in(int th_index, EV_ID queue_id, UINT8 length, + UINT16 max_bytes, EV_Message_Queue_Type type) { + int fd; + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + EVK_Message_Queue_Request req; + req.queueID = queue_id; + req.length = length; + req.max_bytes = max_bytes; + req.type = type; + + int ret = ioctl(fd, EVK_IOC_CREATE_MESSAGE_QUEUE, &req); + int myerrno = errno; + if (ret < 0) { + if (myerrno == EEXIST) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function ioctl + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + + close(fd); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + EV_DEBUG_ERR("queue %x already exists.\n", queue_id); // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + return EV_ERR_Exist; // LCOV_EXCL_LINE 5: fail safe for glibc function ioctl + } else { + close(fd); + errno = myerrno; + //EV_perror("create queue"); + return EV_ERR_Fatal; + } + } + + ret = ioctl(fd, EVK_IOC_SET_POLL, queue_id); + if (ret < 0) { + close(fd); + EV_DEBUG_ERR("set_poll: internal error\n"); + return EV_ERR_Fatal; + } + + add_ev_info(th_index, queue_id, fd); + return EV_OK; +} + +/** @brief message event queue creation + * + * Create a queue of message event with the specified ID. + * Return error if a queue with the same ID already exists. + * + * A memory area corresponding to the specified maximum number of bytes x queue length is allocated dynamically. + * + * @param queue_id [IN] Message queue ID + * @param length [IN] Message queue length + * @param max_bytes [IN] - Maximum number of bytes per message + * @param type [IN] Type of action to take when more events are received when the queue is full + * @see EV_ID + * @see ev_message_queue_type + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Specified an invalid flag ID + * @retval EV_ERR_Exist: A flag with the same ID already exists + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_create_queue(EV_ID queue_id, UINT8 length, UINT16 max_bytes, + EV_Message_Queue_Type type) { + EV_ERR err; + int th_index; + + if(!EV_ID_IS_QUEUE(queue_id) || EV_ID_IS_AUTO_ID(queue_id)) { + EV_DEBUG_ERR("create_queue: Invalid queue_id %x was specified.\n", + queue_id); + return EV_ERR_Invalid_ID; + } + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + return err; + } + + int fd = find_ev_info(th_index, queue_id); + if(fd >= 0) { + EV_DEBUG_ERR("create_queue: You already created queue_id %x.\n", + queue_id); + return EV_ERR_Exist; + } + + err = EV_create_queue_in(th_index, queue_id, length, max_bytes, type); + if (EV_OK != err) { + free_thread_buffer(th_index); + } + + return err; +} + +/** @brief message event queue creation(auto-assign ID) + * + * Automatically assigns a queue ID and creates a queue for message events. + * Same as EV_create_queue(), except that ID is automatically assigned. + * + * @param queue_id [OUT] Area for storing the assigned flag ID + * @param length [IN] Message queue length + * @param max_bytes [IN] - Maximum number of bytes per message + * @param type [IN] Type of action to take when more events are received when the queue is full + * + * @see EV_create_queue + */ +EV_ERR +EV_create_queue_auto_id(EV_ID *queue_id, UINT8 length, UINT16 max_bytes, + EV_Message_Queue_Type type) { + int th_index; + + EV_assert(queue_id != NULL); + EV_ERR err; + int fd; + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + int ret = ioctl(fd, EVK_IOC_ALLOC_QUEUE_ID, queue_id); + close(fd); + EV_assert(ret == 0); + + /* Thread information check */ + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_CREATE); + if(err != EV_OK) { + *queue_id = EV_NO_ID; + return err; + } + + err = EV_create_queue_in(th_index, *queue_id, length, max_bytes, + type); + if (err != EV_OK) { + free_thread_buffer(th_index); + + *queue_id = EV_NO_ID; + return EV_ERR_Fatal; + } + return EV_OK; +} + +/** @brief Deleting flag event + * + * Delete the flag with the specified ID. + * Only flags created by this process can be deleted. + * + * - differences in kernel versions + * EVK_destroy_flag can be used to delete any existing message event queue. + * + * @note The program wakes up that waiting for this queue (poll or wait) + * due to deletion. + * + * @param flag_id [IN] ID of flag + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_destroy_flag(EV_ID flag_id) { + int fd = delete_ev_info(flag_id); + if (fd < 0) { + EV_DEBUG_ERR("You haven't created flag/queue_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + int ret = ioctl(fd, EVK_IOC_DESTROY_QUEUE, flag_id); + int myerrno = errno; + close(fd); + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_ERR("destroy: no such ID %x\n", flag_id); + return EV_ERR_Invalid_ID; + } else { + errno = myerrno; + EV_perror("destroy"); + return EV_ERR_Fatal; + } + } + return EV_OK; +} + +/** @brief Delete message event queue + * + * Delete the message event queue with the specified ID. + * Only message event queues created by this process can be deleted. + * + * - differences in kernel versions + * EVK_destroy_queue can be used to delete any existing message event queue. + * + * @note The program wakes up that waiting for this queue (poll or wait) + * due to deletion. + * + * @param flag_id [IN] Message event queue ID + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The message queue with the specified ID does not exist, + * or there is no message event queue created by this process. + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_destroy_queue(EV_ID queue_id) { + return EV_destroy_flag(queue_id); +} + +static EV_ERR +EV_get_flag_in(EV_ID flag_id, EV_Flag *flag, int peek_only, int wait) { + EV_assert(flag != NULL); + flag->flagID = EV_NO_ID; + flag->bits = 0; + + if (!EV_ID_IS_FLAG(flag_id)) { + EV_DEBUG_ERR("get_flag: %x is not a flag_id.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id); + if(fd < 0) { + EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + EV_Event ev; + ev.type = EV_EVENT_Flag; + ev.u.flag.flagID = flag_id; + ev.u.flag.bits = 0; + int ret = ioctl( + fd, + (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)), + &ev); + + int myerrno = errno; + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + else if (myerrno == EINTR) { + EV_DEBUG_ERR("get_flag: Interrupted\n"); + return EV_ERR_Interrupted; + } else { + errno = myerrno; + EV_perror("get flag"); + return EV_ERR_Fatal; + } + } + + if (ev.type == EV_EVENT_Flag) { + flag->flagID = ev.u.flag.flagID; + flag->bits = ev.u.flag.bits; + } + return EV_OK; +} + +static EV_ERR +EV_get_flag64_in(EV_ID flag_id, EV_Flag64 *flag, int peek_only, int wait) { + EV_assert(flag != NULL); + flag->flagID = EV_NO_ID; + flag->bits = 0; + + if (!EV_ID_IS_FLAG64(flag_id)) { + EV_DEBUG_ERR("get_flag: %x is not a flag_id.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + int fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id); + if (fd < 0) { + EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + EV_Event ev; + ev.type = EV_EVENT_Flag64; + ev.u.flag64.flagID = flag_id; + ev.u.flag64.bits = 0; + int ret = ioctl( + fd, + (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)), + &ev); + + int myerrno = errno; + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_ERR("get_flag: No such flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + else if (myerrno == EINTR) { + EV_DEBUG_ERR("get_flag: Interrupted\n"); + return EV_ERR_Interrupted; + } else { + errno = myerrno; + EV_perror("get flag"); + return EV_ERR_Fatal; + } + } + + if (ev.type == EV_EVENT_Flag64) { + flag->flagID = ev.u.flag64.flagID; + flag->bits = ev.u.flag64.bits; + } + return EV_OK; +} + +/** @brief Get flag event(non-block) + * + * Get the flag event with the specified ID, and clears the flag. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be used to determine no events. + * Only flags created by this process can be gotten. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] Flag Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_flag(EV_ID flag_id, EV_Flag *flag) { + return EV_get_flag_in(flag_id, flag, 0, 0); +} + +/** @brief Get 64bit flag event(non-block) + * + * Get the 64-bit flag event with the specified ID, and clears the 64-bit flag. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be used to determine no events. + * Only flags created by this process can be gotten. + * Be sure to specify the flag ID created by specifying 64-bits. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] 64-bit flag struct + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_flag64(EV_ID flag_id, EV_Flag64 *flag) { + return EV_get_flag64_in(flag_id, flag, 0, 0); +} + +/** @brief Get flag event(block) + * + * Get the flag event with the specified ID, and clear the flag. + * If there is no event, block until an event is received. + * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned. + * If the flag is deleted while waiting, the wait is suspended + * and EV_ERR_Invalid_ID is returned. + * When interrupted, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be judged to have been interrupted. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] Flag Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_wait_flag(EV_ID flag_id, EV_Flag *flag) { + return EV_get_flag_in(flag_id, flag, 0, 1); +} + +/** @brief Get 64bit flag event(block) + * + * Get the 64-bit flag event with the specified ID, and clear the 64-bit flag. + * If there is no event, block until an event is received. + * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned. + * If the flag is deleted while waiting, the wait is suspended + * and EV_ERR_Invalid_ID is returned. + * When interrupted, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be judged to have been interrupted. + * Be sure to specify the flag ID created by specifying 64 bits. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] 64-bit flag structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_wait_flag64(EV_ID flag_id, EV_Flag64 *flag) { + return EV_get_flag64_in(flag_id, flag, 0, 1); +} + +/** @brief Get flag event(non-destructive) + * + * Get the flag event with the specified ID non-destructively. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be used to determine no events. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] Flag Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_peek_flag(EV_ID flag_id, EV_Flag *flag) { + return EV_get_flag_in(flag_id, flag, 1, 0); +} + +/** @brief Get 64bit flag event(non-destructive) + * + * Gets the 64-bit flag event with the specified ID non-destructively. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in flag->flagID. + * A flag->bits of 0 can also be used to determine no events. + * + * @param flag_id [IN] Message event queue ID + * @param flag [OUT] 64-bit flag structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist, + * Or it is not a flag created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_peek_flag64(EV_ID flag_id, EV_Flag64 *flag) { + return EV_get_flag64_in(flag_id, flag, 1, 0); +} + +static EV_ERR +EV_get_message_in(EV_ID queue_id, EV_Message *message, UINT32 senderInfo, + UINT32 length, const void *compare_bytes, + int peek_only, int wait) { + EV_assert(message != NULL); + message->queueID = EV_NO_ID; + message->senderInfo = 0; + message->length = 0; + + if (!EV_ID_IS_QUEUE(queue_id)) { + EV_DEBUG_ERR("get_message: Invalid queue_id %x\n", queue_id); + return EV_ERR_Invalid_ID; + } + + int fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id); + if(fd < 0) { + EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id); + return EV_ERR_Invalid_ID; + } + + EV_Event ev; + ev.type = EV_EVENT_Message; + ev.u.message.queueID = queue_id; + ev.u.message.senderInfo = senderInfo; + if(length > 0 && compare_bytes != NULL) { + ev.u.message.length = length; + memcpy(ev.u.message.message, compare_bytes, length); + } else { + ev.u.message.length = 0; + } + + int ret = ioctl( + fd, + (peek_only ? EVK_IOC_PEEK_EVENT : (wait ? EVK_IOC_WAIT_EVENT : EVK_IOC_GET_EVENT)), + &ev); + + int myerrno = errno; + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_ERR("No such queue_id %x\n", queue_id); + return EV_ERR_Invalid_ID; + } + else if (myerrno == EINTR) { + EV_DEBUG_INFO("Interrupted.\n"); + return EV_ERR_Interrupted; + } else { + errno = myerrno; + EV_perror("get message"); + return EV_ERR_Fatal; + } + } + + if(ev.type == EV_EVENT_Message) { + message->queueID = ev.u.message.queueID; + message->senderInfo = ev.u.message.senderInfo; + message->length = ev.u.message.length; + memcpy(message->message, ev.u.message.message, + ev.u.message.length); + } + + return EV_OK; +} + +/** @brief Get message events(non-block) + * + * Get one message event from the queue with the specified ID. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in message-> queue_id. + * The acquired message is deleted from the queue. + * + * @param queue_id [IN] Message event queue ID + * @param message [OUT] Message Event Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist + * Or not a message event queue created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_message(EV_ID queue_id, EV_Message *message) { + return EV_get_message_in(queue_id, message, 0, 0, NULL, 0, 0); +} + +/** @brief Get message event(block) + * + * Get one message event from the queue with the specified ID. + * If there is no event, block until an event is received. + * However, if the interrupt is interrupted by a signal interrupt, EV_ERR_Interrupted is returned. + * If the queue is deleted while waiting, the waiting is suspended, + * EV_ERR_Invalid_ID is returned. + * When interrupted, EV_NO_ID is stored in message-> queue_id. + * + * @param queue_id [IN] Message event queue ID + * @param message [OUT] Message Event Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist + * Or not a message event queue created by invoking process + * @retval EV_ERR_Interrupted: Interrupted by a signal interrupt + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_wait_message(EV_ID queue_id, EV_Message *message) { + return EV_get_message_in(queue_id, message, 0, 0, NULL, 0, 1); +} + +/** @brief Get message event(non-destructive) + * + * Get one message event queue of the specified ID non-destructively. + * Even if there is no event, it returns immediately. + * If there are no events, EV_NO_ID is stored in message-> queue_id. + * Same as EV_get_message(), except that the retrieved message remains in the queue. + * + * @param queue_id [IN] Message event queue ID + * @param message [OUT] Message Event Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist + * Or not a message event queue created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_peek_message(EV_ID queue_id, EV_Message *message) { + return EV_get_message_in(queue_id, message, 0, 0, NULL, 1, 0); +} + +static EV_ERR +EV_get_next_event_in(EV_Event *ev, int peek_only) { + int i, th_index; + EV_ERR err; + EVK_Next_Event_Query query; + + EV_assert(ev != NULL); + ev->type = EV_EVENT_None; + + bzero(&query, sizeof(query)); + + err = EV_thread_id_check(&th_index, EV_THREAD_INFO_PEEK); + if(err != EV_OK) { + return err; + } + + EV_PROCESS_MUTEX_LOCK; + query.num = EV_thread_info[th_index]->num; + for(i = 0 ; i < query.num ; i++) { + query.ids[i] = EV_thread_info[th_index]->ev_info[i].id; + } + EV_PROCESS_MUTEX_UNLOCK; + + if (query.num == 0) { + return EV_OK; + } + + int fd; + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + int ret = ioctl( + fd, + (peek_only ? EVK_IOC_PEEK_NEXT_EVENT: EVK_IOC_GET_NEXT_EVENT), + &query); + + int myerrno = errno; + close(fd); + + if (ret < 0) { + errno = myerrno; + EV_perror("get_next_event"); + return EV_ERR_Fatal; + } + memcpy(ev, &(query.ev), sizeof(*ev)); + return EV_OK; +} + +/** @brief Get the first event that arrived(non-block) + * + * Get the first arrival of a flag created by invoking process or an event + * that occurred in the message queue. + * If there are no events, EV_EVENT_None is stored in the ev->type and returned immediately. + * + * @param ev [OUT] Event Structure + * Whether the acquired event type is flag or message is determined + * by ev->type is EV_EVENT_Flag or EV_EVENT_Message. + * + * @retval EV_OK: Normal completion + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_next_event(EV_Event *ev) { + return EV_get_next_event_in(ev, 0); +} + +/** @brief Get the first event that arrived(non-destructive) + * + * Get the first arrival of a flag created by invoking process or an event + * that occurred in the message queue non-destructively. + * The next call to EV_get_next_event() or EV_peek_next_event(), + * return the same event as long as no other program gets it. + * If there are no events, EV_EVENT_None is stored in the ev->type and returned immediately. + * + * @param ev [OUT] Event Structure + * Whether the acquired event flag or message is a message is determined + * by whether ev->type is EV_EVENT_Flag or EV_EVENT_Message. + * + * @retval EV_OK: Normal completion + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_peek_next_event(EV_Event *ev) { + return EV_get_next_event_in(ev, 1); +} + +/** @brief Get message event(search by source info) + * + * If there is an event whose source information matches + * in the message event queue of the specified ID,it is gotten and deleted from the queue. + * If there are no such messages, + * EV_NO_ID is stored in message->queue_id, and the system call returns immediately. + * + * @param queue_id [IN] Message event queue ID + * @param senderInfo [IN] Source Info + * @param message [OUT] Message Event Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist + * Or not a message event queue created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_find_message_by_sender(EV_ID queue_id, UINT32 senderInfo, + EV_Message *message) { + EV_assert(message != NULL); + EV_assert(senderInfo != 0); + return EV_get_message_in(queue_id, message, senderInfo, 0, NULL, 0, 0); +} + +/** @brief Get message event(search by content) + * + * If there is an event with byte sequence matching the specified bytes from the beginning + * in the message event queue of the specified ID,it is gotten and deleted from the queue. + * If there are no such messages, + * EV_NO_ID is stored in message->queue_id, and the system call returns immediately. + * + * @param queue_id [IN] Message event queue ID + * @param bytes [IN] Bytes to compare + * @param compare_bytes [IN] Byte sequence to compare content against + * @param message [OUT] Message Event Structure + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Queue with specified ID does not exist + * Or not a message event queue created by invoking process + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_find_message_by_content(EV_ID queue_id, + UINT16 bytes, const void *compare_bytes, + EV_Message *message) { + EV_assert(message != NULL); + EV_assert(bytes <= EV_MAX_MESSAGE_LENGTH); + EV_assert(compare_bytes != NULL); + + return EV_get_message_in(queue_id, message, 0, bytes, + compare_bytes, 0, 0); +} + +/** @brief Set flag event + * + * Set the flag with the specified ID. + * + * @param queue_id [IN] Flag ID + * @param bits [IN] Flag bit-pattern + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist. + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_set_flag(EV_ID flag_id, UINT32 bits) { + if (!EV_ID_IS_FLAG(flag_id)) { + EV_DEBUG_ERR("set_flag: %x is not a valid flag_id.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + EV_Flag flag; + flag.flagID = flag_id; + flag.bits = bits; + + int ret = ioctl(fd, EVK_IOC_STORE_FLAG, &flag); + int myerrno = errno; + close(fd); + + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_WARNING("set_flag: No such flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + errno = myerrno; + EV_perror("set flag"); + return EV_ERR_Fatal; + } + return EV_OK; +} + +/** @brief Set 64bit flag event + * + * Set the flag with the specified ID. + * + * @param queue_id [IN] Flag ID + * @param bits [IN] Bit pattern of 64-bit flag + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: The flag with the specified ID does not exist. + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_set_flag64(EV_ID flag_id, UINT64 bits) { + if (!EV_ID_IS_FLAG64(flag_id)) { + EV_DEBUG_ERR("set_flag: %x is not a valid flag_id.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + int fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + EV_assert(fd >= 0); + + EV_Flag64 flag; + flag.flagID = flag_id; + flag.bits = bits; + + int ret = ioctl(fd, EVK_IOC_STORE_FLAG64, &flag); + int myerrno = errno; + close(fd); + + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_ERR("set_flag: No such flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + errno = myerrno; + EV_perror("set flag"); + return EV_ERR_Fatal; + } + + return EV_OK; +} + +/** @brief Send Messaging Event + * + * Send a message event to the specified queue ID. + * + * @param queue_id [IN] Queue ID + * @param bytes [IN] Bytes to send + * @param buf [IN] Pointer to the byte sequence to send + * @param senderInfo [IN] Source info + * Specify this option to identify applications, etc. + * When not used, specify 0. + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: Message event queue with specified ID does not exist + * @retval EV_ERR_Busy: Queue overflow + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_send_message(EV_ID queue_id, UINT16 bytes, const void *buf, UINT32 senderInfo) { + EV_assert(buf != NULL); + EV_assert(bytes <= EV_MAX_MESSAGE_LENGTH); + if (!EV_ID_IS_QUEUE(queue_id)) { + EV_DEBUG_ERR("send_message: %x is not a valid queue_id.\n", queue_id); + return EV_ERR_Invalid_ID; + } + + + /* + * Open fd at the first time of send_message in process, + * and continue to use the fd with it open after that. + * Reason: + * - Prevent frequent use of open/close system calls. + * - If the process is nonresident, the fd is close after the process is terminated. + * - Even for resident processes, there is no problem because processes + * that use event library normally continue to use event library + * from the beginning to the end. + */ + static int fd = -1; + EV_PROCESS_MUTEX_LOCK; + if (fd < 0) { + fd = open(EVK_DEV_NAME, O_RDWR|O_CLOEXEC); + if (fd < 0) { // LCOV_EXCL_BR_LINE 5: fail safe for glibc function open + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + + EV_PROCESS_MUTEX_UNLOCK; // LCOV_EXCL_LINE 5: fail safe for glibc function open + return EV_ERR_Fatal; // LCOV_EXCL_LINE 5: fail safe for glibc function open + } + fcntl(fd, F_SETFD, FD_CLOEXEC|(fcntl(fd, F_GETFD, 0))); + } + + EV_Message msg; + msg.queueID = queue_id; + msg.senderInfo = senderInfo; + msg.length = bytes; + memcpy(msg.message, buf, bytes); + + int ret = ioctl(fd, EVK_IOC_STORE_MESSAGE, &msg); + int myerrno = errno; + EV_PROCESS_MUTEX_UNLOCK; + + if (ret < 0) { + if (myerrno == ENOENT) { + EV_DEBUG_WARNING("send_message: No such queue_id %x.\n", queue_id); + return EV_ERR_Invalid_ID; + } else if (myerrno == EBUSY) { + EV_DEBUG_WARNING("send_message: queue_id %x returned BUSY.\n", queue_id); + return EV_ERR_Busy; + } + + errno = myerrno; + EV_perror("send message"); + return EV_ERR_Fatal; + } + + return EV_OK; +} + +/** @brief Get fd for poll flag event + * + * Get file descriptor (FD) that used to wait for a flag + * with the specified ID in a poll/select. + * Only flags created by invoked process can be specified. + * + * This FD can only be used to specify a poll/select. + * Subsequent operations are not guaranteed if any other operations are performed. + * When use poll, only POLLIN can be specified in events. + * When use select, you can only check if it is readable. + * + * If the same flag_id is called more than once, + * The same FD is returned each time (unless there is a destroy/create during that time). + * + * - differences in kernel versions + * - This API is not provided in the EVK. + * + * @note If the flag is deleted during poll/select using the FD gotten by the API, + * the poll/select is exited. + * POLLERR is set as event for poll. + * + * @param flag_id [IN] Flag ID + * @param fd [OUT] Pointer to the area to store the file descriptor + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified. + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_flag_fd(EV_ID flag_id, int *fd) { + EV_assert(fd != NULL); + *fd = -1; + if ((!EV_ID_IS_FLAG(flag_id))&& (!EV_ID_IS_FLAG64(flag_id))) { + EV_DEBUG_ERR("get_flag_fd: %x is not a valid flag_id.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + *fd = find_ev_info(EV_SEARCH_ALL_THREAD, flag_id); + if (*fd < 0) { + EV_DEBUG_ERR("You have not created flag_id %x.\n", flag_id); + return EV_ERR_Invalid_ID; + } + + return EV_OK; +} + +/** @brief Get fd for message event queue poll + * + * Get file descriptor (FD) that used to wait for a queue + * with the specified ID in a poll/select. + * Only message event queues created by invoked process can be specified. + * + * This FD can only be used to specify a poll/select. + * Subsequent operations are not guaranteed if any other operations are performed. + * When use poll, only POLLIN can be specified in events. + * When use select, you can only check if it is readable. + * + * If the same queue_id is called more than once, + * The same FD is returned each time (unless there is a destroy/create during that time). + * + * - differences in kernel versions + * - This API is not provided in the EVK. + * + * @note If the queue is deleted during poll/select using the FD gotten by the API, + * the poll/select is exited. + * POLLERR is set as event for poll. + * + * @param queue_id [IN] Message event queue ID + * @param fd [OUT] Pointer to the area to store the file descriptor + * + * @retval EV_OK: Normal completion + * @retval EV_ERR_Invalid_ID: An invalid flag ID was specified. + * @retval Otherwise: FATAL error + */ +EV_ERR +EV_get_queue_fd(EV_ID queue_id, int *fd) { + EV_assert(fd != NULL); + *fd = -1; + if (!EV_ID_IS_QUEUE(queue_id)) { + EV_DEBUG_ERR("get_queue_fd: %x is not a valid queue_id.\n", + queue_id); + return EV_ERR_Invalid_ID; + } + + *fd = find_ev_info(EV_SEARCH_ALL_THREAD, queue_id); + if (*fd < 0) { + EV_DEBUG_ERR("You have not created queue_id %x.\n", queue_id); + return EV_ERR_Invalid_ID; + } + return EV_OK; +} + +/* \~english Functions that specify the module ID (16 bits) instead of the flag ID and queue ID */ +EV_ID EV_moduleID_to_flagID(UINT16 mID) +{ + return EV_Flag_ID_Base(mID); +} + +EV_ID EV_moduleID_to_flag64ID(UINT16 mID) +{ + return EV_Flag64_ID_Base(mID); +} + +EV_ID EV_moduleID_to_queueID(UINT16 mID) +{ + return EV_Queue_ID_Base(mID); +} + +EV_ERR EV_create_flag_by_mID(UINT16 mID) +{ + return EV_create_flag(EV_moduleID_to_flagID(mID)); +} + +EV_ERR EV_create_flag64_by_mID(UINT16 mID) +{ + return EV_create_flag64(EV_moduleID_to_flag64ID(mID)); +} + +EV_ERR EV_create_queue_by_mID(UINT16 mID, UINT8 length,UINT16 max_bytes, + EV_Message_Queue_Type type) +{ + return EV_create_queue(EV_moduleID_to_queueID(mID), length, max_bytes, type); +} + +EV_ERR EV_destroy_flag_by_mID(UINT16 mID) +{ + return EV_destroy_flag(EV_moduleID_to_flagID(mID)); +} + +EV_ERR EV_destroy_queue_by_mID(UINT16 mID) +{ + return EV_destroy_queue(EV_moduleID_to_queueID(mID)); +} + +EV_ERR EV_set_flag_by_mID(UINT16 mID, UINT32 bits) +{ + return EV_set_flag(EV_moduleID_to_flagID(mID), bits); +} + +EV_ERR EV_set_flag64_by_mID(UINT16 mID, UINT64 bits) +{ + return EV_set_flag64(EV_moduleID_to_flag64ID(mID), bits); +} + +EV_ERR EV_send_message_by_mID(UINT16 mID, UINT16 bytes, const void *message, + UINT32 senderInfo) +{ + return EV_send_message(EV_moduleID_to_queueID(mID), + bytes, message, senderInfo); +} +/** @} */ diff --git a/otherservice/other_service.mk b/otherservice/other_service.mk new file mode 100755 index 0000000..85a2f2c --- /dev/null +++ b/otherservice/other_service.mk @@ -0,0 +1,42 @@ +############################################################# +# +# Common Makefile for other_service +# Copyright (C) 2017-2020 TOYOTA MOTOR CORPORATION +# +# 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. +# +############################################################# + +CURRENT_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +############################################################# +# COMPONENT_NAME must not be blank and be named snake_case + +COMPONENT_NAME := other_service + +############################################################# + +############################################################# +# You can add several flags and libraries. +# When you add -I or -L path, DO NOT USE relative path. +# Instead, use $(CURRENT_DIR) variable +# that indicates the path this .mk file is stored. + +COMPONENT_CFLAGS := +COMPONENT_CXXFLAGS := +COMPONENT_LDLIBS := +COMPONENT_LDFLAGS := + +############################################################## + +include $(SDKTARGETSYSROOT)/usr/agl/share/agl.mk diff --git a/otherservice/posix_based_os001_legacy_library/LICENSE b/otherservice/posix_based_os001_legacy_library/LICENSE new file mode 100755 index 0000000..f433b1a --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/LICENSE @@ -0,0 +1,177 @@ + + 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 diff --git a/otherservice/posix_based_os001_legacy_library/Makefile.client b/otherservice/posix_based_os001_legacy_library/Makefile.client new file mode 100755 index 0000000..4192704 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/Makefile.client @@ -0,0 +1,20 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + + +SUBDIRS := library + +include ../other_service.mk diff --git a/otherservice/posix_based_os001_legacy_library/library/Makefile b/otherservice/posix_based_os001_legacy_library/library/Makefile new file mode 100755 index 0000000..874a431 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/Makefile @@ -0,0 +1,48 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +INST_SHLIBS = libPosixBasedOS001legacy + +VPATH = ./src ./include/$(COMPONENT_NAME)/ +INST_HEADERS = strlcat.h strlcpy.h \ +itoa.h \ +PosixBasedOS001TimeApi.h \ +PosixBasedOS001ClockCycleApi.h \ +ultoa.h \ +posix_based_os001_legacy_library.h + +libPosixBasedOS001legacy_SRCS += strlcat.c strlcpy.c \ +itoa.c \ +PosixBasedOS001TimeApi.c \ +PosixBasedOS001ClockCycleApi.c \ +ultoa.c + +CPPFLAGS = -I./include + +LDFLAGS += -Wl,--no-undefined +LDFLAGS += -Wl,--no-as-needed +CPPFLAGS += -Werror=implicit-function-declaration +CPPFLAGS += -Werror=format-security + +CPPFLAGS += -Wconversion +CPPFLAGS += -Wpointer-to-int-cast +CPPFLAGS += -Wint-to-pointer-cast +CPPFLAGS += -Wpointer-arith +CPPFLAGS += -Wformat + + + +include ../../other_service.mk diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001ClockCycleApi.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001ClockCycleApi.h new file mode 100755 index 0000000..2c3fb44 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001ClockCycleApi.h @@ -0,0 +1,83 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_CLOCK_CYCLE_API_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_CLOCK_CYCLE_API_H_ // NOLINT(build/header_guard) + +#include <stdint.h> + +/******************************************************************************/ +/* define */ + +/******************************************************************************/ +/* typedef */ + +/******************************************************************************/ +/* struct */ + + +/******************************************************************************/ +/* function */ +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file PosixBasedOS001ClockCycleApi.h + * @brief \~english This file provides ClockCycle API to get number of clock cycles. + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup ClockCycle +/// \~english @par Brief +/// Get the number of clock cycles. +/// \~english @retval Microsecond +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @par Detail +/// None +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +uint64_t ClockCycle(void); + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_CLOCK_CYCLE_API_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001TimeApi.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001TimeApi.h new file mode 100755 index 0000000..616bda4 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/PosixBasedOS001TimeApi.h @@ -0,0 +1,86 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +// libraries for replacing PosixBasedOS001 to Linux +// PosixBasedOS001TimeApi.h + +#ifndef OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_TIMEAPI_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_TIMEAPI_H_ // NOLINT(build/header_guard) + +#include <sys/types.h> + +/*******************************************************************************/ +/* define */ + +/*******************************************************************************/ +/* typedef */ + +/*******************************************************************************/ +/* struct */ + +/*******************************************************************************/ +/* function */ +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file PosixBasedOS001TimeApi.h + * @brief \~english This file provides delay API to delay for the specified time. + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup delay +/// \~english @par Brief +/// Delay for the specified time. +/// \~english @param [in] duration +/// unsigned int - The number of milliseconds for which to suspend the calling thread from execution +/// \~english @retval EOK +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Detail +/// If duration is more than 1000 milliseconds, return immediately. +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +unsigned int delay(unsigned int duration); // NOLINT(readability/nolint) + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_TIMEAPI_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/itoa.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/itoa.h new file mode 100755 index 0000000..4f26634 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/itoa.h @@ -0,0 +1,74 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ITOA_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ITOA_H_ // NOLINT(build/header_guard) + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file itoa.h + * @brief \~english This file provides itoa API to convert integer value to null terminated string + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup itoa +/// \~english @par Brief +/// Integer value to null terminated string. +/// \~english @param [in] value +/// int - value Number to convert +/// \~english @param [out] buff +/// char - buff Result string +/// \~english @param [in] radix +/// int - radix Radix of value +/// \~english @retval String pointer +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @par Detail +/// None +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +char* itoa(int value, char buff[], int radix); // NOLINT(readability/nolint) + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ITOA_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/posix_based_os001_legacy_library.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/posix_based_os001_legacy_library.h new file mode 100755 index 0000000..188cb01 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/posix_based_os001_legacy_library.h @@ -0,0 +1,46 @@ +/* + * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION + * + * 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. + */ +/** + * @file + * @brief \~english include all posix_based_os001_legacy_library head files + */ +#ifndef OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_H_ // NOLINT(build/header_guard) +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + + +#include <other_service/PosixBasedOS001ClockCycleApi.h> +#include <other_service/PosixBasedOS001TimeApi.h> +#include <other_service/itoa.h> +#include <other_service/strlcat.h> +#include <other_service/strlcpy.h> +#include <other_service/ultoa.h> + + +/** @}*/ // posix_based_os001_legacy_library +/** @}*/ // other_service +/** @}*/ // BaseSystem +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcat.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcat.h new file mode 100755 index 0000000..d42c136 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcat.h @@ -0,0 +1,78 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCAT_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCAT_H_ // NOLINT(build/header_guard) + +#include <strings.h> + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file strlcat.h + * @brief \~english This file provides strlcat API to concatenate strings + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup strlcat +/// \~english @par Brief +/// Concatenate strings +/// \~english @param [in/out] dst +/// char * - Destination string +/// \~english @param [in] src +/// const char * - Concatenated string +/// \~english @param [in] siz +/// size_t - Size of dst +/// \~english @retval String length after concatenation +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @par Detail +/// Appends src to string dst of size siz (unlike strncat, siz is the full size of dst, not space left). +/// At most siz-1 characters will be copied. Always NUL terminates (unless siz <= strlen(dst)). +/// Returns strlen(src) + MIN(siz, strlen(initial dst)). If retval >= siz, truncation occurred. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +size_t strlcat(char *dst, const char *src, size_t siz); // NOLINT(readability/nolint) + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCAT_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcpy.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcpy.h new file mode 100755 index 0000000..14c51fe --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/strlcpy.h @@ -0,0 +1,78 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCPY_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCPY_H_ // NOLINT(build/header_guard) + +#include <strings.h> + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file strlcpy.h + * @brief \~english This file provides API to copy string + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup strlcpy +/// \~english @par Brief +/// Copy string +/// \~english @param [in/out] dst +/// char * - Destination string +/// \~english @param [in] src +/// const char * - Copy string +/// \~english @param [in] siz +/// size_t - Size of dst +/// \~english @retval Length of copied character string +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @par Detail +/// Copy src to string dst of size siz. At most siz-1 characters will be copied. +/// Always NUL terminates (unless siz == 0). +/// Returns strlen(src); if retval >= siz, truncation occurred. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +size_t strlcpy(char *dst, const char *src, size_t siz); // NOLINT(readability/nolint) + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_STRLCPY_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/include/other_service/ultoa.h b/otherservice/posix_based_os001_legacy_library/library/include/other_service/ultoa.h new file mode 100755 index 0000000..2291f1a --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/include/other_service/ultoa.h @@ -0,0 +1,74 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ULTOA_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ULTOA_H_ // NOLINT(build/header_guard) + +#ifdef __cplusplus +extern "C" { +#endif +/** + * @file ultoa.h + * @brief \~english This file provides ultoa API to convert unsigned long type to NULL terminated character string + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup posix_based_os001_legacy_library + * @ingroup other_service + * @{ + */ + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup ultoa +/// \~english @par Brief +/// Convert unsigned long type to NULL terminated character string. +/// \~english @param [in] value +/// int - value Number to convert +/// \~english @param [out] buff +/// char - buff Result string +/// \~english @param [in] radix +/// int - radix Radix of value +/// \~english @retval String pointer +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Detail +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +char *ultoa(unsigned long value, char *buf, int radix); // NOLINT (readability/nolint) + +/** @}*/ // end of posix_based_os001_legacy_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_POSIXBASEDOS001LEGACYLIBRARY_POSIXBASEDOS001_ULTOA_H_ diff --git a/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001ClockCycleApi.c b/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001ClockCycleApi.c new file mode 100755 index 0000000..b4e73c5 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001ClockCycleApi.c @@ -0,0 +1,56 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 <other_service/PosixBasedOS001ClockCycleApi.h> +#include <time.h> + +/******************************************************************************/ +/* +Overview :GetTickCount() like Win32 API +Arguments :void +Return :OK:usec NG:0 +Note : +*/ +static uint64_t GetTickCount(void ) +{ + struct timespec tp; + /*--------------------------------------------------------------------*/ + + if(clock_gettime(CLOCK_MONOTONIC, &tp) != 0) // LCOV_EXCL_BR_LINE 5: fail safe for libc clock_gettime + { + return 0; + } + + return (uint64_t)(tp.tv_sec * 1000000 + tp.tv_nsec / 1000); +} + + +/******************************************************************************/ +/* +Overview :Get the number of clock cycles +Arguments :void +Return :OK:usec NG:0 +Note : +*/ +uint64_t ClockCycle( void ) +{ + return GetTickCount(); +} + +/******************************************************************************/ +/* End of souce code.*/ +/******************************************************************************/ + diff --git a/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001TimeApi.c b/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001TimeApi.c new file mode 100755 index 0000000..2a1dd72 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/PosixBasedOS001TimeApi.c @@ -0,0 +1,57 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +// libraries for replacing PosixBasedOS001 to Linux +// PosixBasedOS001TimeApi.c + +#include <other_service/PosixBasedOS001TimeApi.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> // for using usleep() +#include <time.h> // for using clock() + +// delay() +// NOTE: Control a device +// duration +// The number of milliseconds for which to suspend the calling thread from execution. +// +// _CWORD72_ doesnot use return code of delay, and sets 1,100,and 1000. +unsigned int delay( unsigned int duration ){ + + int ret; + useconds_t duration_usec = duration * 1000; + + ret = EOK; + + if( duration_usec > 1000000 ){ + printf("delay():over flow!\n"); + }else{ + + // using usec order + ret = usleep(duration_usec); + + // error of usleep() = 0(E_OK), -1(ERROR) + // delay() cannot return error code. [data type unmatch] + if(ret < 0){ // LCOV_EXCL_BR_LINE 5: fail safe for libc function usleep + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("delay():error!\n"); // LCOV_EXCL_LINE 5: fail safe for libc function usleep + } + } + + return EOK; +} diff --git a/otherservice/posix_based_os001_legacy_library/library/src/itoa.c b/otherservice/posix_based_os001_legacy_library/library/src/itoa.c new file mode 100755 index 0000000..49a24bf --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/itoa.c @@ -0,0 +1,45 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +char* itoa( int value, char buff[], int radix ) { + static const char table[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + char *head = buff; + char *tail = buff; + char temp; + + // Converting minus sign to character + if ( value < 0 ){ + *tail++ = '-'; + value = -value; + } + // Converting integer to character + if ( value == 0 ){ + *tail++ = '0'; + } + else for ( head = tail ; value != 0 ; value /= radix ){ + *tail++ = table[ value % radix ]; + } + *tail = '\0'; + + // swapping characters + for ( tail-- ; head < tail ; head++, tail-- ){ + temp = *head; + *head = *tail; + *tail = temp; + } + + return buff; +} diff --git a/otherservice/posix_based_os001_legacy_library/library/src/strlcat.c b/otherservice/posix_based_os001_legacy_library/library/src/strlcat.c new file mode 100755 index 0000000..8d11eab --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/strlcat.c @@ -0,0 +1,40 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 <sys/types.h> +#include <string.h> + +size_t +strlcat(char *dst, const char *src, size_t size) +{ + size_t dstsize, srcsize, copysize; + + dstsize = strnlen(dst, size); + srcsize = strlen(src); + if (dstsize == size) { + return dstsize + srcsize; + } + + copysize = size - dstsize - 1; + if (srcsize < copysize) { + copysize = srcsize; + } + + memcpy(dst + dstsize, src, copysize); + dst[dstsize + copysize] = '\0'; + + return dstsize + srcsize; +} diff --git a/otherservice/posix_based_os001_legacy_library/library/src/strlcpy.c b/otherservice/posix_based_os001_legacy_library/library/src/strlcpy.c new file mode 100755 index 0000000..f440c0e --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/strlcpy.c @@ -0,0 +1,49 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 <sys/types.h> +#include <string.h> + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return (size_t)(s - src - 1); /* count does not include NUL */ +} diff --git a/otherservice/posix_based_os001_legacy_library/library/src/ultoa.c b/otherservice/posix_based_os001_legacy_library/library/src/ultoa.c new file mode 100755 index 0000000..1984246 --- /dev/null +++ b/otherservice/posix_based_os001_legacy_library/library/src/ultoa.c @@ -0,0 +1,33 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 <string.h> + +char *ultoa(unsigned long value, char *buf, int radix) +{ + const static char c[] = "0123456789abcdef"; + char b[65]; + char *p = b + sizeof(b); + + *--p ='\0'; + do { + *--p = c[value % (unsigned int)radix]; + value /= (unsigned int)radix; + } while (value); + strcpy(buf, p); + + return buf; +} diff --git a/otherservice/rpc_library/LICENSE b/otherservice/rpc_library/LICENSE new file mode 100755 index 0000000..f433b1a --- /dev/null +++ b/otherservice/rpc_library/LICENSE @@ -0,0 +1,177 @@ + + 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 diff --git a/otherservice/rpc_library/Makefile.client b/otherservice/rpc_library/Makefile.client new file mode 100755 index 0000000..36a4dee --- /dev/null +++ b/otherservice/rpc_library/Makefile.client @@ -0,0 +1,19 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +SUBDIRS := tool_for_arm library + +include ../other_service.mk diff --git a/otherservice/rpc_library/library/Makefile b/otherservice/rpc_library/library/Makefile new file mode 100755 index 0000000..75c734a --- /dev/null +++ b/otherservice/rpc_library/library/Makefile @@ -0,0 +1,46 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +INST_SHLIBS := librpc +librpc_SRCS := rpc_lib.c \ + rpc_marshall.c \ + rpc_event.c \ + rpc_udp.c \ + rpc_thread.c + +CPPFLAGS = -I../tool \ + -I./include \ + -D_GNU_SOURCE \ + +CPPFLAGS += -Wl,--no-undefined +CPPFLAGS += -Werror=implicit-function-declaration +CPPFLAGS += -Werror=format-security + +CPPFLAGS += -Wconversion +CPPFLAGS += -Wpointer-to-int-cast +CPPFLAGS += -Wint-to-pointer-cast +CPPFLAGS += -Wpointer-arith +CPPFLAGS += -Wformat +LDFLAGS += -Wl,--no-as-needed +LDLIBS := -lrt -lcommon + + +VPATH = ./src ./include/$(COMPONENT_NAME) +INST_HEADERS := rpc.h \ + rpc_id.h \ + rpc_library.h \ + +include ../../other_service.mk diff --git a/otherservice/rpc_library/library/include/other_service/rpc.h b/otherservice/rpc_library/library/include/other_service/rpc.h new file mode 100755 index 0000000..f669331 --- /dev/null +++ b/otherservice/rpc_library/library/include/other_service/rpc.h @@ -0,0 +1,765 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc.h + * @brief \~english RPC library --API define header file + */ +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup rpc_library + * @ingroup other_service + * @{ + */ +#ifndef OTHERSERVICE_RPC_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPC_H_ // NOLINT(build/header_guard) + +#include <stdio.h> +#include <unistd.h> + +#include <other_service/rpc_id.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief \~english RPC_ID max number +*/ +#define RPC_MAX_THREADS_IN_PROCESS 64 + +/** @brief \~english fd max number in one process. + * 0 = main/sub thread communication pipe fd. + * 1 = inotify() process listen fd. + * 2~129 = even num : API request data socket. + * odd num : secure stream socket. + * */ +#define RPC_MAX_FD_IN_PROCESS 130 + + +#define RPC_MAX_API_ARG_NUM 8 +///< \~english API call parameter max num + + +#define RPC_MAX_API_ARG_SIZE 1024 +///< \~english API call one parameter max byte + +#define RPC_MAX_API_ARG_TOTAL_SIZE 1500 +///< \~english API call all parameter max byte + +#define RPC_MAX_APICALL_QUEUE 16 +///< \~english API call max queue num + +#define RPC_NO_PORT 0 +///< \~english invalid port num + +/** @brief \~english RPC library function return value + */ +enum rpc_result { // NOLINT (readability/nolint) + RPC_OK = 0, ///< \~english ok + RPC_ERR_No_Response = 0x8fff0000, ///< \~english has no response + RPC_ERR_Timeout, ///< \~english timeout + RPC_ERR_Busy, ///< \~english busy + RPC_ERR_API_Error, ///< \~english API error + RPC_ERR_API_Fatal, ///< \~english API fatal + RPC_ERR_Fatal, ///< \~english fatal + RPC_ERR_Configuration, ///< \~english configuration + RPC_ERR_Server_DeadLock, ///< \~english server deadlock + RPC_ERR_Server_Finish, ///< \~english server finish + RPC_ERR_Reject_connect, ///< \~english reject connect +}; +/** @brief \~english RPC library function return type + * @see rpc_result + * */ +typedef INT32 RPC_Result; + +/** @brief \~english RPC ID + * + */ +typedef UINT32 RPC_ID; + +#define RPC_NO_ID RPC_NO_PORT +///< \~english The ID when destination is invalid + +#define RPC_SELF_ID RPC_NO_PORT +///< \~english The ID when destination is self + +/** @brief \~english The ID when destination is any + * */ +#define RPC_ANY_ID RPC_NO_PORT + + +typedef RPC_Result (*RPC_dispatch_func_t)(UINT16 api_num, + const char *args_string, + unsigned int args_size, + char **ret_string, + unsigned int *ret_bytes); + +#ifdef RPC_DISPATCH_FUNC +#error "Please include <rpc.h> before \"*_srvr.h\"." +#else /* !RPC_DISPATCH_FUNC */ +#define RPC_DISPATCH_FUNC NULL +#endif /* !RPC_DISPATCH_FUNC */ + +/* RPC Library Start Function Macro */ +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_START_SERVER +/// \~english @par Brief +/// server start(certification of the client by UID) +/// \~english @param [in] ID +/// RPC_ID - program's RPC_ID +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Case of an input parameter error +/// - Case of fail to information generation +/// - When RPC_start has already been issued +/// - Case of space reservation fails +/// - Case of socket generation fails +/// - Case of socket allocation fails +/// - Case of creating a pipe fails +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - Used when the server program of RPC-API performs RPC library use start processing +/// - ID specifies a symbol in the form of XXX_RPC_ID defined by rpc_id.h +/// - Only one server program is permitted per thread +/// - When the server program calls the API as a client of another server, +/// it only needs to call RPC_START_SERVER, there is no need to call RPC_START_CLIENT +/// \~english @see RPC_start, RPC_end +//////////////////////////////////////////////////////////////////////////////////// +#define RPC_START_SERVER(ID) RPC_start((ID), RPC_DISPATCH_FUNC, NULL, NO_SECURE_CHECK) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_START_SECURE_SERVER +/// \~english @par Brief +/// server start(certification of the client by UID) +/// \~english @param [in] ID +/// RPC_ID - program's RPC_ID +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Case of an input parameter error +/// - Case of fail to information generation +/// - When RPC_start has already been issued +/// - Case of space reservation fails +/// - Case of socket generation fails +/// - Case of socket allocation fails +/// - Case of creating a pipe fails +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - Used when the server program of RPC-API performs RPC library use start processing +/// - ID specifies a symbol in the form of XXX_RPC_ID defined by rpc_id.h +/// - Only one server program is permitted per thread +/// - When the server program calls the API as a client of another server, +/// it only needs to call RPC_START_SERVER, there is no need to call RPC_START_CLIENT +/// \~english @see RPC_start, RPC_end +//////////////////////////////////////////////////////////////////////////////////// +#define RPC_START_SECURE_SERVER(ID) RPC_start((ID), RPC_DISPATCH_FUNC, NULL, NEED_SECURE_CHECK) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_START_CLIENT +/// \~english @par Brief +/// client start +/// \~english @param [out] pID +/// RPC_ID * - auto allocated program's RPC_ID +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - input parameter error +/// - Unable to get the rpc lib info for the self-thread. +/// - Memory allocation fail for id info. +/// - Socket generation fail. +/// - Socket allocation fail. +/// - Unable to get the socket name. +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - This macro supports only client function of RPC library. +/// - Run the start processing by using this macro only when the APIs provided by the other program are called. +/// \~english @see RPC_start, RPC_end +//////////////////////////////////////////////////////////////////////////////////// +#define RPC_START_CLIENT(pID) RPC_start((UINT16)RPC_NO_ID, NULL, (pID), NO_SECURE_CHECK) +//!< \~english client start + +/* Client authentication by registering the server's UID list */ +#define NEED_SECURE_CHECK 1 ///< \~english has secure check +#define NO_SECURE_CHECK 0 ///< \~english has no secure check + +/* Setting whether to register UID list of server */ +#define REGISTERED 1 ///< \~english registered +#define NO_REGISTERED 0 ///< \~english not registered + +/* API Function Prototypes in the RPC Library */ +RPC_Result RPC_start(RPC_ID id, RPC_dispatch_func_t func, RPC_ID *pID, INT32 secure_check); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_get_fd +/// \~english @par Brief +/// Get the file descriptor to judge whether there is the request of RPC-API call or not. +/// \~english @param [in] id +/// RPC_ID - server program's RPC_ID +/// \~english @param [out] fd +/// int * - area for fd +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// RPC_START_SERVER or RPC_START_SECURE_SERVER is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Argument(id) is RPC_NO_ID. +/// - Argument(fd) is NULL. +/// - Unable to get the rpc lib info for the self-thread. +/// - RPC sub thread doesn't exist. +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - This function returns the fd(file descriptor) to judge whether there is the request to server. +/// - Return value(fd) is used only for poll function or select function parameter. +/// - Usage +/// - To get fd from this function. +/// - Wait for the data to use poll function or select function. +/// - After that, call RPC_process_API_request function. +/// - As a result, the API call request from client is done(that is, run the server API). +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_get_fd(RPC_ID id, int *fd); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_process_API_request +/// \~english @par Brief +/// Run the processing of RPC-API call +/// \~english @param [in] id +/// RPC_ID - server program's RPC_ID +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// RPC_START_SERVER or RPC_START_SECURE_SERVER is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Argument(id) is RPC_NO_ID. +/// - Unable to get the rpc lib info for the self-thread. +/// - RPC sub thread doesn't exist. +/// - fail to send UDP packet. +/// - API processing from the client returns the error. +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - Process all the queued API running requests from the client. +/// - API function of server program is called in this function. +/// - If there are no requests to run API, this function doesn't wait and return immediately. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_process_API_request(RPC_ID id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_end +/// \~english @par Brief +/// End processing of RPC library. +/// \~english @param [in] id +/// RPC_ID - program's RPC_ID +/// \~english @retval None +/// \~english @par Prerequisite +/// RPC_START_SERVER or RPC_START_SECURE_SERVER or RPC_START_CLIENT is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - End processing(socket close and memory release etc) is done. +/// - When there are no more program that uses RPC_ID, RPC sub thread started by RPC_start will be ended. +/// - Need to call this function before the program is ended. +/// - Need to call this function from which the thread called RPC_start. +/// - Nothing is done when incorrect or no more used RPC_ID is designated. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +void RPC_end(RPC_ID id); // NOLINT (readability/nolint) + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_end_all +/// \~english @par Brief +/// End processing of RPC library(forcing to clean up). +/// \~english @par Prerequisite +/// - None +/// \~english @par Change of internal state +/// - None +/// \~english @par Conditions of processing failure +/// - None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Delete the socket files created in process for communication. /n +/// The program which use RPC library must call RPC_end() to free resource, /n +/// This API is used for insurance processing when socket file's link lost. /n +/// 1,Before process ends, call this API. /n +/// When process is ending, auto running socket's close and memory free is not work. /n +/// 2,After called this API, all the RPC's process(both server and client) become to useless. /n +/// Even if after called this API, call RPC_START to repair it also can't make sure to active. /n +/// RPC library which use Unix autobind is nothing to do. /n +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////// +void RPC_end_all(void); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_set_API_timeout +/// \~english @par Brief +/// Set timeout time for server side API processing time +/// \~english @param [in] sec +/// INT32 - timeout time +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @retval RPC_ERR_Configuration Argument is out of range +/// \~english @par Prerequisite +/// RPC_START_SERVER or RPC_START_SECURE_SERVER is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Unable to get the rpc lib info for the self-thread. +/// - Server id info doesn't exist. +/// - Info for API call reception processing doesn't exist. +/// - RPC_ERR_Fatal +/// - The value of the argument(sec) is out of range. +/// - RPC_ERR_Configuration +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// None +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_set_API_timeout(INT32 sec); // NOLINT (readability/nolint) + + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_is_server_ready +/// \~english @par Brief +/// Return RPC server's status +/// \~english @param [in] id +/// RPC_ID - server program's RPC_ID +/// +/// \~english @retval RPC_OK : Success +/// \~english @retval RPC_ERR_No_Response : No response +/// +/// \~english @par Prerequisite +/// - None +/// \~english @par Change of internal state +/// - None +/// \~english @par Conditions of processing failure +/// - None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// return the server's work status. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_is_server_ready(RPC_ID id); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_regist_credential +/// \~english @par Brief +/// Register UID and GID list +/// \~english @param [in] uid_num +/// int - UID number to regist(number of elements of UID list) +/// \~english @param [in] uid_list +/// uid_t* - head pointer of UID list +/// \~english @param [in] gid_num +/// int - GID number to regist(number of elements of GID list) +/// \~english @param [in] uid_list +/// gid_t* - head pointer of GID list +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @retval RPC_ERR_Configuration Argument is out of range +/// \~english @par Prerequisite +/// RPC_START_SECURE_SERVER is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Unable to get the rpc lib info for the self-thread. +/// - Server id info doesn't exist. +/// - Info for API call reception processing doesn't exist. +/// - Arguments(client_uid and client_gid) are NULL. +/// - Client authentication check is not necessary. +/// - Authentication info is already registered. +/// - Memory allocation fail for UID and GID lists. +/// - RPC_ERR_Fatal +/// - Values of Arguments(uid_num and gid_num) are out of range. +/// - RPC_ERR_Configuration +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - Register the UID and GID lists acceptable by the RPC server. +/// - If RPC_START_SECURE_SERVER is not called, this function returns the error. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_regist_credential(int uid_num, uid_t *uid_list, int gid_num, gid_t *gid_list); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_get_client_credential +/// \~english @par Brief +/// Get UID and GID of client that requested to run APIs processing +/// \~english @param [out] client_uid +/// uid_t* - UID of client that requested to run APIs processing +/// \~english @param [out] client_gid +/// gid_t* - GID of client that requested to run APIs processing +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal Error +/// \~english @par Prerequisite +/// RPC_START_SECURE_SERVER is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Server id info doesn't exist. +/// - Info for API call reception processing doesn't exist. +/// - Arguments(client_uid and client_gid) are NULL. +/// - Client authentication check is not necessary. +/// - There are no running clients. +/// - Info for the running client is not applicable. +/// - RPC_ERR_Fatal +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - This function is to get UID and GID of client that requested to run APIs processing. +/// - If RPC_START_SECURE_SERVER is not called, this function returns the error. +/// - If the running client doesn't exist, this function returns the error. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_get_client_credential(uid_t *client_uid, gid_t *client_gid); // NOLINT (readability/nolint) + +/* + * The following are only used in stub files + */ +#define RPC_RETCODE_LEN 9 + +#define RPC_MARSHALL_FLAG_BITS_CODE 12 +#define RPC_MARSHALL_FLAG_BITS_IS_VARARRAY 1 +#define RPC_MARSHALL_FLAG_BITS_IS_POINTER 1 +#define RPC_MARSHALL_FLAG_BITS_IN_OUT 2 + +/** @brief \~english APIcall property stored struct + * + */ +typedef union { + UINT32 all; ///< \~english all property + struct { + unsigned int code: RPC_MARSHALL_FLAG_BITS_CODE; ///< \~english value type + /** @brief \~english vararray or not + * + */ + unsigned int is_vararray: RPC_MARSHALL_FLAG_BITS_IS_VARARRAY; + /** @brief \~english pointer or not + * + */ + unsigned int is_pointer: RPC_MARSHALL_FLAG_BITS_IS_POINTER; + /** @brief \~english in/out parameter property + * + */ + unsigned int in_out: RPC_MARSHALL_FLAG_BITS_IN_OUT; + /** @brief \~english string or user define type byte num.other is 0 + * + */ + UINT16 bytes; + } bits; ///< \~english variable properties +} RPC_marshall_flag; + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_API_call +/// \~english @par brief +/// API call execution function (client) +/// \~english @param [in] id +/// RPC_ID - RPC_ID of server program +/// \~english @param [in] api_num +/// UINT16 - Request API number +/// \~english @param [in] args_string +/// const char* - Argument string +/// \~english @param [in] args_size +/// unsigned int - Argument string length +/// \~english @param [out] ret_string +/// char** - Process result string +/// \~english @param [out] ret_size +/// unsigned int* - Process result string length +/// \~english @retval RPC_OK Normal End +/// \~english @retval RPC_ERR_Fatal Fatal error +/// \~english @retval RPC_ERR_No_Response No response +/// \~english @retval RPC_ERR_Busy API call queue overflow +/// \~english @retval RPC_ERR_Server_DeadLock RPC server deadlock +/// \~english @retval RPC_ERR_Reject_connect The RPC server does not allow communication +/// \~english @par Prerequisite +/// The RPC server is running. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Acquisition of rpc library information for self thread fails +/// - Generation of self-thread rpc library information fails +/// - The RPC ID information does not exist +/// - Failed to receive data from the server at initial authentication +/// - Analysis of received data failed during initial authentication +/// - Commands not expected to be received during initial authentication +/// - Server response when initial authentication is API call error +/// - Failed to receive data from the server at API processing request +/// - Analysis of received data failed during API processing request +/// - Commands not expected to be received during API processing request +/// - Server response when API processing request is API call error +/// - Error in server response other than deadlock when processing results are received +/// - Server shut down +/// - RPC_ERR_Fatal +/// - UDP packet transmission fails at initial authentication +/// - A timeout occurred in response from the server during initial authentication +/// - UDP packet transmission failed at API processing request +/// - A timeout occurred in response from the server during API processing request +/// - RPC_ERR_No_Response +/// - Server response when initial authentication is API call queue overflow +/// - Server response when API processing request is API call queue overflow +/// - RPC_ERR_Busy +/// - When the server response is deadlocked on initial authentication +/// - When the server response is deadlocked on API processing request +/// - Server response is deadlocked when processing result is received +/// - RPC_ERR_Server_DeadLock +/// - Server response is not authenticated at initial authentication +/// - RPC_ERR_Reject_connect +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - Request execution of RPC-API from the client side. +/// - However, since this API is called from the automatically generated code, it is not used directly by the user. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RPC_Result RPC_API_call(RPC_ID id, UINT16 api_num, // NOLINT (readability/nolint) + const char *args_string, unsigned int args_size, + char **ret_string, unsigned int *ret_size); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_demarshall_arguments +/// \~english @par Brief +/// Confirm whether the input character string conforms to the prescribed format. +/// \~english @param [in] from +/// const char * - Input string +/// \~english @param [in] size +/// unsigned int - Byte length of the input string +/// \~english @param [in] need_alloc +/// int - Flag whether memory allocation is necessary or not. +/// \~english @param [in] num_args +/// int - Number of the variable length arguments +/// \~english @param [in] ... +/// void * - Variable length arguments +/// \~english @retval 0 Normal End +/// \~english @retval -1 Abnormal End +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - Byte length of the input string is 0 bytes or less or larger than 1024 bytes. +/// - The input character string doesn't conform to the prescribed format. +/// - -1 +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// This function is used in the stub file only and user must not call this function directly. +/// \~english @see RPC_marshall_arguments +//////////////////////////////////////////////////////////////////////////////////// +int RPC_demarshall_arguments(const char *from, unsigned int size, // NOLINT (readability/nolint) + int need_alloc, int num_args, ...); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_marshall_arguments +/// \~english @par Brief +/// Collect variable arguments, convert them to a format that matches the receiver's specification, +/// and stuff them into the message buffer. +/// \~english @param [in] size +/// unsigned int * - data size after conversion +/// \~english @param [in] dont_marshall_out_args +/// int - input/output kind(when the argument is a pointer) +/// \~english @param [in] num_args +/// int - value of variable argument +/// \~english @param [in] ... +/// void * - variable argument +/// \~english @retval char * Message buffer after conversion +/// \~english @retval NULL Abnormal +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// - When marshall work securing work area fails +/// - When the specified type size is abnormal +/// - When securing the area of the message buffer after conversion fails +/// - NULL +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// This function is used in the stub file for client only and user must not call this function directly. +/// \~english @see RPC_demarshalol_arguments +//////////////////////////////////////////////////////////////////////////////////// +char *RPC_marshall_arguments(unsigned int *size, int dont_marshall_out_args, // NOLINT (readability/nolint) + int num_args, ...); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_marshall_free +/// \~english @par Brief +/// Variadic function for memory release +/// \~english @param [in] num +/// int - number of memory to be released +/// \~english @param [in] ... +/// void * - allocated memory +/// \~english @retval None +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - This function is used in the stub file only and user must not call this function directly. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +void RPC_marshall_free(int num, ...); // NOLINT (readability/nolint) + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_free_return_string +/// \~english @par Brief +/// release memory allocated during running API call. +/// \~english @param [in] ptr +/// void * - allocated memory +/// \~english @retval None +/// \~english @par Prerequisite +/// RPC_API_call is already called. +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - This function is used in the stub file for client only and user must not call this function directly. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +void RPC_free_return_string(void *ptr); // NOLINT (readability/nolint) + +#ifdef DBG_ENABLE + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup RPC_record_dbg_log +/// \~english @par Brief +/// RPC-API call process's log +/// \~english @param [in] filename +/// const char - filename's point +/// \~english @param [in] funcname +/// const char - function name's point +/// \~english @param [in] line +/// int - file's line +/// \~english @param [in] apiname +/// const char - called API name's point +/// \~english @param [out] +/// +/// \~english @retval 0 : Success +/// +/// \~english @par Prerequisite +/// - DBG_ENABLE is defined. +/// \~english @par Change of internal state +/// - None +/// \~english @par Conditions of processing failure +/// - None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// Receipt and record the client's filename, function name, +/// line and called API's function name which called this API. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////// +int RPC_record_dbg_log(const char *filename, const char *funcname, int line, + const char *apiname); +#endif + +#define rpc_malloc malloc +#define rpc_free free + +/* + * RPC debug message control + * if set to non-null and some critical information is displayed. + */ +extern char *RPC_DEBUG; // NOLINT (readability/nolint) + +/** @}*/ // end of rpc_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#ifdef __cplusplus +} +#endif + +#endif // OTHERSERVICE_RPC_H_ diff --git a/otherservice/rpc_library/library/include/other_service/rpc_id.h b/otherservice/rpc_library/library/include/other_service/rpc_id.h new file mode 100755 index 0000000..e43e03c --- /dev/null +++ b/otherservice/rpc_library/library/include/other_service/rpc_id.h @@ -0,0 +1,96 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_id.h + * @brief \~english RPC library -- RPC_ID(port no) define + */ +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup rpc_library + * @ingroup other_service + * @{ + */ + +/** @brief \~english define the RPC_ID used by program + * like #define XXX_RPC_ID ID + * but RPC_START_CLIENT() is not necessary + * + * RPC_ID as the following + * - UI Application : 50xxx + * - Application Service : 51xxx + * + HMI : 511xx + * + AV : 512xx + * + Radio : 513xx + * + Connectivity : 514xx + * + Navigation/Location: 515xx + * + Vehicle : 516xx + * + Communication : 517xx + * + BasePF : 518xx + * + System : 519xx + * + Others : 510xx + * - Common Service : 53xxx + * - Extension Service : 55xxx + * - System/Device Driver : 56xxx + * + * - 49152~59999 are Reserved. + * @note \~english RPC_ID==port num , + * when not call from RPClibrary, and not well-known(~1023)/registered(1024~49151) + * use the fixed port num to IP communicate, use 6xxxx port number. + * @note \~english when RPC_START_CLIENT,and distribute automatically. + * use the linux kernel port distribute function + * 1024~4999 as the port num unused. + */ + +#ifndef OTHERSERVICE_RPCID_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPCID_H_ // NOLINT(build/header_guard) + + +#define test_RPC_ID 49999 +///< \~english sample(ID is used by RPClibrary test program) + +/* UI Aapplication : 50xxx */ + +/* Application Service : 51xxx */ +#define MODEMANAGER_RPC_ID 51100 /* ModeManager */ +#define ACTIVITYMANAGER_RPC_ID 51101 /* ActivityManager */ + +/* Common Service : 53xxx */ +#define TIMERENTRYDRV_RPC_ID 53000 /* TimerEntryDrv */ +#define TSKM_RPC_ID 53001 /* TaskManager */ +#define MSGBRK_RPC_ID 53002 /* MessageBroker */ +#define IPMANAGER_RPC_ID 53003 /* IPManager */ +#define IPMANAGER_RPC_ID 53003 /* IPManager */ +#define DEVICEMANAGER_RPC_ID 53004 /* DeviceManager */ +#define CAN_RPC_ID 53005 /* Communication(CAN) */ +#define _CWORD83__RPC_ID 53006 /* Communication(_CWORD83_) */ +#define SENSOR_RPC_ID 53007 /* Vehicle(Sensor) */ +#define GPS_RPC_ID 53008 /* Vehicle(GPS) */ +#define RESMGR_RPC_ID 53009 /* ResourceManager */ +#define GRAPHICS_RPC_ID 53010 /* Graphic */ + +/* Extension Service : 55xxx */ + +/* System/Device Driver : 56xxx */ +/** @}*/ // end of rpc_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem +#endif // OTHERSERVICE_RPCID_H_ diff --git a/otherservice/rpc_library/library/include/other_service/rpc_library.h b/otherservice/rpc_library/library/include/other_service/rpc_library.h new file mode 100755 index 0000000..298f741 --- /dev/null +++ b/otherservice/rpc_library/library/include/other_service/rpc_library.h @@ -0,0 +1,41 @@ +// +// @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. +// +// 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. +// + +/** + * @file + * @brief \~english include all rpc_library head files + */ +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup rpc_library + * @ingroup other_service + * @{ + */ +#ifndef OTHERSERVICE_RPCLIBRARY_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPCLIBRARY_H_ // NOLINT(build/header_guard) + +#include <other_service/rpc.h> +#include <other_service/rpc_id.h> + +#endif // OTHERSERVICE_RPCLIBRARY_H_ +/** @}*/ +/** @}*/ +/** @}*/ diff --git a/otherservice/rpc_library/library/include/rpc_internal.h b/otherservice/rpc_library/library/include/rpc_internal.h new file mode 100755 index 0000000..2b293ca --- /dev/null +++ b/otherservice/rpc_library/library/include/rpc_internal.h @@ -0,0 +1,135 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_internal.h + * @brief RPC Library Internal Implementation-Type, macro, and function definitions used internally + * + */ +/** @addtogroup RPClib_in + */ +#ifndef OTHERSERVICE_RPCINTERNAL_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPCINTERNAL_H_ // NOLINT(build/header_guard) + +#include <unistd.h> +#include <stdlib.h> + +#if defined(__linux__) +/* Using unix autobind Features That Are Only Available in linux */ +#define RPC_USE_UNIX_AUTOBIND +#endif /* __linux__ */ + +#define RPC_USE_SYSLOG + +typedef RPC_ID *RPC_ID_p; + +#include "rpc_udp.h" +#include "rpc_thread.h" + +RPC_Result RpcQueueAPIRequestBefore(RpcIdInfo *id, + UINT32 size, char **buff); +RPC_Result RpcQueueAPIRequestAfter(RpcIdInfo *id, RPC_ID client, + const char *mesg, UINT32 size, + char *args); +void RpcFreeAPIArgsString(char *args_string); +UINT16 RpcGetAPIRequest(RpcIdInfo *id, RPC_ID_p client, + char **args_string, unsigned int *args_size); +RPC_Result RpcSetAPIcallReturn(RpcIdInfo *id, + const char *mesg, UINT32 size); +void RpcDiscardAPIcallReturn(RpcIdInfo *id); + +RPC_Result RpcDeleteSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, int wd); + +#define StrEqual(a, b) (strcmp((a), (b)) == 0) +#define MemEqual(a, b, c) (memcmp((a), (b), (c)) == 0) + +#define RPC_IS_INVALID_ID(a) ((a) == RPC_NO_ID) +#define RPC_INVALIDATE_ID(a) ((a) = RPC_NO_ID) +#define RPC_ID_COPY(a, b) ((a) = (b)) +#define RPC_ID_Equal(a, b) ((a) == (b)) + +/* inotify Events read Sizes */ +#define EVENT_SIZE ( sizeof(struct inotify_event) ) /* One inotify event size */ +#define BUF_LEN (4 * EVENT_SIZE) /* Read sizes */ + +#define LESS_THAN < + +#define SET_NONBLOCK(fd) { \ + int flag; \ + flag = fcntl((fd), F_GETFL, 0); \ + fcntl((fd), F_SETFL, O_NONBLOCK|flag); \ + } + +#define SET_CLOSE_ON_EXEC(fd) { \ + int flag; \ + flag = fcntl((fd), F_GETFD, 0); \ + fcntl((fd), F_SETFD, FD_CLOEXEC|flag); \ + } + +#if defined(RPC_USE_SYSLOG) + +#include <syslog.h> + +#define RPC_LOG_CRIT(format, arg...) syslog(LOG_CRIT, format "\n", ##arg) +#define RPC_LOG_ERR(format, arg...) syslog(LOG_ERR, format "\n", ##arg) +#define RPC_LOG_STATE(format, arg...) syslog(LOG_INFO, format "\n", ##arg) +#define RPC_LOG_DEBUG(format, arg...) syslog(LOG_DEBUG, format "\n", ##arg) + +#else // defined(RPC_USE_SYSLOG) + +#define RPC_LOG_CRIT(format, arg...) fprintf(stderr, "[RPC:CRIT](%d): " format "\n", getpid(), ##arg) +#define RPC_LOG_ERR(format, arg...) fprintf(stderr, "[RPC:ERR](%d): " format "\n", getpid(), ##arg) +#define RPC_LOG_STATE(format, arg...) fprintf(stderr, "[RPC:STATE](%d): " format "\n", getpid(), ##arg) +#define RPC_LOG_DEBUG(format, arg...) + +#endif // defined(RPC_USE_SYSLOG) + +#include <sys/prctl.h> + +#define RPC_LOG_ERR_W_NAME(format, arg...) \ +do { \ + char name[16]; \ + prctl(PR_GET_NAME, name); \ + name[15] = '\0'; \ + RPC_LOG_ERR("(%s): " format, name, ##arg); \ +} while (0) + +#define RPC_LOG_PERROR(format, arg...) RPC_LOG_ERR("[%s:%d] %s : " format, __FILE__, __LINE__, strerror(errno), ##arg); + +#include <assert.h> +#define rpc_assert assert + +#define BUG_ASSERT(cond, x) \ + if (!(cond)) { \ + rpc_assert("BUG ASSERTION! " #x " @ " __FILE__ ==NULL); \ + } +#define CONFIG_ASSERT(s) rpc_assert((s) == NULL) + +#define RUNS_IN_CALLERS_THREAD +#define RUNS_IN_READING_THREAD + +#if !defined(RPC_USE_UNIX_AUTOBIND) + +#define RPC_SOCKET_NAME "/tmp/RPC/%05d" + +static inline void +rpc_set_socket_name(char *str, RPC_ID id) { + sprintf(str, RPC_SOCKET_NAME, id); // NOLINT (readability/nolint) +} + +#endif /* !AUTOBIND */ + +#endif // OTHERSERVICE_RPCINTERNAL_H_ diff --git a/otherservice/rpc_library/library/include/rpc_thread.h b/otherservice/rpc_library/library/include/rpc_thread.h new file mode 100755 index 0000000..819e5a6 --- /dev/null +++ b/otherservice/rpc_library/library/include/rpc_thread.h @@ -0,0 +1,240 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_RPCTHREAD_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPCTHREAD_H_ // NOLINT(build/header_guard) + +#include <pthread.h> + +/** @addtogroup RPClib_in + * @{ + */ + +#define RPC_NO_SOCKET -1 +#define RPC_NO_THREAD 0 + +#define RPC_MAIN_SUB_COMMAND "%-2d %-16lx" +#define RPC_MAIN_SUB_COMMAND_SIZE 20 +#define RPC_MAIN_SUB_COMMANDs "%d %lx" +/** Type of command sent from the main thread to the subthread */ +enum { + RPC_COMMAND_ADD_SERVER, /* Addition of RPC_ID */ + RPC_COMMAND_REMOVE_SERVER, /* Remove RPC_ID */ + RPC_COMMAND_EXIT, /* Sub-thread termination (when all RPC_ID are exhausted) */ +}; + +#define APICALL_TIMEOUT_DEFAULT -1 + +/** Periodic checking timeout (mSec) for detecting deadlocks */ +#define TIMEOUT_FOR_DEADLOCK_CHECK 1000 + +/** Length of the socket name + API request datagram socket = '\0' + "5-digit number associated with RPC_ID" + Authentication stream socket = '\0' + "secure_" + "5-digit number associated with RPC_ID" */ +#define SOCK_NAME_LEN (1+5) /* API request datagram socket */ +#define SECURE_SOCK_NAME_LEN (1+12) /* Authentication stream socket */ + +#define rpc_mutex_lock pthread_mutex_lock +#define rpc_mutex_unlock pthread_mutex_unlock + +/** Upper limit of UID and GID list registration */ +#define CREDENTIAL_LIST_NUM_MAX 32 + +/** Authentication result to be sent to the client */ +typedef struct { + UINT16 certify_res; /**< Client Authentication Result */ + pid_t srvr_pid; /**< Server PID */ +} RpcCertifyResult; + +#define CERTIFY_OK 0 +#define CERTIFY_NG 1 + +/** Received API call request */ +typedef struct { + RPC_ID client; /**< API ID of the requested program */ + UINT16 api_num; /**< Calling API number */ + char *args_string; /**< API Call Arguments */ + UINT32 args_size; /**< Number of bytes in the argument */ +} rpc_apicall_queue; + +/** Source Client Socket Name Management Table */ +typedef struct RpcClientSockNameInfoST RpcClientSockNameInfo; +struct RpcClientSockNameInfoST { + char client_sock_name[SOCK_NAME_LEN]; /**< Socket Name List for Source Client */ + pid_t pid; /**< Source pid */ + uid_t uid; /**< Source uid */ + gid_t gid; /**< Source gid */ + int wd; /**< Non-negative inotify monitored descriptors */ + RpcClientSockNameInfo *next; /**< Pointer to the next node */ +}; + +/** Communication server PID management table */ +typedef struct RpcSrvrPidInfoST RpcSrvrPidInfo; +struct RpcSrvrPidInfoST { + RPC_ID srvr_rpc_id; /**< Communication destination server RPC_ID */ + pid_t srvr_pid; /**< Communication destination server pid */ + int wd; /**< Non-negative inotify monitored descriptors */ + RpcSrvrPidInfo *next; /**< Pointer to the next node */ +}; + +/** Buffer structure for API call acceptance processing. + * This function is allocated only when the dispatch function is specified by RPC_start(). + */ +typedef struct { + RPC_dispatch_func_t dispatch_func;/**< Dispatch Functions to APIs (in stub) */ +#define RPC_apicall_dispatch_func(id) \ + ((id)->apicall ? (id)->apicall->dispatch_func : 0) + + INT32 pipe_sub_main[2];/**< Notification pipe from the subthread to the main thread */ +#define RPC_pipe_sub_main(th) ((th)->srvr_id->apicall->pipe_sub_main) + + UINT16 num_queue;/**< Number of queued API call requests */ +#define RPC_apicall_num_queue(id) \ + ((id)->apicall ? (id)->apicall->num_queue : 0) +#define RPC_apicall_num_queue_inc(id) ((id)->apicall->num_queue++) +#define RPC_apicall_num_queue_dec(id) ((id)->apicall->num_queue--) + + rpc_apicall_queue queue[RPC_MAX_APICALL_QUEUE];/**< Queuing API Call Requests (FIFO) */ +#define RPC_apicall_queue(id, i) ((id)->apicall->queue[(i)]) +#define RPC_apicall_queue_client(id, i) ((id)->apicall->queue[(i)].client) +#define RPC_apicall_queue_api_num(id, i) ((id)->apicall->queue[(i)].api_num) +#define RPC_apicall_queue_args(id, i) ((id)->apicall->queue[(i)].args_string) +#define RPC_apicall_queue_args_size(id, i) ((id)->apicall->queue[(i)].args_size) + + RPC_ID in_process_client;/**< Clients running on ID */ +#define RPC_apicall_in_process_client(id) ((id)->apicall->in_process_client) + + INT32 timeout_sec;/**< API processing timeout */ +#define RPC_apicall_api_timeout_sec(id) ((id)->apicall->timeout_sec) + + INT32 secure_check;/**< Client Authentication Check Enabled/Disabled */ +#define RPC_secure_check(id) ((id)->apicall->secure_check) + + INT32 regist_credential_info;/**< Registration of authentication information */ +#define RPC_regist_credential_info(id) ((id)->apicall->regist_credential_info) + + uid_t *uid_list;/**< List of UIDs that can communicate */ +#define RPC_uid_list(id, i) ((id)->apicall->uid_list[(i)]) + + INT32 uid_num;/**< Number of UID list elements that can communicate */ +#define RPC_uid_num(id) ((id)->apicall->uid_num) + + gid_t *gid_list;/**< GID list that can communicate */ +#define RPC_gid_list(id, i) ((id)->apicall->gid_list[(i)]) + + INT32 gid_num;/**< Number of GID list elements that can communicate */ +#define RPC_gid_num(id) ((id)->apicall->gid_num) + + RpcClientSockNameInfo *sock_info_head;/**< Leading node of the source client's socket information management table */ +#define RPC_sock_info_head(id) ((id)->apicall->sock_info_head) +#define RPC_client_sock_name(id) ((id)->apicall->sock_info_head->client_sock_name) +#define RPC_client_sock_pid(id) ((id)->apicall->sock_info_head->pid) +#define RPC_client_sock_next_node(id) ((id)->apicall->sock_info_head->next) + + INT32 client_sock_name_num;/**< Number of elements in the source client's socket name list */ +#define RPC_client_sock_name_num(id) ((id)->apicall->client_sock_name_num) +#define RPC_client_sock_name_num_inc(id) ((id)->apicall->client_sock_name_num++) +#define RPC_client_sock_name_num_dec(id) ((id)->apicall->client_sock_name_num--) +} RpcApicallInfo; + +struct RpcThreadInfo; + +/** Structure that holds information about each RPC_ID */ +typedef struct RpcIdInfo { + struct RpcThreadInfo *thread_info; + + RPC_ID port;/**< Port number (=ID) used by the RPC library */ +#define RPC_port(id) ((id)->port) +#define RPC_my_id(id) RPC_port(id) +#define rpc_get_port(id) (id) + + INT32 sock;/**< Sockets used by the RPC library */ +#define RPC_my_sock(id) ((id)->sock) + + INT32 secure_sock;/**< Authentication socket used by the RPC library */ +#define RPC_my_secure_sock(id) ((id)->secure_sock) + + int inotify_fd;/**< Server process monitoring inotify */ +#define RPC_clnt_inotify_fd(id) ((id)->inotify_fd) + + INT32 count;/**< Number of clients using the same RPC_ID */ +#define RPC_clnt_count(id) ((id)->count) +#define RPC_inc_clnt_count(id) ((id)->count++) +#define RPC_dec_clnt_count(id) ((id)->count--) + + RpcApicallInfo *apicall;/**< Information for API call acceptance processing */ +#define RPC_apicall_info(id) ((id)->apicall) + + RpcSrvrPidInfo *srvr_pid_head;/**< Communication destination server PID management table top node */ +#define RPC_srvr_pid_head(id) ((id)->srvr_pid_head) +#define RPC_srvr_rpc_id(id) ((id)->srvr_pid_head->srvr_rpc_id) +#define RPC_srvr_pid(id) ((id)->srvr_pid_head->srvr_pid) +#define RPC_srvr_pid_next_node(id) ((id)->srvr_pid_head->next) + + UINT32 return_str_len;/**<Number of bytes in the returned string as a result of an API call*/ + /* Including the terminating '\0' */ +#define RPC_apicall_return_str_len(id) ((id)->return_str_len) + + UINT8 *return_str;/**<String returned as a result of an API call*/ +#define RPC_apicall_return_str(id) ((id)->return_str) +} RpcIdInfo; + +/** Received response packet */ +typedef struct { + RPC_ID id;/**< ID of the thread that sent the response */ + UINT16 type;/**< Response type */ + UINT32 seq_num;/**< The packet number to which this was sent (the response to this) */ +} RpcResponse; + +/** Structure that stores the state of each thread that called the RPC library */ +typedef struct RpcThreadInfo { + pthread_mutex_t th_mtx;/**< Mutex for modifying this struct */ +#define RPC_THREAD_MUTEX_LOCK(th) (rpc_mutex_lock(&((th)->th_mtx))) +#define RPC_THREAD_MUTEX_UNLOCK(th) (rpc_mutex_unlock(&((th)->th_mtx))) + + pthread_t thread;/**< Thread calling the RPC library */ +#define RPC_main_thread(th) ((th)->thread) + + UINT32 sequence_number;/**< Sequence number given to the transmitted packet */ + /* Send 30 times per second from the beginning of the thread, then wrap around two years. + * It is not necessary to wrap around 0 because there is no comparison. + */ + UINT32 magic;/**< Magic number to detect corrupted memories */ + + RpcIdInfo *srvr_id;/**< Information by RPC_ID (server) */ +#define RPC_srvr_idinfo(th) ((th)->srvr_id) + + RpcIdInfo *clnt_id;/**< Info by RPC_ID (client) */ +#define RPC_clnt_idinfo(th) ((th)->clnt_id) +} RpcThreadInfo; + +extern pthread_t g_rpc_thread; +extern UINT32 g_rpc_thread_alive; + +#define PIPE_READ 0 +#define PIPE_WRITE 1 +extern int g_rpc_pipe_main_sub[2]; + +RpcThreadInfo *RpcMyThreadInfo(void); +RpcThreadInfo *RpcCreateThreadInfo(void); +int RpcCreateIdInfo(RpcThreadInfo *th, RPC_ID id, + RPC_dispatch_func_t dispatch, INT32 secure_check); +void RpcDestroyIdInfo(RpcThreadInfo *th, RpcIdInfo *idinfo); +void RpcDestroyThreadInfo(void); +void RpcUnlinkSocketFiles(void); + +/** @} */ +#endif // OTHERSERVICE_RPCTHREAD_H_ diff --git a/otherservice/rpc_library/library/include/rpc_udp.h b/otherservice/rpc_library/library/include/rpc_udp.h new file mode 100755 index 0000000..8c45ce6 --- /dev/null +++ b/otherservice/rpc_library/library/include/rpc_udp.h @@ -0,0 +1,162 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 OTHERSERVICE_RPCUDP_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_RPCUDP_H_ // NOLINT(build/header_guard) + +/** @addtogroup RPClib_in */ +/** @{ */ +/** Number of bytes of payload that can be stored in a UDP packet */ +#define RPC_UDP_PAYLOAD RPC_MAX_API_ARG_TOTAL_SIZE + +/** UDP packet header + * + * Packet type, source ID, sequence number, packet size, packet position + */ +#define RPC_PACKET_HEADER "%-2d %-5x %-8x %-4u %1d " +/** Number of bytes in the UDP packet header + */ +#define RPC_PACKET_HEADER_LEN (2+1 + 5+1 + 8+1 + 4+1 + 1+1) + +/** Number of bytes to store in the UDP packet */ +#define RPC_UDP_PACKET_SIZE (RPC_UDP_PAYLOAD + RPC_PACKET_HEADER_LEN) + +#define RPC_COMMAND_LEN 3 + +/** Format string for UDP packet header analysis */ +#define RPC_PACKET_HEADER_scanf "%d %x %x %d" + +/** Header (API number) to be added to the API call packet */ +#define RPC_APICALL_FORMAT "%-4d " +/** Number of bytes in the header of an API call packet */ +#define RPC_APICALL_FORMAT_ARGS_START 5 + +#define RPC_MAX_RESPONSE_MESSAGE_SIZE 5 + +#define RPC_SEQ_NUM_START 1 +#define RPC_SEQ_NUM_INVALID 0 + +/** Internal API call number for checking server existence */ +#define RPC_API_NUM_RPC_ALIVE 0 + +/** Type of packet that the RPC library sends */ +typedef enum { + RPC_PACKET_APICALL = 0,/**< API call request */ + + RPC_RESPONSE_APICALL,/**< Responding to API Call Requests */ +#define RPC_RESPONSE_NONE 0x0000 +#define RPC_RESPONSE_API_OK 0x0001 +#define RPC_RESPONSE_API_BUSY 0x0002 +#define RPC_RESPONSE_API_ERR 0x0004 +#define RPC_RESPONSE_API_DEADLOCK 0x0005 /* Server deadlock */ +#define RPC_RESPONSE_API_CERTIFY 0x0006 /* Authentication request */ + + RPC_PACKET_APIRETURN,/**< Result of the API call */ + + RPC_PACKET_NONE, +} RPC_packet_type; + +/** Packet Location (Multi-Fragment Packet Support) */ +typedef enum { + RPC_PACKET_POS_ONEANDONLY = 0,/**< Complete with one packet */ +} rpc_packet_position; + +/** Transmitting buffer */ +typedef struct { + unsigned int bytes; + const void *buf; +} rpc_send_buf; + +/** Valid bytes in the sockaddr_un struct specified for send */ +#define RPC_SOCKET_NAME_LEN 6 /**< Name: 5 characters + first NULL bytes */ +#define RPC_SOCKET_ADDR_LEN (sizeof(short) + RPC_SOCKET_NAME_LEN) // NOLINT (readability/nolint) + +enum { + RPC_SEND_TO_CLIENT, + RPC_SEND_TO_SERVER, + RPC_SEND_TO_SERVER_NO_RETRY, +}; + +struct RpcIdInfo; + +int RpcSendUdp(struct RpcIdInfo *id, RPC_ID receiver, int direction, + RPC_packet_type type, const void *mesg, unsigned int bytes); +int RpcSendUdp2(struct RpcIdInfo *id, RPC_ID receiver, int direction, + RPC_packet_type type, unsigned int num, rpc_send_buf *sendbuf); +RPC_Result RpcSendUdpResponse(struct RpcIdInfo *id, RPC_ID receiver, + int direction, + RPC_packet_type type, + UINT32 seq_num, char *mesg, UINT32 bytes); + +int RpcReadUdpPacket(const struct RpcIdInfo *id, UINT8 *buf); + +RPC_Result RpcParsePacketHeader(const char *str, RPC_packet_type *command, + RPC_ID_p id, UINT32 *seq_num, UINT32 *size); + +RPC_Result RpcClientWaitResponse(struct RpcIdInfo *idinfo, + UINT32 seq_num, + UINT32 timeout_msec, UINT16 *response); +RPC_Result RpcClientWaitResult(struct RpcIdInfo *idinfo, RPC_ID srvr_id); + +#if defined(RPC_USE_UNIX_AUTOBIND) +/* ===pathname of datagram sockets for API requests=== */ +static inline void +RpcSetServerName(char *str, RPC_ID id) { + *str = '\0'; + sprintf(str + 1, "S%04x", id); // NOLINT (readability/nolint) +} + +static inline void +RpcSetClientName(char *str, RPC_ID id) { + *str = '\0'; + sprintf(str + 1, "%05x", id); // NOLINT (readability/nolint) +} + +static inline void +RpcGetClientName(const char *str, RPC_ID *id) { + char buf[6]; + memcpy(buf, str + 1, 5); + buf[5] = '\0'; + if (buf[1] == 'X') { + *id = (RPC_ID)(strtoul(buf + 1, NULL, 16)); + } else { + *id = (RPC_ID)(strtoul(buf, NULL, 16)); + } +} + +/* ===pathname of stream-socket for authenticating=== */ +static inline void +RpcSetServerSecureName(char *str, RPC_ID id) { + *str = '\0'; + sprintf(str + 1, "secure_S%04x", id); // NOLINT (readability/nolint) +} + +static inline void +RpcSetClientSecureName(char *str, RPC_ID id) { + *str = '\0'; + sprintf(str + 1, "secure_%05x", id); // NOLINT (readability/nolint) +} + +static inline void +RpcGetClientNameFromSock(const char *str, char *client_sock_name) { + memcpy(client_sock_name, str + 8, 5); + client_sock_name[5] = '\0'; +} + +#endif /* !AUTOBIND */ + +/** @} */ +#endif // OTHERSERVICE_RPCUDP_H_ diff --git a/otherservice/rpc_library/library/librpc.ver b/otherservice/rpc_library/library/librpc.ver new file mode 100755 index 0000000..2fbb9dc --- /dev/null +++ b/otherservice/rpc_library/library/librpc.ver @@ -0,0 +1,29 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +###################### +# rpc version script # +###################### +{ + global: + ### .text section ### + RPC_*; + ### .data section ### + local: + *; +}; + + diff --git a/otherservice/rpc_library/library/src/rpc_event.c b/otherservice/rpc_library/library/src/rpc_event.c new file mode 100755 index 0000000..2e3fd38 --- /dev/null +++ b/otherservice/rpc_library/library/src/rpc_event.c @@ -0,0 +1,158 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_event.c + * @brief RPC Library Internal Implementation--Event Handling + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <native_service/cl_monitor.h> + +#include <other_service/rpc.h> +#include "rpc_internal.h" + +/** @ingroup RPClib_in + */ +RUNS_IN_READING_THREAD +RPC_Result +RpcQueueAPIRequestBefore(RpcIdInfo *id, UINT32 size, char **buff) { + RPC_THREAD_MUTEX_LOCK(id->thread_info); + + int n = RPC_apicall_num_queue(id); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_thread.h + + if (n >= RPC_MAX_APICALL_QUEUE) { + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); + RPC_LOG_STATE("Returned BUSY."); + return RPC_ERR_Busy; + } else { + *buff = rpc_malloc(size);/* malloc */ + if (*buff == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc function malloc + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); // LCOV_EXCL_START 5: fail safe for libc function malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_STATE("queue API request: No Memory"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + } + return RPC_OK; +} +/** @ingroup RPClib_in + */ +RUNS_IN_READING_THREAD +RPC_Result +RpcQueueAPIRequestAfter(RpcIdInfo *id, RPC_ID client, + const char *mesg, UINT32 size, char *args) { + int n = RPC_apicall_num_queue(id); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_thread.h + + UINT16 api_num; + api_num = (UINT16)strtol(mesg, NULL, 10); + memcpy(args, mesg + RPC_APICALL_FORMAT_ARGS_START, size); + RPC_ID_COPY(RPC_apicall_queue_client(id, n), client); + RPC_apicall_queue_api_num(id, n) = api_num; + RPC_apicall_queue_args(id, n) = args; + RPC_apicall_queue_args_size(id, n) = size; + RPC_apicall_num_queue_inc(id); + + /* set RUN state */ + CL_MonitorSetEntry(CL_MONITOR_TYPE_RPC, + RPC_port(id), + CL_MONITOR_STATE_RUN, + (uint32_t)(RPC_apicall_api_timeout_sec(id)), + api_num); + + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); + return RPC_OK; +} + +/** @ingroup RPClib_in + */ +RUNS_IN_CALLERS_THREAD +void +RpcFreeAPIArgsString(char *args_string) { + if (args_string != NULL) { // LCOV_EXCL_BR_LINE 5: free the memory, malloced in RpcQueueAPIRequestBefore(...) + rpc_free(args_string);/* free */ + } +} + +/** @ingroup RPClib_in + */ +RUNS_IN_CALLERS_THREAD +UINT16 +RpcGetAPIRequest(RpcIdInfo *id, RPC_ID_p client, + char **args_string, unsigned int *args_size) { + UINT16 api_num = 0; + + RPC_THREAD_MUTEX_LOCK(id->thread_info); + + UINT32 n = RPC_apicall_num_queue(id); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_thread.h + if (n > 0) { + RPC_ID_COPY(*client, RPC_apicall_queue_client(id, 0)); + api_num = RPC_apicall_queue_api_num(id, 0); + *args_string = RPC_apicall_queue_args(id, 0); + /* this string must be freed by the caller using discard_APIcall_return()*/ + *args_size = RPC_apicall_queue_args_size(id, 0); + + if (n > 1) { + memmove(&(RPC_apicall_queue(id, 0)), &(RPC_apicall_queue(id, 1)), + (n - 1) * sizeof(RPC_apicall_queue(id, 0))); + } + RPC_apicall_num_queue_dec(id); + } + + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); + return api_num; +} + +/** @ingroup RPClib_in + */ +RUNS_IN_READING_THREAD +RPC_Result +RpcSetAPIcallReturn(RpcIdInfo *id, const char *mesg, UINT32 size) { + if (RPC_apicall_return_str(id) != NULL) { // LCOV_EXCL_BR_LINE 6: double check + RPC_LOG_STATE("previous APIcall return string was not used"); // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RpcDiscardAPIcallReturn(id); + } // LCOV_EXCL_STOP + RPC_THREAD_MUTEX_LOCK(id->thread_info); + + RPC_apicall_return_str(id) = rpc_malloc(size);/* malloc */ + if (RPC_apicall_return_str(id) == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc function malloc + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); // LCOV_EXCL_START 5: fail safe for libc function malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_STATE("set APIcall return: No Memory"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + RPC_apicall_return_str_len(id) = size; + memcpy(RPC_apicall_return_str(id), mesg, size); + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); + return RPC_OK; +} + +/** @ingroup RPClib_in + */ +RUNS_IN_CALLERS_THREAD +void +RpcDiscardAPIcallReturn(RpcIdInfo *id) { + RPC_THREAD_MUTEX_LOCK(id->thread_info); + if (RPC_apicall_return_str(id) != NULL) { // LCOV_EXCL_BR_LINE 6: double check + rpc_free(RPC_apicall_return_str(id));/* free */ + RPC_apicall_return_str_len(id) = 0; + RPC_apicall_return_str(id) = NULL; + } + RPC_THREAD_MUTEX_UNLOCK(id->thread_info); +} diff --git a/otherservice/rpc_library/library/src/rpc_lib.c b/otherservice/rpc_library/library/src/rpc_lib.c new file mode 100755 index 0000000..76f0d49 --- /dev/null +++ b/otherservice/rpc_library/library/src/rpc_lib.c @@ -0,0 +1,1264 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_lib.c + * @brief RPC Library-API Function Implementation + * + */ +/** @mainpage + * This document describes the following API functions, structures, + * type declarations, and macros. + * - RPC library external specification + * - External specifications for RPC tools + * + * For an overview of other RPC libraries and tools and anomaly processing, + * to reference the Word version of the documentation. + * (external specifications and programming guides) */ +/** @defgroup RPClib RPC library external specification */ +/** @defgroup RPCtool RPC tool (rpc_apidef) */ +/** @defgroup RPC_ID_assign RPC_ID Assignment */ +/** @defgroup RPClib_in RPC library internal specifications (incomplete) */ +/** @addtogroup RPClib + * @{ + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/poll.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <sys/un.h> +#include <sys/inotify.h> + +#include <other_service/rpc.h> +#include "rpc_internal.h" + +#include <native_service/cl_process.h> // for CL_INTFY_FILENAME_FORMAT +#include <native_service/cl_monitor.h> + + +/* Prototype declarations */ +static RPC_Result ProcessAPIcallRequest(RpcIdInfo *idinfo, RPC_ID client, + UINT16 api_num, char *args_string, + unsigned int args_size); +static RPC_Result RpcAllDeleteSrvrPid(RpcIdInfo *idinfo); +static RPC_Result RpcClientWaitCertification(RpcIdInfo *idinfo, pid_t *srvr_pid); +static RPC_Result RpcRegistSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, pid_t srvr_pid, int wd); + +#define THREAD_INFO_CHECK(th) \ + if ((th) == NULL) { \ + RPC_LOG_STATE("No thread info"); \ + return RPC_ERR_Fatal; \ + } + +#define SUB_THREAD_CHECK() \ + if (g_rpc_thread_alive == 0) { \ + RPC_LOG_STATE("No sub thread -- shutdown"); \ + RpcDestroyThreadInfo(); \ + return RPC_ERR_Fatal; \ + } + +/** + * Waiting for response packet for API call and API result transmission + * Timeout time in msec. + * If the other program is abnormal (process termination), delay occurs in the meanwhile. + * Confirm the operation on the actual machine and set again. + */ +#define RESPONSE_WAIT_MSEC_DEFAULT 2000 +static unsigned int Response_wait_msec = RESPONSE_WAIT_MSEC_DEFAULT; + +char *RPC_DEBUG = NULL; + +#if defined(RPC_USE_UNIX_AUTOBIND) + + static RPC_Result +CreateClientIdinfo(RpcThreadInfo *th, RPC_ID *pID) { + if (RpcCreateIdInfo(th, *pID, NULL, NO_SECURE_CHECK) < 0) { + RPC_LOG_ERR("Can't create id_info"); + return RPC_ERR_Fatal; + } + + *pID = RPC_my_id(RPC_clnt_idinfo(th)); + RPC_LOG_DEBUG("RPC: assigned client ID %d", *pID); + if (RPC_DEBUG) { // LCOV_EXCL_BR_LINE 7: debug + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("RPC[%s]: client start finished.\n", RPC_DEBUG); // LCOV_EXCL_LINE 7: debug + } + return RPC_OK; +} +#else /* !AUTOBIND */ + +#include <sys/file.h> + + static int +FindUniqClientId(void) { +#define RPC_ID_FILE_NAME "/tmp/RPC/id" +#define RPC_MIN_CLIENT_ID 1024 +#define RPC_MAX_CLIENT_ID (1024+32768-1) + + int fd, found; + RPC_ID id, next; + struct stat statbuf; + char fname[32]; + + fd = open(RPC_ID_FILE_NAME, O_RDWR|O_CLOEXEC, 0777); + if (fd < 0) { + id = RPC_MIN_CLIENT_ID; + fd = open(RPC_ID_FILE_NAME, O_RDWR|O_CREAT|O_CLOEXEC, 0777); + if (fd < 0) { + return -1; + } + flock(fd, LOCK_EX); // Possible sleep here + } else { + flock(fd, LOCK_EX); // Possible sleep here + read(fd, &id, sizeof(id)); + } + + found = 0; + while(found == 0) { + rpc_set_socket_name(fname, id); + if (stat(fname, &statbuf) < 0) { + found = 1; + break; + } + id++; + if (id > RPC_MAX_CLIENT_ID) { + id = RPC_MIN_CLIENT_ID; + } + } + + next = id + 1; + if (next > RPC_MAX_CLIENT_ID) { + next = RPC_MIN_CLIENT_ID; + } + + lseek(fd, 0, SEEK_SET); + write(fd, &next, sizeof(next)); + flock(fd, LOCK_UN); + close(fd); + + return id; +} + + static RPC_Result +CreateClientIdinfo(RpcThreadInfo *th, UINT16 port) { + if (RpcCreateIdInfo(th, port, NULL, NO_SECURE_CHECK) < 0) { + RPC_LOG_ERR("Can't create id_info"); + return RPC_ERR_Fatal; + } + // LCOV_EXCL_BR_START 7: debug + if (RPC_DEBUG) { + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("RPC[%s]: client start finished.\n", RPC_DEBUG); + } + // LCOV_EXCL_BR_STOP + return RPC_OK; +} +#endif /* AUTOBIND */ + +/** @fn RPC_START_SERVER(ID) + * @brief RPC_start() macro for the server + * + * Used by RPC-API server programs to activate the RPC library. + * ID specifies a symbol of the form XXX_RPC_ID defined in rpc_id.h. + * Only one server program per thread is allowed. + * When a server program calls an API as a client of another server, + * it only needs to call RPC_START_SERVER, + * not RPC_START_CLIENT. + * + * RPC_end() should be called when the RPC library is no longer needed. + * @param ID [IN]RPC_ID of the program + * @see RPC_start + * @see RPC_end + */ +/** @fn RPC_START_CLIENT(pID) + * @brief RPC_start() macro for clients + * + * Use only the client functions of the RPC library + * (only calling APIs provided by other programs), + * This macro is used for the start process. + * + * + * RPC_end() should be called when the RPC library is no longer needed. + * + * @param pID [OUT]Pointer to the RPC_ID of the program + * @see RPC_start + * @see RPC_end + */ +/** @brief Start processing of the RPC library + * + * - With an open socket, RPC_ID, and API call dispatching functions + * Register in the global variable (managed separately for each thread and RPC_ID) + * - Starting use as a server + * - func specifies a function pointer (defined in stub) that is not a NULL. + * - Specifies a fixed ID defined in rpc_id.h as the ID. + * - If the same thread has already started using the server, an error code is returned. + * - When the server function is started for the first time in a process, + * one subthread is started to process received packets + * in the background. + * - Starting use as a client + * - NULL is specified in the func. + * - In principle, an invalid ID value (RPC_NO_PORT) is specified. + * This function automatically assigns IDs and returns the assignment result to pID. + * - However, if another program has already started using it as a client, + * it shares the socket/RPC_ID instead of creating a new socket. + * - Exceptionally, it is allowed to specify a fixed ID defined in rpc_id.h as the ID. + * This is the only way to use RPC_start() in programs + * where it is difficult to always call RPC_end() at the end of use by program structure/design. + * - In this case, the pID argument is not referenced. + * - The maximum number of threads that use the RPC library in a process is + * specified by RPC_MAX_THREADS_IN_PROCESS. + * + * @param id [IN]RPC_ID of the program (in the case of RPC_NO_PORT, this means automatic assignment) + * @param dispatch_func Dispatching functions (defined in stub files for servers, + * and NULL specified in programs that do not provide APIs) + * @param pID [OUT]RPC_ID of the automatically assigned program + * + * @retval RPC_OK: normal completion + * @retval Otherwise: Abnormal termination (FATAL) + * + * @note Normally, this function is not called directly, but the following macro is used. + * - RPC_START_SERVER(ID) + * For programs that provide RPC server functions. + * This macro is also used when both server and client functions are used. + * - RPC_START_CLIENT(pID) + * For programs that use only the RPC client function. + */ + RPC_Result +RPC_start(RPC_ID id, RPC_dispatch_func_t func, RPC_ID *pID, INT32 secure_check) +{ +#if defined(RPC_USE_SYSLOG) + static int init_syslog = 0; + + if (init_syslog == 0) { + openlog("librpc", LOG_PID, LOG_USER); + setlogmask(LOG_UPTO(LOG_INFO)); + /* setlogmask(LOG_MASK(LOG_DEBUG)); */ + init_syslog = 1; + if (func != NULL) + RPC_LOG_STATE("RPC_START_SERVER(%#x)\n", id); + } +#endif /* RPC_USE_SYSLOG */ + + if (func != NULL && id == RPC_NO_ID) { /* No ID is specified despite as a server */ + RPC_LOG_ERR("Invalid RPC_start server arg"); + return RPC_ERR_Fatal; + } + if (func != NULL && pID != NULL) { /* Requested obtaining pID despite as a server */ // LCOV_EXCL_BR_LINE 200: macro guarantee impossible both not NULL, RPC_START_*** + RPC_LOG_ERR("Invalid RPC_start server arg"); // LCOV_EXCL_START 200: macro guarantee impossible both not NULL, RPC_START_*** + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + if (func == NULL && id != RPC_NO_ID) { /* Specified ID despite as a client */ + RPC_LOG_ERR("Invalid RPC_start server arg"); + return RPC_ERR_Fatal; + } +#if defined(RPC_USE_UNIX_AUTOBIND) + if (func == NULL && pID == NULL) { + /* pID is NULL despite as a client (not supported for ID-specified clients) */ + RPC_LOG_ERR_W_NAME("RPC_Start(ID, NULL, NULL) is no longer supported, ID is auto-assigned"); + return RPC_ERR_Fatal; + } +#else /* !AUTOBIND */ + if (func == NULL && id == RPC_NO_ID && pID == NULL) { + /* pID is NULL despite as an auto-assigned client */ + RPC_LOG_ERR("Invalid RPC_start arg"); + return RPC_ERR_Fatal; + } +#endif /* !AUTOBIND */ + if ((secure_check != NO_SECURE_CHECK) && (secure_check != NEED_SECURE_CHECK)) { // LCOV_EXCL_BR_LINE 200: macro guarantee only two value, RPC_START_*** + /* Check Arguments for Client Authentication */ + RPC_LOG_ERR("Invalid RPC_start arg"); // LCOV_EXCL_START 200: macro guarantee only two value, RPC_START_*** + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RpcThreadInfo *th = RpcMyThreadInfo(); + if (th == NULL) { + th = RpcCreateThreadInfo(); + if (th == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + return RPC_ERR_Fatal; + } + } + + /* RPC_start is already done in the same thread */ + if (func != NULL) {/* Server start */ + if (RPC_srvr_idinfo(th) != NULL) {/* Server already started */ + RPC_LOG_ERR("duplicated RPC_START_SERVER"); + return RPC_ERR_Fatal; + } + } else { /* Client start */ + if (RPC_clnt_idinfo(th) != NULL) {/* Client already started */ + if (pID != NULL) { // LCOV_EXCL_BR_LINE 6: double check + *pID = (RPC_clnt_idinfo(th))->port; + RPC_LOG_DEBUG("use existing client ID=%d", *pID); + RPC_inc_clnt_count(RPC_clnt_idinfo(th)); + } + /* + * When pID == NULL (RPC_ID fixed), there is no guarantee + * that RPC_end() will be called as many times as needed, so it does not count up. + */ + return RPC_OK; + } + } + + if (func == NULL) {/* Client start */ +#if defined(RPC_USE_UNIX_AUTOBIND) + /* Automatically assign everything without supporting ID specification */ + RPC_ID id_local = RPC_NO_ID; + RPC_Result ret = CreateClientIdinfo(th, &id_local); + if(RPC_OK != ret) return ret; + + if (pID) { // LCOV_EXCL_BR_LINE 6: double check + *pID = id_local; + } + RPC_clnt_inotify_fd(RPC_clnt_idinfo(th)) = inotify_init1(IN_CLOEXEC); + return ret; +#else /* !AUTOBIND */ + if (id == RPC_NO_ID) { + /* No port number specified -> Automatically assign an ID and port number here */ + /* + * FindUniqClientId() returns ID within the range of RPC_MIN_CLIENT_ID(1024) to RPC_MAX_CLIENT_ID(1024+32768-1) + */ + int ret; + ret = FindUniqClientId(); + if (ret < 0) { + return RPC_ERR_Fatal; + } + /* pID != NULL is already checked */ + *pID = (UINT16)ret; + return CreateClientIdinfo(th, *pID); + } else { + /* + * Client start with specified port number + * Programs that cannot guarantee an RPC_end() call + * at termination specify a fixed RPC_ID from the upper level and use it. + * (To avoid memory shortage caused by building up socket-files in /tmp/RPC) + */ + return CreateClientIdinfo(th, id); + } +#endif /* !AUTOBIND */ + } + + /* Dispatch func specified (servers) -> bind */ + CL_MonitorInit(CL_MONITOR_INIT_USER); /* Using the API for Error Monitoring */ + + if (RpcCreateIdInfo(th, id, func, secure_check) < 0) { + RPC_LOG_ERR("Can't create id_info"); + return RPC_ERR_Fatal; + } + + if (RPC_DEBUG) { // LCOV_EXCL_BR_LINE 7: debug + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("RPC[%s]: server thread invoked\n", RPC_DEBUG); // LCOV_EXCL_LINE 7: debug + } + char *env; + if ((env = getenv("RPC_RESPONSE_WAIT")) != NULL) { + Response_wait_msec = (unsigned int)strtol(env, NULL, 10); + } + + return RPC_OK; +} + + static void +RpcEndSub(RpcThreadInfo *th, RpcIdInfo *idinfo) { + int sockfd; +#if !defined(RPC_USE_UNIX_AUTOBIND) + char path[120]; + + rpc_set_socket_name(path, RPC_my_id(idinfo)); +#endif /* !AUTOBIND */ + sockfd = idinfo->sock; + RpcDestroyIdInfo(th, idinfo); + close(sockfd); +#if !defined(RPC_USE_UNIX_AUTOBIND) + unlink(path); +#endif /* !AUTOBIND */ +} + +/** @brief RPC Library End-of-Use Processing + * + * - Perform termination processing such as closing the opened socket, releasing the memory. + * (Server/Client Common) + * - If there are no programs in the thread that use RPC_ID, + * the subthread started by RPC_start is terminated. + * - Each RPC_ID must be called before the program exits. + * - RPC_end must be called by the thread that performed the RPC_start. + * - Ignored unused or no longer used RPC_ID if specified. + * + * @param ID [IN]RPC_ID of the program + */ + void +RPC_end(RPC_ID id) { + RpcThreadInfo *th = RpcMyThreadInfo(); + if (th == NULL) { + return; + } + RpcIdInfo *idinfo; + idinfo = RPC_srvr_idinfo(th); + if (idinfo != NULL && RPC_my_id(idinfo) == id) {/* srvr */ + RpcEndSub(th, idinfo); + } + + idinfo = RPC_clnt_idinfo(th); + if (idinfo != NULL && RPC_my_id(idinfo) == id) {/* client */ + + RPC_dec_clnt_count(idinfo); + if (RPC_clnt_count(idinfo) == 0) { + /* Deleting management table of the communication destination server PID */ + RpcAllDeleteSrvrPid(idinfo); + close(RPC_clnt_inotify_fd(idinfo)); + + RpcEndSub(th, idinfo); + } + } + if (RPC_srvr_idinfo(th) == NULL && RPC_clnt_idinfo(th) == NULL) { + RPC_LOG_DEBUG("destroy thread info %p", th); + RpcDestroyThreadInfo(); + } +} + +/** @brief RPC library use termination processing (forced cleanup at process termination) + * + * Deletes the socket file created for RPC communication in the process. + * For to release the resources of programs that use the RPC library with RPC_end() in principle, + * but this API is an insurance process to eliminate socket file leaks. + * + * - Since it is assumed that the socket is called immediately before the process terminates, + * closing sockets and releasing memory is not performed automatically when the process terminates. + * - All RPC processing (both server and client) after this API call cannot be used. + * Operation is not guaranteed even if RPC_START is performed again after that. + * + * No action for versions of the RPC library that use Unix autobind. + */ + void +RPC_end_all(void) { +#if !defined(RPC_USE_UNIX_AUTOBIND) + RpcUnlinkSocketFiles(); +#endif +} + +/** + * @fn RPC_Result RPC_set_API_timeout(RPC_ID id, UINT32 sec) + * @brief Setting the timeout period during server API processing + * + * @param sec [IN] Timeout (sec) Set within the range of 1 to 60 sec. + * + * @retval RPC_OK: normal completion + * @retval RPC_ERR_Configuration: Argument out of range + * @retval RPC_ERR_Fatal: Fatal error + */ + RPC_Result +RPC_set_API_timeout(INT32 sec) { + /* param check */ + if ((sec > 60) || (sec < 1)) { + RPC_LOG_ERR( "RPC_set_API_timeout() : Invalid Param." ); + return RPC_ERR_Configuration; + } + + /* thread_info check */ + RpcThreadInfo *th = RpcMyThreadInfo(); + THREAD_INFO_CHECK(th); + + /* thread_info->id_info check */ + if (RPC_srvr_idinfo(th) != NULL ) { // LCOV_EXCL_BR_LINE 200: server start abnormal can't test + RpcIdInfo *idinfo = RPC_srvr_idinfo(th); + + /* thread_info->id_info->apicall_info check */ + if( RPC_apicall_info(idinfo) != NULL ) { // LCOV_EXCL_BR_LINE 200: server start abnormal can't test + RPC_apicall_api_timeout_sec(idinfo) = sec; + } else { // LCOV_EXCL_START 200: server start abnormal can't test + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR( "No apicall_info" ); + return RPC_ERR_Fatal; + } + + } else { + RPC_LOG_STATE("No srvr_id info"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + return RPC_OK; +} + + +/** @brief API call execution function (client side) + * + * (These functions are called from within a client-facing STUB. Users never use these directly.) + */ + RPC_Result +RPC_API_call(RPC_ID server, UINT16 api_num, + const char *args_string, unsigned int args_size, + char **ret_string, unsigned int *ret_size) { + *ret_string = NULL; + + RpcThreadInfo *th = RpcMyThreadInfo(); + + THREAD_INFO_CHECK(th); + + RpcIdInfo *idinfo; + idinfo = RPC_clnt_idinfo(th); + + pid_t srvr_pid; + + if (idinfo == NULL) { // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL + /* + * In the past, the remedy of uninitialized clients has been done here. + * However, because it becomes to accumulate garbage in the /tmp/RPC by changing UNIX sockets, + * as an error without remedies. + */ + // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL + RPC_LOG_ERR_W_NAME("warning!!! RPC call without RPC_start(): server=%d, api_num=%d", server, api_num); + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert +#if defined(RPC_USE_UNIX_AUTOBIND) + RPC_ID id = RPC_NO_ID; + RPC_Result ret = CreateClientIdinfo(th, &id); +#else /* !AUTOBIND */ + int id; + id = FindUniqClientId(); + if (id < 0) { + return RPC_ERR_Fatal; + } + RPC_Result ret = CreateClientIdinfo(th, (UINT16)id); +#endif /* !AUTOBIND */ + if (ret != RPC_OK) { + return ret; + } + idinfo = RPC_clnt_idinfo(th); + if (idinfo == NULL) { + return RPC_ERR_Fatal; + } + } // LCOV_EXCL_STOP + + char api_head[RPC_APICALL_FORMAT_ARGS_START + 1]; + sprintf(api_head, RPC_APICALL_FORMAT, api_num); + + rpc_send_buf sendbuf[2]; + sendbuf[0].buf = api_head; + sendbuf[0].bytes = RPC_APICALL_FORMAT_ARGS_START; + if (args_size > 0) { + sendbuf[1].buf = args_string; + sendbuf[1].bytes = args_size; + } + + int seq_num; + +send_api_call: + seq_num = RpcSendUdp2(idinfo, server, + (api_num == RPC_API_NUM_RPC_ALIVE + ? RPC_SEND_TO_SERVER_NO_RETRY + : RPC_SEND_TO_SERVER), + RPC_PACKET_APICALL, + (args_size > 0) ? 2 : 1, sendbuf); + if (seq_num < 0) { + return RPC_ERR_No_Response; + } + + // wait for response + UINT16 response; + RPC_Result result = RpcClientWaitResponse(idinfo, (UINT32)seq_num, Response_wait_msec, + &response); + if (result != RPC_OK) { + return result; + } + + if (response == RPC_RESPONSE_API_BUSY) { /* Server is busy */ + return RPC_ERR_Busy; + } else if (response == RPC_RESPONSE_API_ERR) { /* API call error */ + RPC_LOG_STATE("APIcall error (can't queue)"); + return RPC_ERR_Fatal; + } else if (response == RPC_RESPONSE_API_DEADLOCK) { /* Server is in deadlock */ + RPC_LOG_STATE("server DeadLock."); + return RPC_ERR_Server_DeadLock; + } else if (response == RPC_RESPONSE_API_CERTIFY) { /* Authentication request */ + struct sockaddr_un srvr_sa_un, secure_sa_un; + socklen_t srvr_sa_len, secure_sa_len; + int secure_sock_un; + + /* Create client socket for authentication */ + memset(&secure_sa_un, 0, sizeof(secure_sa_un)); + secure_sa_un.sun_family = AF_UNIX; + secure_sock_un = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + RpcSetClientSecureName(secure_sa_un.sun_path, RPC_port(idinfo)); + secure_sa_len = (socklen_t)(sizeof(secure_sa_un.sun_family) + SECURE_SOCK_NAME_LEN); + if (bind(secure_sock_un, (struct sockaddr *)&secure_sa_un, secure_sa_len) < 0) { + RPC_LOG_PERROR("STREAM : bind(unix), ID:%#x", RPC_port(idinfo)); + } + idinfo->secure_sock = secure_sock_un; + + /* Destination Server Socket Setting */ + memset(&srvr_sa_un, 0, sizeof(srvr_sa_un)); + srvr_sa_un.sun_family = AF_UNIX; + RpcSetServerSecureName(srvr_sa_un.sun_path, server); + srvr_sa_len = (socklen_t)(sizeof(srvr_sa_un.sun_family) + SECURE_SOCK_NAME_LEN); + + /* Connection */ + int cr = connect(RPC_my_secure_sock(idinfo), (struct sockaddr *)&srvr_sa_un, srvr_sa_len); + if (0 > cr) { + RPC_LOG_STATE("client connect() is failed."); + return RPC_ERR_Fatal; + } + + /* Waiting for server authentication */ + RPC_Result ret_certify = RpcClientWaitCertification(idinfo, &srvr_pid); + close(RPC_my_secure_sock(idinfo)); + if (RPC_OK != ret_certify) {/* Authentication NG */ + RPC_LOG_STATE("denied the connection."); + return ret_certify; + } + + /* inotify monitoring of server processes */ + char intfy_fname[32]; + snprintf(intfy_fname, sizeof(intfy_fname), CL_INTFY_FILENAME_FORMAT, srvr_pid); + int wd = inotify_add_watch(RPC_clnt_inotify_fd(idinfo), intfy_fname, IN_DELETE_SELF); + if (0 > wd) { + RPC_LOG_STATE("intfy_fname is Not Found [%s].", intfy_fname); + } + + /* Register the communication destination server PID in the management table. */ + if (RPC_OK != RpcRegistSrvrPid(idinfo, server, srvr_pid, wd)) { + return RPC_ERR_Fatal; + } + goto send_api_call; /* Sending the API request again */ + + } else if (response == RPC_RESPONSE_NONE) { // LCOV_EXCL_BR_LINE 8: dead code, not implement + // Not implemented to cancel processing + // LCOV_EXCL_START 8: dead code, not implement + RPC_LOG_STATE("No response for API call"); + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_No_Response; + } // LCOV_EXCL_STOP + + // When the server ALIVE is queried, no result is returned, so return here + if (api_num == RPC_API_NUM_RPC_ALIVE) { + return RPC_OK; + } + + // API call is accepted at server + // now wait for the return packet + result = RpcClientWaitResult(idinfo, server); + if (result != RPC_OK) { + RpcDiscardAPIcallReturn(idinfo); + return result; + } + + /****** Function error and return value must be handled separately *******/ + UINT8 *return_str = RPC_apicall_return_str(idinfo); /* pgr0689 */ +#ifdef APICALL_RETURN_TIMEOUT + if (return_str == NULL) { + RPC_LOG_STATE("APIcall return timeout"); + return RPC_ERR_No_Response; + } +#else + rpc_assert(return_str != NULL); // LCOV_EXCL_BR_LINE 6: double check +#endif + + RPC_THREAD_MUTEX_LOCK(idinfo->thread_info); + + *ret_string = rpc_malloc(RPC_apicall_return_str_len(idinfo)); + if (*ret_string != NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + if (ret_size) { + *ret_size = RPC_apicall_return_str_len(idinfo); + } + memcpy(*ret_string, RPC_apicall_return_str(idinfo), + RPC_apicall_return_str_len(idinfo)); + } else { + RPC_LOG_STATE("APIcall: No Memory"); // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + result = RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + RPC_THREAD_MUTEX_UNLOCK(idinfo->thread_info); + RpcDiscardAPIcallReturn(idinfo); + + return result; +} + +/** @brief Releasing allocated memory while API call is processing + * + * (These functions are called from within a client-facing STUB. Users never use it directly.) + */ + void +RPC_free_return_string(void *ptr) { + if (ptr != NULL) { + rpc_free(ptr); + } +} + +/** @brief Retrieving file descriptors for determining whether RPC-API calls are requested + * + * - This function returns a file descriptor used to determine whether or not there is a request to the server. + * - For the FD returned by this function, Don't use the other way than the FD specified + * in the poll or select parameter. + * - Intended use + * - Obtain FD using this function. + * - Wait for data to arrive by poll or select. + * - Call RPC_process_API_request() when data arrived. + * - This procedure performs handling request of the API call from the client. + * (Server-side API function is executed.) + * + * @param id [IN]RPC_ID of the server program. + * @param fd [OUT]Storage of file descriptor + * + * @retval RPC_OK: normal completion + * @retval Otherwise: Abnormal termination (FATAL) + * @see RPC_process_API_request + */ + RPC_Result +RPC_get_fd(RPC_ID id, int *fd) { + if ((id == RPC_NO_ID) || (fd == NULL)) { + return RPC_ERR_Fatal; + } + rpc_assert(fd != NULL); // LCOV_EXCL_BR_LINE 6: double check + + RpcThreadInfo *th = RpcMyThreadInfo(); + + THREAD_INFO_CHECK(th); + + SUB_THREAD_CHECK(); // LCOV_EXCL_BR_LINE 15: macro define in rpc_lib.c + + RpcIdInfo *idinfo = RPC_srvr_idinfo(th); + + rpc_assert(idinfo != NULL && RPC_my_id(idinfo) == id); // LCOV_EXCL_BR_LINE 6: double check + + *fd = RPC_pipe_sub_main(th)[PIPE_READ]; + + return RPC_OK; +} + +/** API Call Request Handling +*/ + static RPC_Result +ProcessAPIcallRequest(RpcIdInfo *idinfo, RPC_ID client, UINT16 api_num, + char *args_string, unsigned int args_size) { + /* ---------------------------- + * call API dispatch function + * ---------------------------- + */ + + /* API Running Client RPC_ID Setting */ + RPC_apicall_in_process_client(idinfo) = client; + + char *ret_string = NULL; + unsigned int ret_size = 0; + RPC_dispatch_func_t dispatch = RPC_apicall_dispatch_func(idinfo); + rpc_assert(dispatch != NULL); // LCOV_EXCL_BR_LINE 6: double check + RPC_Result api_ret; + api_ret = dispatch(api_num, args_string, args_size, &ret_string, &ret_size); /* pgr0060 */ + + unsigned char retcode[RPC_RETCODE_LEN+1]; + sprintf((char *)retcode, "%08x ", api_ret); + + rpc_send_buf sendbuf[2]; + sendbuf[0].buf = retcode; + sendbuf[0].bytes = sizeof(retcode) - 1; + + int seq_num; + + if (ret_string != NULL) { + sendbuf[1].buf = ret_string; + sendbuf[1].bytes = ret_size; + seq_num = RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT, + RPC_PACKET_APIRETURN, 2, sendbuf); + } else { + seq_num = RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT, + RPC_PACKET_APIRETURN, 1, sendbuf); + } + RPC_marshall_free(1, ret_string); + + if (seq_num < 0) { + RPC_LOG_ERR("send result failed!"); + return RPC_ERR_Fatal; + } + + /* Set API Running Client RPC_ID to None */ + RPC_apicall_in_process_client(idinfo) = RPC_NO_PORT; + + /* Sleep API-processing entries */ + RPC_THREAD_MUTEX_LOCK(idinfo->thread_info); + CL_MonitorSetEntry(CL_MONITOR_TYPE_RPC, RPC_port(idinfo), + CL_MONITOR_STATE_SLEEP, 0, 0); + RPC_THREAD_MUTEX_UNLOCK(idinfo->thread_info); + + return api_ret; +} + +/** @brief Executing RPC-API calls + * + * Process all queued API execution requests from clients. + * The API function of the server program is called from here. + * If there is no API execution request, the system returns normally immediately without waiting. + * + * @param id [IN]RPC_ID of the server program + * @retval RPC_OK: normal completion + * @retval Otherwise: Fatal errors + */ + RPC_Result +RPC_process_API_request(RPC_ID id) { + if (id == RPC_NO_ID) { + return RPC_ERR_Fatal; + } + RpcThreadInfo *th = RpcMyThreadInfo(); + + THREAD_INFO_CHECK(th); + + SUB_THREAD_CHECK(); + + RpcIdInfo *idinfo = RPC_srvr_idinfo(th); + + rpc_assert(idinfo != NULL && id == RPC_my_id(idinfo)); // LCOV_EXCL_BR_LINE 6: double check + + rpc_assert(RPC_apicall_info(idinfo) != NULL /* pgr0689 */ // LCOV_EXCL_BR_LINE 6: double check + && RPC_apicall_dispatch_func(idinfo) != NULL); // LCOV_EXCL_BR_LINE 6: double check + + char c; + read(RPC_pipe_sub_main(th)[PIPE_READ], &c, sizeof(c)); + + /* Process all API calls here */ + UINT16 api_num; + RPC_ID client = RPC_NO_PORT; + RPC_Result result = RPC_OK; + char *args_string; + unsigned int args_size; + do { + api_num = RpcGetAPIRequest(idinfo, &client, + &args_string, &args_size); + + if (api_num > 0) {/* API calls were queued */ + result = ProcessAPIcallRequest(idinfo, client, api_num, + args_string, args_size); + + RpcFreeAPIArgsString(args_string); + + if (result == RPC_ERR_API_Fatal || result == RPC_ERR_Fatal) { + break; + } else { + result = RPC_OK; + } + } + } while(api_num > 0); + + return result; +} + +/** @brief Returns the operational state of the RPC server + * + * Returns whether or not the server with the specified RPC_ID is running. + * + * @param id [IN]RPC_ID of the server program + * @retval RPC_OK: Running + * @retval RPC_ERR_No_Response: Server is not running + */ + RPC_Result +RPC_is_server_ready(RPC_ID id) { +#if defined(RPC_USE_UNIX_AUTOBIND) + char *ret_string = NULL; + unsigned int ret_size; + RPC_Result ret; + + // Invoke Internal-API Calls for Server ALIVE Queries + ret = RPC_API_call(id, RPC_API_NUM_RPC_ALIVE, NULL, 0, + &ret_string, &ret_size); + RPC_free_return_string(ret_string); + + return ret; +#else /* !AUTOBIND */ + struct stat statbuf; + int err; + char sockname[128]; + + /* Check if server socket is created */ + rpc_set_socket_name(sockname, id); + err = stat(sockname, &statbuf); + if (err == 0) { + return RPC_OK; + } else { + return RPC_ERR_No_Response; + } +#endif /* !AUTOBIND */ +} + +/** @brief Registering UIDs and GID Lists + * + * Register a list of UIDs and GIDs that can be accepted by the RPC server. + * A function used by the RPC server after RPC_START_SECURE_SERVER(). + * Return error if called from an RPC client or an RPC server that has not called RPC_START_SECURE_SERVER(). + * + * @param uid_num [IN] Number of registered UIDs (number of elements in UID list array) + * @param *uid_list [IN] Start pointer of registered UID list + * @param gid_num [IN] Number of registered GIDs (number of elements in the array of GID lists) + * @param *gid_list [IN] Start pointer of registered GID list + * @retval RPC_OK: List registration completed + * @retval RPC_ERR_Fatal: Failed to save to list + */ +RPC_Result +RPC_regist_credential(int uid_num, uid_t *uid_list, int gid_num, gid_t *gid_list) { + RpcThreadInfo *th = RpcMyThreadInfo(); + THREAD_INFO_CHECK(th); + + if (NULL == RPC_srvr_idinfo(th)) { + RPC_LOG_ERR("No server thread info"); + return RPC_ERR_Fatal; + } + + RpcIdInfo *idinfo = RPC_srvr_idinfo(th); + if ((NULL == idinfo) || (NULL == RPC_apicall_info(idinfo))) { // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL + // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("No RPC_ID info"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + /* Neither UID nor GID list is specified. */ + if ((NULL == uid_list) && (NULL == gid_list)) { + RPC_LOG_ERR("RPC_regist_credential() : UID and GID list is NULL."); + return RPC_ERR_Fatal; + } + + /* UID list argument check */ + if ((NULL == uid_list) && ((0 < uid_num ) && (uid_num <= CREDENTIAL_LIST_NUM_MAX))) {/* UID list is invalid */ + RPC_LOG_ERR("RPC_regist_credential() : UID list is illegal."); + return RPC_ERR_Fatal; + } else if ((NULL != uid_list) && ((1 > uid_num) || (uid_num > CREDENTIAL_LIST_NUM_MAX))) {/* Number of UID list elements is invalid */ + RPC_LOG_ERR("RPC_regist_credential() : UID list num is illegal."); + return RPC_ERR_Configuration; + } + + /* GID list argument check */ + if ((NULL == gid_list) && ((0 < gid_num ) && (gid_num <= CREDENTIAL_LIST_NUM_MAX))) {/* GID list is invalid */ + RPC_LOG_ERR("RPC_regist_credential() : GID list is illegal."); + return RPC_ERR_Fatal; + } else if ((NULL != gid_list) && ((1 > gid_num) || (gid_num > CREDENTIAL_LIST_NUM_MAX))) {/* Number of GID list elements is invalid */ + RPC_LOG_ERR("RPC_regist_credential() : GID list num is illegal."); + return RPC_ERR_Configuration; + } + + if (NO_SECURE_CHECK == RPC_secure_check(idinfo)) {/* Return error if registration is not necessary */ + RPC_LOG_ERR("Needless secure check."); + return RPC_ERR_Fatal; + } + + if (REGISTERED == RPC_regist_credential_info(idinfo)) {/* Return error if a list has already been registered */ + RPC_LOG_ERR("credential info has been registered already."); + return RPC_ERR_Fatal; + } + + /* Allocate as many memory areas as there are UID and GID lists */ + RPC_apicall_info(idinfo)->uid_list = rpc_malloc(sizeof(uid_t) * (unsigned int)uid_num); + if (NULL == RPC_apicall_info(idinfo)->uid_list) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + RPC_LOG_ERR("Can't malloc uid_list."); // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + RPC_apicall_info(idinfo)->gid_list = rpc_malloc(sizeof(gid_t) * (unsigned int)gid_num); + if (NULL == RPC_apicall_info(idinfo)->gid_list) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + RPC_LOG_ERR("Can't malloc gid_list."); // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + /* Copy UID and GID registration list and number of elements */ + memcpy(RPC_apicall_info(idinfo)->uid_list, uid_list, sizeof(uid_t) * (unsigned int)uid_num); /* UID list */ + memcpy(RPC_apicall_info(idinfo)->gid_list, gid_list, sizeof(gid_t) * (unsigned int)gid_num); /* GID list */ + RPC_uid_num(idinfo) = uid_num; /* Number of elements in the UID list */ + RPC_gid_num(idinfo) = gid_num; /* Number of elements in the GID list */ + + /* Set whether to register authentication information to Yes/No */ + RPC_regist_credential_info(idinfo) = REGISTERED; + + return RPC_OK; +} + +/** @brief Obtain authentication info (UID, GID) of API requesting client + * + * Obtain the UID and GID of the client that requested the API processing being executed. + * Return error if called from an RPC client or to an RPC server that has not called RPC_START_SECURE_SERVER(). + * This function should be called within an API function (in other words, API is being executed) provided to the client. + * if called the other function, error is returned because there is no API being executed. + * + * @param *client_uid [OUT] Requesting client UID of running API + * @param *client_gid [OUT] Requesting client GID of running API + * @retval RPC_OK: Succeeded to obtain of authentication info + * @retval RPC_ERR_Fatal: Failed to obtain of authentication Info + */ +RPC_Result +RPC_get_client_credential(uid_t *client_uid, gid_t *client_gid) { + RpcThreadInfo *th = RpcMyThreadInfo(); + THREAD_INFO_CHECK(th); + + if (NULL == RPC_srvr_idinfo(th)) { + RPC_LOG_ERR("No server thread info"); + return RPC_ERR_Fatal; + } + + RpcIdInfo *idinfo = RPC_srvr_idinfo(th); + if ((NULL == idinfo) || (NULL == RPC_apicall_info(idinfo))) { // LCOV_EXCL_BR_LINE 8: dead code, idinfo always isn't NULL + // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("No RPC_ID info"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + if ((NULL == client_uid) || (NULL == client_gid)) {/* Argument check */ + RPC_LOG_ERR("RPC_regist_credential() : Invalid Param."); + return RPC_ERR_Fatal; + } + + if (NO_SECURE_CHECK == RPC_secure_check(idinfo)) {/* Return error if no security */ + RPC_LOG_ERR("Needless secure check."); + return RPC_ERR_Fatal; + } + + if (RPC_NO_PORT == RPC_apicall_in_process_client(idinfo)) {/* Return error if the API is not being executed */ + RPC_LOG_ERR("NOT in process APIcall."); + return RPC_ERR_Fatal; + } + + char buf[7], client_path_name[SOCK_NAME_LEN]; /* Client socket name */ + + /* Converting client_id to the socket name associated with RPC_ID */ + RpcSetClientName(buf, RPC_apicall_in_process_client(idinfo)); + memcpy(client_path_name, buf + 1, 5); + client_path_name[5] = '\0'; + RpcClientSockNameInfo *current = RPC_sock_info_head(idinfo); + + /* Search info of running client from the management table */ + while (NULL != current) { + if (0 == strcmp(current->client_sock_name, client_path_name)) {/* Match Running Client Info */ + *client_uid = current->uid; + *client_gid = current->gid; + return RPC_OK; + } + current = current->next; + } + RPC_LOG_ERR("Nothing client credential info."); + return RPC_ERR_Fatal; /* Not found Client info */ +} + +/** @brief Waiting for server authentication + * + * When a client requests an API to the server, + * wait for the server to check whether it is allowed to communicate. + * + * @param *idinfo [IN] Information associated with the client's RPC_ID + * + * @retval RPC_OK: Authentication OK (communication with the server is permitted) + * @retval RPC_ERR_Reject_connect: Authentication NG (Communication denied) + */ +static RPC_Result +RpcClientWaitCertification(RpcIdInfo *idinfo, pid_t *srvr_pid) { + fd_set fds; + RpcCertifyResult recv_ret; /* Authentication result from the server */ + RPC_Result ret = RPC_ERR_Fatal; + + for(;;) { + FD_ZERO(&fds); + FD_SET(RPC_my_secure_sock(idinfo), &fds); + + int sret = select(RPC_my_secure_sock(idinfo) + 1, &fds, NULL, NULL, NULL); + if (sret < 0 && errno == EINTR) {/* signal interrupt */ // LCOV_EXCL_BR_LINE 5: fail safe for libc select + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; // LCOV_EXCL_LINE 5: fail safe for libc select + } else if (sret > 0 && FD_ISSET(RPC_my_secure_sock(idinfo), &fds)) { + /* Check the response from the server */ + ssize_t rret = recv(RPC_my_secure_sock(idinfo), (char*)&recv_ret, sizeof(RpcCertifyResult), 0); + if (0 < rret) { // LCOV_EXCL_BR_LINE 5: fail safe for libc recv + switch(recv_ret.certify_res) { + case CERTIFY_OK: /* OK */ + ret = RPC_OK; + *srvr_pid = recv_ret.srvr_pid; + break; + + case CERTIFY_NG: /* NG */ + ret = RPC_ERR_Reject_connect; + break; + + default: + ret = RPC_ERR_Fatal; + break; + } + goto exit_loop_ok; + } else if(0 == rret) { // LCOV_EXCL_START 5: fail safe for libc recv + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("server process terminate."); + return RPC_ERR_Fatal; + } else { + RPC_LOG_PERROR("certification_wait recv()"); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + } + } +exit_loop_ok: + return ret; +} + +/** @brief Register the PID of the communication destination server in the management table. + * + * Register a pair of the PID and ID of the server in the management table. + * + * @param *idinfo [IN] Information associated with the client's RPC_ID + * @param srvr_rpc_id [IN] RPC_ID of the communication destination server + * @param srvr_pid [IN] PID of the communication destination server + * + * @retval RPC_OK : Registration completed + * @retval RPC_ERR_Fatal : Registration failed + */ +static RPC_Result +RpcRegistSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, pid_t srvr_pid, int wd) { + if ((NULL == idinfo) || (srvr_rpc_id == RPC_NO_ID) || (0 > srvr_pid)) { // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("RpcRegistSrvrPid() : Invalid Param."); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RpcSrvrPidInfo *srvr_pid_buf, *current; + + srvr_pid_buf = rpc_malloc(sizeof(RpcSrvrPidInfo)); + if( srvr_pid_buf == NULL ){ // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + srvr_pid_buf->srvr_rpc_id = srvr_rpc_id; /* Server RPC_ID */ + srvr_pid_buf->srvr_pid = srvr_pid; /* Server PID */ + srvr_pid_buf->wd = wd; /* wd */ + srvr_pid_buf->next = NULL; /* Next node in the communication destination server PID management table */ + + if (0 == RPC_srvr_pid_head(idinfo)) { + RPC_srvr_pid_head(idinfo) = srvr_pid_buf; + } else { + for (current = RPC_srvr_pid_head(idinfo); current->next != NULL; current = current->next) + ; + current->next = srvr_pid_buf; + } + return RPC_OK; +} + +/** @brief Delete Termination Process PID from Management Table + * + * Check whether the terminated process matches the communicating server process, and delete it from the management table. + * + * @param *idinfo [IN] Information associated with the client's RPC_ID + * @param srvr_rpc_id [IN] Currently communicating server RPC_ID + * @param wd [IN] Wd of the termination process + * + * @retval RPC_OK : Deletion completed + * @retval RPC_ERR_Server_Finish: Deletion completed (server process in communication terminated) + * @retval RPC_ERR_Fatal : Argument error + */ + RPC_Result +RpcDeleteSrvrPid(RpcIdInfo *idinfo, RPC_ID srvr_rpc_id, int wd) { + if ((NULL == idinfo) || (RPC_NO_ID == srvr_rpc_id)) { // LCOV_EXCL_START 8: dead code, idinfo always isn't NULL + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("rpc_check_srvr_pid() : Invalid Param."); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RPC_Result ret = RPC_OK; + int cnt = 0; + RpcSrvrPidInfo *current, *previous; + current = RPC_srvr_pid_head(idinfo); + + while (NULL != current) { + if (wd == current->wd) { + + /* Check whether the termination process matches the communicating server process */ + if (srvr_rpc_id == current->srvr_rpc_id) { + ret = RPC_ERR_Server_Finish; + } + + /* Delete info from the Server info table */ + if (0 == cnt) {/* Delete the start of the management table */ + RPC_srvr_pid_head(idinfo) = RPC_srvr_pid_head(idinfo)->next; + rpc_free(current); + current = RPC_srvr_pid_head(idinfo); + cnt = -1; + } else {/* Delete all but the first element */ + // LCOV_EXCL_START 8: dead code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + previous->next = current->next; + rpc_free(current); + current = previous->next; + // LCOV_EXCL_STOP + } + } else { + previous = current; + current = current->next; + } + cnt ++; + } + return ret; +} + +/** @brief Delete all PID management tables of the communication destination server + * + * Releases the PID management table and deletes all data when the client terminates with RPC_end(). + * + * @param *idinfo [IN] Information associated with the client's RPC_ID + * + * @retval RPC_OK : Deletion completed + * @retval RPC_ERR_Fatal : Argument error + */ +static RPC_Result +RpcAllDeleteSrvrPid(RpcIdInfo *idinfo) { + if (NULL == idinfo) { // LCOV_EXCL_BR_LINE 6: double check in rpc_lib.c --> RPC_end() + RPC_LOG_ERR("RpcAllDeleteSrvrPid() : Invalid Param."); // LCOV_EXCL_START 6: double check in rpc_lib.c --> RPC_end() + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RpcSrvrPidInfo *current = RPC_srvr_pid_head(idinfo); + while (NULL != current) { + + if (0 <= current->wd) { + inotify_rm_watch(RPC_clnt_inotify_fd(idinfo), current->wd); + } + + RpcSrvrPidInfo *previous = current; + current = current->next; + + rpc_free(previous); + } + RPC_srvr_pid_head(idinfo) = NULL; + return RPC_OK; +} + +/** @brief Logging RPC-API calling process + * + * Receive File name, function name and line-number of the client calling API and API-function-name, and logging them. + * + * @param filename [IN]Pointer to caller filename string + * @param funcname [IN]Pointer to caller function-name string + * @param line [IN]Line-number in the source file of the client + * @param apiname [IN]Pointer to call-API-function-name string + * @retval 0: normal completion + * @retval Otherwise: Fatal error + */ + int +RPC_record_dbg_log( const char *filename, const char *funcname, int line, + const char *apiname ) { + printf( "[RPC debug log]%s() called from %s() [%s, line %d]\n", + apiname, funcname, filename, line ); + return 0; +} + +/** @}*/ diff --git a/otherservice/rpc_library/library/src/rpc_marshall.c b/otherservice/rpc_library/library/src/rpc_marshall.c new file mode 100755 index 0000000..8a4a56a --- /dev/null +++ b/otherservice/rpc_library/library/src/rpc_marshall.c @@ -0,0 +1,740 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_marshall.c + * @brief RPC Library Internal Implementation--Argument Conversion During API Calls + * + */ +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <math.h> + +#include <other_service/rpc.h> +#include "rpc_internal.h" + +#include "apidef.tab.h" +#include "apidef.h" + +/** @addtogroup RPClib_in + * @{ + */ +/** Structures for String Add Operations */ +typedef struct { + char *start; + char *wp; + unsigned int units; + unsigned int remain; +} RpcString; + +#ifdef STRETCH_STRING +#define _STRING_ALLOC_UNIT 512 +#else +/* + * Batch allocate total bytes of arguments + data to be added internally + * (maximal 6 bytes per argument) + */ +#define _STRING_ALLOC_UNIT \ + (RPC_MAX_API_ARG_TOTAL_SIZE + RPC_MAX_API_ARG_NUM * (2 + 4)) +#endif + +#define _ENOUGH_SPACE_FOR_ALL_TYPES \ + (sizeof(UINT64) > sizeof(double) ? sizeof(UINT64) : sizeof(double)) + +static RpcString* NewRpcString(void); +#ifdef STRETCH_STRING +static int StretchString(RpcString *str, UINT16 bytes); +#endif +static char *CopyString(RpcString *str, unsigned int *size); +static void DestroyString(RpcString *str); +static inline int AppendString(RpcString *str, + const UINT8 *append, UINT16 applen); +static inline int MarshallUINT8(RpcString *str, UINT8 uc); +static inline int MarshallUINT16(RpcString *str, UINT16 uh); +static inline int MarshallUINT32(RpcString *str, UINT32 ui); +static inline int MarshallUINT64(RpcString *str, UINT64 ul); +static inline int Marshallfloat(RpcString *str, float f); +static inline int Marshalldouble(RpcString *str, double d); +static inline int MarshallUINT8Stream(RpcString *str, const UINT8 *buf, + UINT16 bytes); +static inline int MarshallString(RpcString *str, char *buf, + UINT16 bytes); +static inline int MarshallNullPointer(RpcString *str); +static inline int MarshallPointer(RpcString *str); + +static RpcString * +NewRpcString(void) { + RpcString *str; + + str = rpc_malloc(sizeof(RpcString)); + if (str == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return NULL; + } // LCOV_EXCL_STOP + + str->start = rpc_malloc(_STRING_ALLOC_UNIT); + if (str->start == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + rpc_free(str); + return NULL; + } // LCOV_EXCL_STOP + str->start[0] = '\0'; + str->wp = str->start; + str->units = 1; + str->remain = _STRING_ALLOC_UNIT - 1; + + return str; +} + +#ifdef STRETCH_STRING +static int +StretchString(RpcString *str, UINT16 bytes) { + unsigned int oldunits = str->units; + unsigned int units = 1 + (bytes / _STRING_ALLOC_UNIT) + oldunits; + if (units == oldunits) { + return 0; + } + unsigned int length = str->wp - str->start; + char *newp = rpc_malloc(units * _STRING_ALLOC_UNIT); + if (newp == NULL) { + return -1; + } + memcpy(newp, str->start, length); + rpc_free(str->start); + str->start = newp; + str->wp = str->start + length; + *(str->wp) = '\0'; + str->units = units; + str->remain += (units - oldunits) * _STRING_ALLOC_UNIT; + return 0; +} +#endif /* STRETCH_STRING */ + +static inline int +AppendString(RpcString *str, const UINT8 *append, UINT16 applen) { + rpc_assert(append != NULL); // LCOV_EXCL_BR_LINE 6: double check +#ifdef STRETCH_STRING + if (applen > str->remain) { + if (StretchString(str, applen - str->remain) < 0) { + return -1; + } + } +#else + rpc_assert(applen <= str->remain); // LCOV_EXCL_BR_LINE 6: double check +#endif + memcpy(str->wp, append, applen); + str->wp += applen; + str->remain -= applen; + return 0; +} + +static char * +CopyString(RpcString *str, unsigned int *size) { + unsigned int length = (unsigned int)(str->wp - str->start); + char *ret = rpc_malloc(length); + // LCOV_EXCL_BR_START 5: fail safe for libc malloc + if (ret == NULL) { + return NULL; + } + // LCOV_EXCL_BR_STOP + memcpy(ret, str->start, length); + if (size != NULL) { + *size = length; + } + + return ret; +} + +static void +DestroyString(RpcString *str) { + rpc_free(str->start); + rpc_free(str); +} + +static inline int +MarshallUINT8(RpcString *str, UINT8 c) { + UINT8 buf[1 + sizeof(c)]; + buf[0] = 'C'; + buf[1] = c; + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallUINT8Stream(RpcString *str, const UINT8 *buf, UINT16 bytes) { + int ret = AppendString(str, (const UINT8 *)"B", 1); + if (ret < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + return AppendString(str, buf, bytes); +} + +static inline int +MarshallVararrayStream(RpcString *str, const UINT8 *buf, UINT16 bytes) { + char head_str[1+4+1+1]; /* Area where symbol "V" + size is stored */ + sprintf(head_str, "V%03d ", bytes); + head_str[1+4+1] = '\0'; + + if (AppendString(str, (const UINT8 *)head_str, (UINT16)strlen(head_str)) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + + if (AppendString(str, buf, bytes) < 0) { // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c + return -1; + } + return 0; +} + +static inline int +MarshallString(RpcString *str, char *buf, UINT16 bytes) { + char *p = buf; + UINT16 count = 0; + /* count the number of bytes in the argument */ + while(*p != '\0' && count < (UINT16)(bytes - 1)) { + count++; + p++; + } + + char count_str[1+strlen("1024")+1+1]; + sprintf(count_str, "S%d ", count); + + if (AppendString(str, (const UINT8 *)count_str, (UINT16)strlen(count_str)) < 0 || AppendString(str, (const UINT8 *)buf, count) < 0) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + return -1; + } + return 0; +} + +static int +MarshallUINT16(RpcString *str, UINT16 uh) { + UINT8 buf[1 + sizeof(uh)]; + buf[0] = 'H'; + memcpy(buf + 1, &uh, sizeof(uh)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallUINT32(RpcString *str, UINT32 ui) { + UINT8 buf[1 + sizeof(ui)]; + buf[0] = 'I'; + memcpy(buf + 1, &ui, sizeof(ui)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshallint(RpcString *str, int i) { + return MarshallUINT32(str, (UINT32)i); +} + +static inline int +MarshallUINT64(RpcString *str, UINT64 ul) { + UINT8 buf[1 + sizeof(ul)]; + buf[0] = 'L'; + memcpy(buf + 1, &ul, sizeof(ul)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshallfloat(RpcString *str, float f) { + UINT8 buf[1 + sizeof(f)]; + buf[0] = 'F'; + memcpy(buf + 1, &f, sizeof(f)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +Marshalldouble(RpcString *str, double d) { + UINT8 buf[1 + sizeof(d)]; + buf[0] = 'D'; + memcpy(buf + 1, &d, sizeof(d)); + return AppendString(str, buf, sizeof(buf)); +} + +static inline int +MarshallPointer(RpcString *str) { + /* only to specify that a non-NULL pointer was delivered */ + return AppendString(str, (const UINT8 *)"P", 1); +} + +static inline int +MarshallNullPointer(RpcString *str /*, int code*/) { + return AppendString(str, (const UINT8 *)"N", 1); +} + +/** @ingroup RPClib_in + */ + +#define MACROMarshallPointer(TYPE) \ + do { \ + TYPE *p = (TYPE *)temp; \ + error = Marshall##TYPE(str, *p); \ + } while(0) + +#define MACROMarshallValue(TYPE, STACK_TYPE) \ + do { \ + TYPE value = (TYPE)va_arg(ap, STACK_TYPE); \ + error = Marshall##TYPE(str, value); \ + } while(0) + +char * +RPC_marshall_arguments(unsigned int *size, int dont_marshall_out_pointer, + int num_args, ...) { + rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check + va_list ap; + + RpcString *str; + str = NewRpcString(); + if (str == NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return NULL; // LCOV_EXCL_LINE 5: fail safe for libc malloc + } + + va_start(ap, num_args); + + int ii, error; + error = 0; + + for(ii = 0 ; ii < num_args && error == 0 ; ii++) { + unsigned int code, is_vararray, is_pointer, in_out, out_only; + UINT16 bytes; + unsigned int val = va_arg(ap, unsigned int); + + RPC_marshall_flag flag; + flag.all = ntohl(val); + code = flag.bits.code; + is_vararray = flag.bits.is_vararray; + is_pointer = flag.bits.is_pointer; + in_out = flag.bits.in_out; + bytes = flag.bits.bytes; + rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check + + + out_only = 0; + if (in_out == RPC_OUT_ARG) { /* OUT only argument */ + out_only = 1; + } + + if (is_pointer) { /* Argument passed by pointer */ + + void *temp = (void *)va_arg(ap, void *); + if (temp == NULL) { + /* NULL pointer */ + error = MarshallNullPointer(str); + } else if (dont_marshall_out_pointer && out_only) { + /* Not refer to the contents of a pointer */ + error = MarshallPointer(str); + } else {/* Marshall the contents of pointers */ + if (is_vararray) { + /* Variable-length array */ + error = MarshallVararrayStream(str, temp, bytes); + } else { + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACROMarshallPointer(UINT8); + break; + case rpc_INT16: + case rpc_UINT16: + MACROMarshallPointer(UINT16); + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACROMarshallPointer(int); + break; + case rpc_INT32: + case rpc_UINT32: + MACROMarshallPointer(UINT32); + break; + case rpc_INT64: + case rpc_UINT64: + MACROMarshallPointer(UINT64); + break; + case rpc_FLOAT: + MACROMarshallPointer(float); + break; + case rpc_DOUBLE: + MACROMarshallPointer(double); + break; + case rpc_STRING: + error = MarshallString(str, temp, bytes); + break; + case rpc_USER_DEFINED: + error = MarshallUINT8Stream(str, temp, bytes); + break; + default: + error = -1; + break; + } + } + } + } else {/* Argument passed by value */ + + /* Note: In this area, the code depends on the CPU architecture */ + + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACROMarshallValue(UINT8, unsigned int); + break; + case rpc_INT16: + case rpc_UINT16: + MACROMarshallValue(UINT16, unsigned int); + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACROMarshallValue(int, int); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT32: + case rpc_UINT32: + MACROMarshallValue(UINT32, UINT32); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT64: + case rpc_UINT64: + MACROMarshallValue(UINT64, UINT64); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_FLOAT: + MACROMarshallValue(float, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_DOUBLE: + MACROMarshallValue(double, double); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_USER_DEFINED: + rpc_assert(bytes <= sizeof(UINT64)); + /* This area is very architecture-dependent! */ + if (bytes <= sizeof(UINT32)) { + UINT32 value = (UINT32)va_arg(ap, UINT32); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes); + } else if (bytes <= sizeof(UINT64)) { // LCOV_EXCL_BR_LINE 6: double check + UINT64 value = (UINT64)va_arg(ap, UINT64); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes); + } + break; + default: + error = -1; + break; + } + } + } + va_end(ap); + + if (error != 0) { + DestroyString(str); + return NULL; + } + + char *ret = CopyString(str, size); + DestroyString(str); + return ret; +} + +static inline int DeMarshallUINT8(const char *from, UINT8 *ucp); +static inline int DeMarshallUINT16(const char *from, UINT16 *uhp); +static inline int DeMarshallUINT32(const char *from, UINT32 *uip); +static inline int DeMarshallUINT64(const char *from, UINT64 *ulp); +static inline int DeMarshallfloat(const char *from, float *fp); +static inline int DeMarshalldouble(const char *from, double *dp); +static inline int DeMarshallUINT8Stream(const char *from, UINT8 *buffer, + UINT16 bytes); +static inline int DeMarshallString(const char *from, char *buffer, + UINT16 bytes); + +static inline int +DeMarshallUINT8(const char *from, UINT8 *ucp) { + if (*from == 'C') { + *ucp = *(UINT8 *)(from + 1); + return 1 + sizeof(*ucp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT16(const char *from, UINT16 *uhp) { + if (*from == 'H') { + memcpy(uhp, from + 1, sizeof(*uhp)); + return 1 + sizeof(*uhp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT32(const char *from, UINT32 *uip) { + if (*from == 'I') { + memcpy(uip, from + 1, sizeof(*uip)); + return 1 + sizeof(*uip); + } else { + return -1; + } +} + +static inline int +DeMarshallint(const char *from, int *ip) { + return DeMarshallUINT32(from, (UINT32 *)ip); +} + +static inline int +DeMarshallUINT64(const char *from, UINT64 *ulp) { + if (*from == 'L') { + memcpy(ulp, from + 1, sizeof(*ulp)); + return 1 + sizeof(*ulp); + } else { + return -1; + } +} + +static inline int +DeMarshallfloat(const char *from, float *fp) { + if (*from == 'F') { + memcpy(fp, from + 1, sizeof(*fp)); + return 1 + sizeof(*fp); + } else { + return -1; + } +} + +static inline int +DeMarshalldouble(const char *from, double *dp) { + if (*from == 'D') { + memcpy(dp, from + 1, sizeof(*dp)); + + return 1 + sizeof(*dp); + } else { + return -1; + } +} + +static inline int +DeMarshallUINT8Stream(const char *from, UINT8 *buffer, UINT16 bytes) { + if (*from == 'B') { + memcpy(buffer, from + 1, bytes); + return (int)(1 + bytes); + } else { + return -1; + } +} + +static inline int +DeMarshallString(const char *from, char *buffer, UINT16 bytes) { + if (*from == 'S') { + char *start; + long len = strtol(from + 1, &start, 10); + if (len < 0 || len >= bytes) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol + return -1; + } + start++; /* skip ' ' */ + int skip = (int)(start - from); + memcpy(buffer, start, (size_t)len); + buffer[len] = '\0'; + return skip + (int)len; + } else { + return -1; + } +} + +/* Variable-length array data */ +static inline int +DemarshallVararrayInfo(const char *from, UINT16 *bytes/* OUT */) { + if (*from == 'V') { + char *end; + long len = strtol((char *)(from + 1), &end, 10); + if (len <= 0 || len > RPC_MAX_API_ARG_SIZE) { // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol + return -1; + } + *bytes = (UINT16)len; + return (int)(end - from + 1); /* skip ' ' */ + } else { + return -1; + } +} + +/** @ingroup RPClib_in + */ + +#define MACRODemarshall(TYPE) \ + do {\ + TYPE *p; \ + if (need_alloc && is_pointer) { \ + p = rpc_malloc(sizeof(TYPE)); \ + *(TYPE **)temp = p; \ + } else { \ + p = (TYPE *)temp; \ + } \ + if (p != NULL) { \ + ret = DeMarshall##TYPE(from, p); \ + } \ + } while(0) + +int +RPC_demarshall_arguments(const char *from, unsigned int size, + int need_alloc, int num_args, ...) { + rpc_assert(num_args <= RPC_MAX_API_ARG_NUM); // LCOV_EXCL_BR_LINE 6: double check + va_list ap; + va_start(ap, num_args); + + int ii, error; + error = 0; + int remain_len = (int)size; + + for(ii = 0 ; ii < num_args && error == 0 && remain_len > 0 ; ii++) { + unsigned int code, is_pointer, is_vararray; + UINT16 bytes; + unsigned int val = va_arg(ap, unsigned int); + RPC_marshall_flag flag; + flag.all = ntohl(val); + code = flag.bits.code; + is_vararray = flag.bits.is_vararray; + is_pointer = flag.bits.is_pointer; + bytes = flag.bits.bytes; + rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE); // LCOV_EXCL_BR_LINE 6: double check + + + void *temp = va_arg(ap, void *); + int ret = -1; + + if (*from == 'N') { /* NULL pointer */ + if (bytes > 0 || is_pointer != 0) { + if (need_alloc) { + *(void **)temp = NULL; + } else { + /* do nothing */ + } + ret = 1; + } + } else if (*from == 'P') { /* Pointer(no content) */ + if (need_alloc) { + if (bytes > 0) { /* String type or user-defined type */ + *(void **)temp = rpc_malloc(bytes); + } else if (is_pointer != 0) { /* Other pointers */ + *(void **)temp = rpc_malloc(_ENOUGH_SPACE_FOR_ALL_TYPES); + } + ret = 1; + } + } else { /* non-NULL pointer */ + if ( is_vararray ) { /* Variable-length array */ + ret = DemarshallVararrayInfo(from, &bytes); + if( ret < 0 ) { + va_end(ap); + return -1; /* pgr0524 */ + } + char *p; + if (need_alloc) { + p = rpc_malloc(sizeof(char)*bytes); + *(char **)temp = p; + } else { + p = (char *)temp; /* pgr0524 */ + } + if (p != NULL) { + memcpy(p, from + ret, bytes); + ret += bytes; + } + } else { + switch(code) { + case rpc_CHAR: + case rpc_INT8: + case rpc_UINT8: + MACRODemarshall(UINT8); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT16: + case rpc_UINT16: + MACRODemarshall(UINT16); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + MACRODemarshall(int); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT32: + case rpc_UINT32: + MACRODemarshall(UINT32); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_INT64: + case rpc_UINT64: + MACRODemarshall(UINT64); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_FLOAT: + MACRODemarshall(float); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_DOUBLE: + MACRODemarshall(double); /* pgr0524 */ // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c + break; + case rpc_USER_DEFINED: { + UINT8 *p; + if (need_alloc && is_pointer) { + p = rpc_malloc(bytes); + *(UINT8 **)temp = p; + } else { + p = (UINT8 *)temp; /* pgr0524 */ + } + if (p != NULL) { + ret = DeMarshallUINT8Stream(from, p, bytes); + } + break; + } + case rpc_STRING: { + char *p; + if (need_alloc) { + p = rpc_malloc(sizeof(char)*bytes); + *(char **)temp = p; + } else { + p = (char *)temp; /* pgr0524 */ + } + if (p != NULL) { + ret = DeMarshallString(from, p, bytes); + } + break; + } + default: + break; + } + } + } + if (ret < 0) { + error = 1; + } else { + remain_len -= ret; + from += ret; + } + } + va_end(ap); + + if (error) { + return -1; /* pgr0524 */ + } else { + return 0; /* pgr0524 */ + } +} + +void +RPC_marshall_free(int num, ...) { + va_list ap; + va_start(ap, num); + + int i; + for(i = 0 ; i < num ; i++) { + void *ptr = va_arg(ap, void *); // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h + if (ptr != NULL) { + rpc_free(ptr); + } + } + va_end(ap); +} diff --git a/otherservice/rpc_library/library/src/rpc_thread.c b/otherservice/rpc_library/library/src/rpc_thread.c new file mode 100755 index 0000000..df0f746 --- /dev/null +++ b/otherservice/rpc_library/library/src/rpc_thread.c @@ -0,0 +1,1224 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_thread.c + * @brief RPC Library Internal Implementation--Processing of Internally Generated Threads + * + */ +/** @addtogroup RPClib_in */ +/** @{ */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <malloc.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/select.h> +#include <sys/poll.h> +#include <sys/prctl.h> + +#include <sys/socket.h> +#include <sys/un.h> + +#include <sys/inotify.h> + +#include <other_service/rpc.h> +#include "rpc_internal.h" + +#include <native_service/cl_monitor.h> +#include <native_service/cl_process.h> + +/** Sub-threads that wake up in the RPC library */ +static RpcThreadInfo *Thread_info[RPC_MAX_THREADS_IN_PROCESS]; +static int Num_thread_info; +pthread_t g_rpc_thread = RPC_NO_THREAD; +UINT32 g_rpc_thread_alive;/**< Sub-thread running */ + +#define RPC_MAGIC_ID (('R'<<24)|('P'<<16)|('C'<<8)|'L') + +/** Pipes used for communication with sub-threads + * Read: Main thread, Write: Sub-thread */ +int g_rpc_pipe_main_sub[2] = { -1, -1 }; + +static pthread_mutex_t process_global_mutex = PTHREAD_MUTEX_INITIALIZER; +#define PROCESS_MUTEX_LOCK rpc_mutex_lock(&process_global_mutex) +#define PROCESS_MUTEX_UNLOCK rpc_mutex_unlock(&process_global_mutex) + +static void *RpcThreadMain(void *ptr); +static void NotifyMainThread(RpcThreadInfo *th); + +static void KillRpcThread(void); +static void NotifyAddServer(RpcThreadInfo *th); +static void NotifyRemoveServer(RpcThreadInfo *th); + +static RPC_Result RpcRegistSockName(RpcIdInfo *idinfo, char *client_sock_name, const struct ucred *cr, int wd); +static RPC_Result RpcCheckSockName(RpcIdInfo *idinfo, RPC_ID client_id); +static RPC_Result RpcDeleteSockName(RpcIdInfo *idinfo, int wd); +static RPC_Result RpcAllDeleteSockName(RpcIdInfo *idinfo, int inotify_fd); +static RPC_Result RpcCheckClientCredential(RpcIdInfo *idinfo, const struct ucred *cr); + +#define RPC_SUB_THREAD_WAIT_SEC 5 + +#define WAIT_FOR_SUB_THREAD(loop_cond, sec) \ +{ \ + struct timeval timeout; \ + timeout.tv_sec = sec; \ + timeout.tv_usec = 0; \ + \ + int fd = RPC_pipe_sub_main(th)[PIPE_READ]; \ + fd_set fds; \ + \ + while((loop_cond)) { \ + FD_ZERO(&fds); \ + FD_SET(fd, &fds); \ + int sret = select(fd + 1, &fds, NULL, NULL, &timeout); \ + if (sret < 0 && errno == EINTR) { \ + continue; \ + } else if (sret > 0 && FD_ISSET(fd, &fds)) { \ + char c; \ + read(fd, &c, sizeof(c)); \ + } else { \ + break; \ + } \ + } \ +} + +RUNS_IN_CALLERS_THREAD + RpcThreadInfo * +RpcMyThreadInfo(void) { + RpcThreadInfo *ret = NULL; + int i; + pthread_t me = pthread_self(); + + PROCESS_MUTEX_LOCK; + for(i = 0; i < RPC_MAX_THREADS_IN_PROCESS ; i++) { + if (Thread_info[i] != NULL + && pthread_equal(Thread_info[i]->thread, me)) { + ret = Thread_info[i]; + break; + } + } + PROCESS_MUTEX_UNLOCK; + return ret; +} + +RUNS_IN_CALLERS_THREAD + RpcThreadInfo * +RpcCreateThreadInfo(void) { + int i; + pthread_t me = pthread_self(); + + PROCESS_MUTEX_LOCK; + /* Look for a free slot to store the thread info pointer */ + for(i = 0; i < RPC_MAX_THREADS_IN_PROCESS ; i++) { + if (Thread_info[i] != NULL) { + if (pthread_equal(Thread_info[i]->thread, me)) { // LCOV_EXCL_BR_LINE 6: double check + PROCESS_MUTEX_UNLOCK; // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return Thread_info[i]; + } // LCOV_EXCL_STOP + } else { + break; + } + } + + if (i == RPC_MAX_THREADS_IN_PROCESS) { + PROCESS_MUTEX_UNLOCK; + //CONFIG_ASSERT("Must increase RPC_MAX_THREADS_IN_PROCESS"); + RPC_LOG_ERR("Must increase RPC_MAX_THREADS_IN_PROCESS"); + return NULL; + } + + /* Allocate area for thread info */ + // Because there is a timing when the server sub-thread is accessed without being initialized, + // corrected so as to fill up to 0 in the MUTEX. + RpcThreadInfo *th = rpc_malloc(sizeof(*th)); + if (th != NULL) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + memset(th, 0, sizeof(*th)); + Thread_info[i] = th; + th->magic = RPC_MAGIC_ID; + Num_thread_info++; + } + PROCESS_MUTEX_UNLOCK; + + if (th == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("Can't alloc thread_info."); + return NULL; + } // LCOV_EXCL_STOP + + /* Initializing Thread Info */ + th->thread = me; + pthread_mutex_init(&(th->th_mtx), NULL); + th->sequence_number = RPC_SEQ_NUM_START; + + return th; +} + +/* + * check if the allocated client ID conflicts with the server ID + * of the same thread + */ + static int +RpcCheckIdConflict(RpcThreadInfo *th, RPC_ID id) { + RpcIdInfo *idinfo; + idinfo = RPC_srvr_idinfo(th); + if (idinfo != NULL && RPC_my_id(idinfo) == id) { // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return 1; + } // LCOV_EXCL_STOP + return 0; +} + +/** Adding IDs with RPC_start() + * + * - Main: Create and initialize structures and tell sub-threads to add + * - Sub: Add pointer to thread info (RpcThreadInfo) and notify it to the main process + * - The main process waits for this procedure to finish. + * Use id_info->thread_info to determine completion (completed if not NULL) + */ +RUNS_IN_CALLERS_THREAD + int +RpcCreateIdInfo(RpcThreadInfo *th, + RPC_ID id, RPC_dispatch_func_t dispatch, INT32 secure_check) { + RpcIdInfo *id_info = rpc_malloc(sizeof(*id_info)); + if (id_info == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + } // LCOV_EXCL_STOP + memset(id_info, 0, sizeof(*id_info)); + + /* + * Creates a Unix domain socket based on a given number of ports + */ +#if defined(RPC_USE_UNIX_AUTOBIND) + int sock_un = -1, secure_sock_un = -1; + socklen_t sa_len; + struct sockaddr_un sa_un; + +get_id_retry: + sock_un = socket(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); /* Datagram socket for receiving API requests */ + if (sock_un < 0) { + RPC_LOG_PERROR("socket"); + goto error; + } + SET_NONBLOCK(sock_un); + SET_CLOSE_ON_EXEC(sock_un); + + /* + * Naming Rules for Unix domain Sockets + * Server:(ID=50000-59999) + * sa_un.sun_path[0] = 0x00; + * sa_un.sun_path[1] = 'S'; + * sa_un.sun_path[2-5] = sprintf("%04x", ID); + * + * Client:(ID=1-0xfffff) + * sa_un.sun_path[0] = 0x00; + * sa_un.sun_path[1-5] = sprintf("%05x", ID); + * ID is autobind by kernel during bind(see linux/net/unix/af_unix.c) + * ! Since it depends on the unix socket implementations of Linux, be careful when porting to other operating systems. + * + * ID=50000-59999 is duplicated in Server and Client, + * but generated it according to the above rules when sent in the RPClib (see rpc_udp.c) + * + * Because file deletion is leaked when the system is forcibly terminated and abnormal process termination + * by a traditional way to create and bind files under /tmp/RPC/, + * change to the above method(2009.02.04,2012.01.21) + */ + memset(&sa_un, 0, sizeof(sa_un)); + sa_un.sun_family = AF_UNIX; + if (dispatch != NULL) { // server + RpcSetServerName(sa_un.sun_path, id); + sa_len = sizeof(sa_un.sun_family) + SOCK_NAME_LEN; + } else { // client + // Automatically assign name (ID) by unix_autobind() + sa_len = sizeof(sa_un.sun_family); + } + +#else /* !AUTOBIND */ + int sock_un = -1; + struct sockaddr_un sa_un; + sa_un.sun_family = AF_UNIX; + rpc_set_socket_name(sa_un.sun_path, id); + sock_un = socket(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (sock_un < 0) { + RPC_LOG_PERROR("socket(unix)"); + goto error; + } + SET_NONBLOCK(sock_un); + SET_CLOSE_ON_EXEC(sock_un); + unlink(sa_un.sun_path); + sa_len = sizeof(sa_un); +#endif /* !AUTOBIND */ + if (bind(sock_un, (struct sockaddr *)&sa_un, sa_len) < 0) { + RPC_LOG_PERROR("DGRAM : bind(unix), ID:%#x", id); + goto error; + } + +#if defined(RPC_USE_UNIX_AUTOBIND) + if (dispatch == NULL) { // client + // Retrieves the assigned name (ID) + socklen_t len = sizeof(sa_un); + if (getsockname(sock_un, (struct sockaddr *)&sa_un, &len) < 0) { + perror("getsockname"); + goto error; + } + RpcGetClientName(sa_un.sun_path, &id); + if (RpcCheckIdConflict(th, id)) { // LCOV_EXCL_BR_LINE 8: dead code, RpcCheckIdConflict always is false + // LCOV_EXCL_START 8: dead code, RpcCheckIdConflict always is false + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_STATE("ID %d conflicts with server -- get next one", id); + close(sock_un); + goto get_id_retry; + } // LCOV_EXCL_STOP + RPC_LOG_DEBUG("client %s", sa_un.sun_path + 1); + } +#endif /* AUTOBIND */ + + id_info->port = id; + id_info->sock = sock_un; + + if (dispatch != NULL) { /* server */ + rpc_assert(th->srvr_id == NULL); // LCOV_EXCL_BR_LINE 6: double check + RpcApicallInfo *apicall = rpc_malloc(sizeof(*apicall)); + if (apicall == NULL) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + goto error; + } // LCOV_EXCL_STOP + + /* Create Socket for Authentication */ + socklen_t secure_sa_len; + struct sockaddr_un secure_sa_un; + + secure_sock_un = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); /* stream socket for authentication */ + if (secure_sock_un < 0) { + RPC_LOG_PERROR("socket"); + rpc_free(apicall); + apicall = NULL; + goto error; + } + SET_NONBLOCK(secure_sock_un); + SET_CLOSE_ON_EXEC(secure_sock_un); + + memset(&secure_sa_un, 0, sizeof(secure_sa_un)); + secure_sa_un.sun_family = AF_UNIX; + RpcSetServerSecureName(secure_sa_un.sun_path, id); + secure_sa_len = sizeof(secure_sa_un.sun_family) + SECURE_SOCK_NAME_LEN; + + /* Bind socket for authentication */ + if (bind(secure_sock_un, (struct sockaddr *)&secure_sa_un, secure_sa_len) < 0) { + RPC_LOG_PERROR("STREAM : bind(unix), ID:%#x", id); + rpc_free(apicall); + apicall = NULL; + goto error; + } + + id_info->secure_sock = secure_sock_un; + + memset(apicall, 0, sizeof(*apicall)); + apicall->dispatch_func = dispatch; + apicall->pipe_sub_main[PIPE_READ] = -1; + apicall->pipe_sub_main[PIPE_WRITE] = -1; + apicall->timeout_sec = 30; /* Server API processing timeout */ + apicall->secure_check = secure_check; /* Authentication check by UID list */ + if (NEED_SECURE_CHECK == secure_check) { /* Initializes the UID list with not-registered if secured given. */ + apicall->regist_credential_info = NO_REGISTERED; + } + apicall->sock_info_head = NULL; /* Leading Node of Source Client Socket Info */ + apicall->client_sock_name_num = 0; /* Number of elements in the source client's socket name list */ + apicall->in_process_client = RPC_NO_PORT; /* Client RPC_ID during API processing */ + + id_info->apicall = apicall; + th->srvr_id = id_info; + + /* Creating a pipe for communication pipe from sub-thread to main-thread direction */ + if (pipe(apicall->pipe_sub_main) != 0) { + RPC_LOG_PERROR("pipe"); + goto error; + } + SET_NONBLOCK(apicall->pipe_sub_main[PIPE_READ]); + SET_CLOSE_ON_EXEC(apicall->pipe_sub_main[PIPE_READ]); + SET_NONBLOCK(apicall->pipe_sub_main[PIPE_WRITE]); + SET_CLOSE_ON_EXEC(apicall->pipe_sub_main[PIPE_WRITE]); + + PROCESS_MUTEX_LOCK; + if (g_rpc_thread == RPC_NO_THREAD) { /* There are no sub-threads. */ + /* Creating a pipe for communication from main-thread to sub-thread direction */ + if (pipe(g_rpc_pipe_main_sub) != 0) { + RPC_LOG_PERROR("pipe"); + PROCESS_MUTEX_UNLOCK; + goto error; + } + + SET_NONBLOCK(g_rpc_pipe_main_sub[PIPE_READ]); + SET_CLOSE_ON_EXEC(g_rpc_pipe_main_sub[PIPE_READ]); + SET_NONBLOCK(g_rpc_pipe_main_sub[PIPE_WRITE]); + SET_CLOSE_ON_EXEC(g_rpc_pipe_main_sub[PIPE_WRITE]); + + /* Creating sub-thread */ + pthread_t read_th; + if (pthread_create(&read_th, NULL, RpcThreadMain, 0) != 0) { + RPC_LOG_PERROR("pthread_create"); + PROCESS_MUTEX_UNLOCK; + goto error; + } + g_rpc_thread = read_th; + } + PROCESS_MUTEX_UNLOCK; + + /* Instruct a sub-thread to add and wait for completion */ + NotifyAddServer(th); + // LCOV_EXCL_BR_START 15: macro define in rpc_thread.c + WAIT_FOR_SUB_THREAD((th->srvr_id->thread_info == NULL), + RPC_SUB_THREAD_WAIT_SEC); + // LCOV_EXCL_BR_STOP + rpc_assert(th->srvr_id->thread_info != NULL); // LCOV_EXCL_BR_LINE 6: double check + + } else { /* dispatch == NULL => client */ + id_info->count = 1; + id_info->thread_info = th; + th->clnt_id = id_info; + } + return 0; /* pgr0524 */ + +error: + if (g_rpc_pipe_main_sub[PIPE_READ] >= 0) { // LCOV_EXCL_BR_LINE 5: fail safe for libc socket + close(g_rpc_pipe_main_sub[PIPE_READ]); + } + if (g_rpc_pipe_main_sub[PIPE_WRITE] >= 0) { // LCOV_EXCL_BR_LINE 5: fail safe for libc socket + close(g_rpc_pipe_main_sub[PIPE_WRITE]); + } + if (id_info->apicall != NULL) { + if (id_info->apicall->pipe_sub_main[PIPE_READ] >= 0) { + close(id_info->apicall->pipe_sub_main[PIPE_READ]); + } + if (id_info->apicall->pipe_sub_main[PIPE_WRITE] >= 0) { + close(id_info->apicall->pipe_sub_main[PIPE_WRITE]); + } + rpc_free(id_info->apicall); + } + if (sock_un != -1) { + close(sock_un); +#if !defined(RPC_USE_UNIX_AUTOBIND) + unlink(sa_un.sun_path); +#endif /* !AUTOBIND */ + } + if (secure_sock_un != -1) { + close(secure_sock_un); +#if !defined(RPC_USE_UNIX_AUTOBIND) + unlink(secure_sa_un.sun_path); +#endif /* !AUTOBIND */ + } + rpc_free(id_info); + th->srvr_id = NULL; + return -1; /* pgr0524 */ +} + +/* + * Notify an unfinished request of an error at server termination (RPC_end). + */ + static void +RpcSendErrorToPendingRequest(RpcThreadInfo *th, RpcIdInfo *idinfo) { + UINT16 api_num; + RPC_ID client; + char *args_string; + unsigned int args_size; + rpc_send_buf sendbuf; + char retcode[10]; + + do { + api_num = RpcGetAPIRequest(idinfo, &client, + &args_string, &args_size); + if (api_num > 0) { /* API calls are queued */ + + sprintf(retcode, "%08x ", RPC_ERR_Fatal); + sendbuf.buf = retcode; + sendbuf.bytes = sizeof(retcode) - 1; + RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT, + RPC_PACKET_APIRETURN, 1, &sendbuf); + RPC_LOG_STATE("sent error result to pending client %05x", client); + RpcFreeAPIArgsString(args_string); + } + } while(api_num > 0); +} + +/* + * Notify unfinished request of deadlock when deadlock of the server is detected. + */ + static void +RpcSendDeadlockToPendingRequest(RpcThreadInfo *th, RpcIdInfo *idinfo) { + UINT16 api_num; + RPC_ID client; + char *args_string; + unsigned int args_size; + rpc_send_buf sendbuf; + char retcode[10]; + + do { + api_num = RpcGetAPIRequest(idinfo, &client, + &args_string, &args_size); + if (api_num > 0) { /* API calls are queued */ + + sprintf(retcode, "%08x ", RPC_ERR_Server_DeadLock); + sendbuf.buf = retcode; + sendbuf.bytes = sizeof(retcode) - 1; + RpcSendUdp2(idinfo, client, RPC_SEND_TO_CLIENT, + RPC_PACKET_APIRETURN, 1, &sendbuf); + RPC_LOG_STATE("sent deadlock result to pending client %05x", client); + RpcFreeAPIArgsString(args_string); + } + } while(api_num > 0); + + if (RPC_NO_PORT != RPC_apicall_in_process_client(idinfo)) { + sprintf(retcode, "%08x ", RPC_ERR_Server_DeadLock); + sendbuf.buf = retcode; + sendbuf.bytes = sizeof(retcode) - 1; + RpcSendUdp2(idinfo, RPC_apicall_in_process_client(idinfo), RPC_SEND_TO_CLIENT, + RPC_PACKET_APIRETURN, 1, &sendbuf); + RPC_LOG_STATE("sent deadlock result to pending client %05x", RPC_apicall_in_process_client(idinfo)); + RPC_apicall_in_process_client(idinfo) = RPC_NO_PORT; + } +} + +/** Delete RPC_ID Info by RPC_end() + * + * - Main: Notify sub of deletion of RPC_ID info. + * - Sub: Delete a pointer from thread info (RpcThreadInfo) and notify main of that. + * - Main waits for this procedure to finish. + * Use id_info->thread_info to determine completion (completed if NULL). + * Then, release the memory related to RPC_ID info and close the socket. + */ +RUNS_IN_CALLERS_THREAD + void +RpcDestroyIdInfo(RpcThreadInfo *th, RpcIdInfo *id_info) { + rpc_assert(id_info->count == 0); // LCOV_EXCL_BR_LINE 6: double check + if (id_info->apicall) { + if (g_rpc_thread_alive != 0) { + NotifyRemoveServer(th); + /* Wait for a sub-thread to recognize IDinfo deletion */ + // LCOV_EXCL_BR_LINE 15: macro define in rpc_thread.c + WAIT_FOR_SUB_THREAD((th->srvr_id->thread_info != NULL), + RPC_SUB_THREAD_WAIT_SEC); + // LCOV_EXCL_BR_STOP + rpc_assert(th->srvr_id->thread_info == NULL); /* not recognized yet */ // LCOV_EXCL_BR_LINE 6: double check + } + + if (id_info->apicall->pipe_sub_main[PIPE_READ] >= 0) { + close(id_info->apicall->pipe_sub_main[PIPE_READ]); + } + if (id_info->apicall->pipe_sub_main[PIPE_WRITE] >= 0) { + close(id_info->apicall->pipe_sub_main[PIPE_WRITE]); + } + if (id_info->secure_sock >= 0) { + close(id_info->secure_sock); + } + rpc_free(id_info->apicall); + th->srvr_id = NULL; + } else { + th->clnt_id = NULL; + } + rpc_free(id_info); +} + +RUNS_IN_CALLERS_THREAD + void +RpcDestroyThreadInfo(void) { + unsigned int i; + RpcThreadInfo *th = RpcMyThreadInfo(); + if (th == NULL) { + return; + } + + RPC_THREAD_MUTEX_LOCK(th); + if (th->thread == RPC_NO_THREAD) { // LCOV_EXCL_BR_LINE 6: double check + RPC_THREAD_MUTEX_UNLOCK(th); // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return; + } // LCOV_EXCL_STOP + th->thread = RPC_NO_THREAD; + RPC_THREAD_MUTEX_UNLOCK(th); + + PROCESS_MUTEX_LOCK; + /* + * Remove the pointer from the global variable. + * Subsequent calls to RpcMyThreadInfo() return NULL + */ + for(i = 0; i < RPC_MAX_THREADS_IN_PROCESS ; i++) { + if (th == Thread_info[i]) { + Thread_info[i] = NULL; + Num_thread_info--; + break; + } + } + PROCESS_MUTEX_UNLOCK; + BUG_ASSERT(i < RPC_MAX_THREADS_IN_PROCESS, "No info in Thread_info[]"); // LCOV_EXCL_BR_LINE 15: marco defined in rpc_internal.h + + if (Num_thread_info == 0 && g_rpc_thread_alive != 0) { + KillRpcThread(); + char name[32]; + prctl(PR_GET_NAME, name); + RPC_LOG_DEBUG("[%s]waiting for sub thread to join...", name); + pthread_join(g_rpc_thread, NULL); + RPC_LOG_DEBUG("[%s]sub thread joined.", name); + g_rpc_thread = RPC_NO_THREAD; /* bug fix */ + rpc_assert(g_rpc_thread_alive == 0); // LCOV_EXCL_BR_LINE 6: double check + close(g_rpc_pipe_main_sub[PIPE_READ]); + close(g_rpc_pipe_main_sub[PIPE_WRITE]); + } + + if (th->srvr_id != NULL) { // LCOV_EXCL_BR_LINE 6: double check + RpcDestroyIdInfo(th, th->srvr_id); // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + th->srvr_id = NULL; + } // LCOV_EXCL_STOP + if (th->clnt_id != NULL) { // LCOV_EXCL_BR_LINE 6: double check + RpcDestroyIdInfo(th, th->clnt_id); // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + th->clnt_id = NULL; + } // LCOV_EXCL_STOP + + pthread_mutex_destroy(&(th->th_mtx)); + rpc_free(th); +} + +#if !defined(RPC_USE_UNIX_AUTOBIND) +/** + * Sub-function of RPC_end_all() + * + * Assuming releasing memory and closing the socket are processing at immediately after the end of the process, + * Suppress socket file leaks by only deleting socket files because to avoid deadlocks and shorten the time + * by exclusive processing. + */ + void +RpcUnlinkSocketFiles(void) { + int i; + char sock_name[16]; + + for(i = 0; i < RPC_MAX_THREADS_IN_PROCESS ; i++) { + RpcThreadInfo *th = Thread_info[i]; + if (th != NULL) { + if (th->srvr_id != NULL) { + rpc_set_socket_name(sock_name, RPC_port(th->srvr_id)); + RPC_LOG_STATE("unlink srvr %s", sock_name); + unlink(sock_name); + } + if (th->clnt_id != NULL) { + rpc_set_socket_name(sock_name, RPC_port(th->clnt_id)); + RPC_LOG_STATE("unlink clnt %s", sock_name); + unlink(sock_name); + } + } + } +} +#endif /* !AUTOBIND */ + +/* + * Deadlock detection check for servers in the thread + */ + static void +RpcDeadlockCheck(RpcThreadInfo** thread_info, unsigned int num_thread_info) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + unsigned int i = 0; + for(i = 0 ; i < num_thread_info ; i++) { + RpcThreadInfo *th = thread_info[i]; + RpcIdInfo *idinfo = th->srvr_id; + CL_MonitorEntry_t entry; + + if (0 == CL_MonitorGetEntry(CL_MONITOR_TYPE_RPC, RPC_port(idinfo), &entry)) { + if (entry.state == CL_MONITOR_STATE_RUN && entry.timeout <= ts.tv_sec) { + RPC_LOG_ERR("Time Out : RPC_ID = %#x API_NUM = %#x", entry.id, entry.user_data); + fprintf(stderr, "Time Out : RPC_ID = %#x API_NUM = %#x\n", entry.id, entry.user_data); + RpcSendDeadlockToPendingRequest(th, idinfo); + } + } + } +} +/** Main functions of the sub-threads (READING THREAD) +*/ +RUNS_IN_READING_THREAD + static void * +RpcThreadMain(void *ptr __attribute__((unused))) { + struct pollfd wait_files[RPC_MAX_FD_IN_PROCESS]; + RpcThreadInfo *thread_info[RPC_MAX_THREADS_IN_PROCESS]; + unsigned int num_thread_info = 0; + + unsigned int poll_num; + int need_reset_sockfd = 1; + int normal_exit = 0; + RPC_Result result; + unsigned int i, j; + + /* Monitoring for clients process with inotify() *//* Monitoring target filename */ + const int inotify_fd = inotify_init1(IN_CLOEXEC); /* fd for process monitoring with inotify() */ + + UINT8 readbuf[RPC_UDP_PACKET_SIZE]; + memset(readbuf, 0, sizeof(UINT8) * RPC_UDP_PACKET_SIZE); + + g_rpc_thread_alive = 1; + + CL_MonitorInit(CL_MONITOR_INIT_USER); /* Using the API for Error Monitoring */ + + // Name the thread created in the RPClib (append "_R") +#define RPC_APPEND_NAME "_R" +#ifndef PRF_SIZE_PROCESSNAME +#define PRF_SIZE_PROCESSNAME 8 /* Limit name length for Profiler Analysis Tools */ +#endif + { + char *p, name[32]; + prctl(PR_GET_NAME, name); + name[PRF_SIZE_PROCESSNAME] = '\0'; + if (strlen(name) + strlen(RPC_APPEND_NAME) > PRF_SIZE_PROCESSNAME) { + p = name + PRF_SIZE_PROCESSNAME - strlen(RPC_APPEND_NAME); + } else { + p = name + strlen(name); + } + strcpy(p, RPC_APPEND_NAME); + prctl(PR_SET_NAME, name); + } + + /* Set the communication pipe with the main thread to poll fd */ + poll_num = 1; + wait_files[0].fd = g_rpc_pipe_main_sub[PIPE_READ]; + wait_files[0].events = POLLIN; + +restart: + for( ; ; ) { + if (need_reset_sockfd) { + /* Set the UDP socket of each RPC_ID to poll fd */ + PROCESS_MUTEX_LOCK; + for(i = 0, j = 0 ; i < RPC_MAX_THREADS_IN_PROCESS ; i++) { + if (Thread_info[i] != NULL) { + if (Thread_info[i]->magic != RPC_MAGIC_ID) { // LCOV_EXCL_BR_LINE 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("Someone(me?) destroyed my area!"); // LCOV_EXCL_LINE 6: double check + } + if (Thread_info[i]->srvr_id != NULL + && Thread_info[i]->srvr_id->thread_info != NULL) { + thread_info[j] = Thread_info[i]; + j++; + } + } + } + PROCESS_MUTEX_UNLOCK; + num_thread_info = j; + + poll_num = 1; + /* Register fd for monitoring with inotify() in poll() */ + wait_files[1].fd = inotify_fd; + wait_files[1].events = POLLIN; + + poll_num = 2; + for(i = 0 ; i < num_thread_info ; i++) { + /* Datagram socket for API request */ + wait_files[poll_num].fd = thread_info[i]->srvr_id->sock; /* pgr0000 */ + wait_files[poll_num].events = POLLIN; + poll_num++; + // LCOV_EXCL_BR_START 5: fail safe for libc listen + /* Authentication stream socket */ + if (0 != listen(thread_info[i]->srvr_id->secure_sock, 10)) { /* Number of queues */ + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_PERROR("listen(unix)"); // LCOV_EXCL_LINE 5: fail safe for libc listen + } + // LCOV_EXCL_BR_STOP + wait_files[poll_num].fd = thread_info[i]->srvr_id->secure_sock; + wait_files[poll_num].events = POLLIN; + poll_num++; + } + need_reset_sockfd = 0; + } + + int pollret; + pollret = poll(wait_files, poll_num, TIMEOUT_FOR_DEADLOCK_CHECK); + + int save_errno = errno; + + RpcDeadlockCheck(thread_info, num_thread_info); + if (pollret < 0) { // LCOV_EXCL_BR_LINE 5: fail safe for libc poll + if (save_errno == EINTR) { // LCOV_EXCL_START 5: fail safe for libc poll + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; + } else { + rpc_assert(pollret > 0); + goto exit_read_thread; + } // LCOV_EXCL_STOP + } + + /* Commands from the main thread (via pipe) */ + if ((wait_files[0].revents & POLLIN) == POLLIN) { + char buf[RPC_MAIN_SUB_COMMAND_SIZE]; + long ret, arg; + int cmd; + RpcThreadInfo *th; + ret = read(wait_files[0].fd, buf, sizeof(buf)); + if (ret == sizeof(buf)) { + sscanf(buf, RPC_MAIN_SUB_COMMANDs, &cmd, &arg); + switch(cmd) { + case RPC_COMMAND_ADD_SERVER: + th = (RpcThreadInfo *)arg; + th->srvr_id->thread_info = th; /* Indicate the completion of the processing */ + NotifyMainThread(th); + need_reset_sockfd = 1; + goto restart; + break; + + case RPC_COMMAND_REMOVE_SERVER: + th = (RpcThreadInfo *)arg; + RpcSendErrorToPendingRequest(th, th->srvr_id); + + RpcAllDeleteSockName(th->srvr_id, inotify_fd); /* delete client_sock_name_list */ + rpc_free((th->srvr_id)->apicall->uid_list); /* delete uid_list */ + rpc_free((th->srvr_id)->apicall->gid_list); /* delete gid_list */ + + th->srvr_id->thread_info = NULL;/* Indicate the completion of the processing */ + NotifyMainThread(th); + need_reset_sockfd = 1; + goto restart; + break; + + case RPC_COMMAND_EXIT: + /************ Termination request from the parent thread *************/ + RPC_LOG_DEBUG("Received exit command from main thread."); + normal_exit = 1; + goto exit_read_thread; + break; + } /* switch */ + } /* if (ret == sizeof(buf)) */ + } /* Complete the processing of commands from the main thread */ + + /* Client Monitoring Events with inotify() */ + if ((wait_files[1].revents & POLLIN) == POLLIN) { + UINT32 read_len = 0; + int length = 0; + char *buffer; + buffer = (char *)rpc_malloc(BUF_LEN); + if (NULL == buffer) {// LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("rpc_malloc() ERROR."); + goto exit_read_thread; + } // LCOV_EXCL_STOP + + if( (length = (int)read( inotify_fd, buffer, BUF_LEN ) ) < 0 ) { // LCOV_EXCL_START 5: fail safe for libc read + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_PERROR("inotify read() ERROR."); + rpc_free(buffer); + buffer = NULL; + goto exit_read_thread; + } // LCOV_EXCL_STOP + while ( read_len < length ) { + struct inotify_event *event = ( struct inotify_event * )&buffer[read_len]; + + if ( event->mask & IN_DELETE_SELF ) {/* Terminating a Client Process */ + int i; /* Looping variable */ + + /* Delete the source socket name from all RpcThreadInfo in the received thread */ + for(i = 0 ; i < num_thread_info ; i++) { + RpcThreadInfo *th = thread_info[i]; + RpcDeleteSockName(th->srvr_id, event->wd); + } + } + read_len += (UINT32)(EVENT_SIZE + event->len); /* Size of the inotify_event structure */ + } + rpc_free(buffer); + goto restart; + } /* Client Monitoring Events Completed with inotify() */ + + for(i = 2 ; i < poll_num ; i++) { + /* Event to the API request datagram socket */ + if ((i % 2 == 0) && ((wait_files[i].revents & POLLIN) == POLLIN)) { + unsigned int thread_info_num = ((i/2) - 1); /* Compute thread_info[thread_info_num] with events */ + RpcThreadInfo *th = thread_info[thread_info_num]; /* pgr0000 */ + RpcIdInfo *idinfo = th->srvr_id; + for(;;) { + /* RPClib packet received */ + int readret = RpcReadUdpPacket(idinfo, readbuf); + if (readret < 0) { // LCOV_EXCL_BR_LINE 5: fail safe for libc recvfrom + rpc_assert(readret >= 0); // LCOV_EXCL_START 5: fail safe for libc recvfrom + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + goto exit_read_thread; + // LCOV_EXCL_STOP + } else if (readret == 0) { + break; + } + /* successfully read udp packets */ + /* parse the packet and queue events */ + RPC_ID sender = RPC_NO_ID; + UINT32 seq_num = 0; + UINT32 size = 0; + RPC_packet_type command = RPC_PACKET_NONE; + if (RpcParsePacketHeader((const char *)readbuf, &command, &sender, &seq_num, &size) != RPC_OK) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + goto exit_read_thread; + } + + long int api_num; + char *buff; + + switch(command) { + case RPC_PACKET_APICALL: + if (RPC_DEBUG != NULL) { // LCOV_EXCL_BR_LINE 7: debug + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("RPC[%s]: received APIcall\n", RPC_DEBUG); // LCOV_EXCL_LINE 7: debug + } + // Return response without queuing for ALIVE query + api_num = strtol((const char *)(readbuf + RPC_PACKET_HEADER_LEN), NULL, 10); + if (api_num == RPC_API_NUM_RPC_ALIVE) { + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "OK", sizeof("OK")); + break; + } + + /* Return BUSY if secure and unregistered in UID-list */ + if ((NEED_SECURE_CHECK == RPC_secure_check(idinfo)) + && (NO_REGISTERED == RPC_regist_credential_info(idinfo))) { + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "BUSY", sizeof("BUSY")); + RPC_LOG_ERR("Need UID list register."); + break; + } + + result = RpcQueueAPIRequestBefore(idinfo, size, (char**)&buff); + if (result == RPC_OK) { + /* Check whether the source has been authenticated */ + if(RPC_OK == RpcCheckSockName(idinfo, sender)) { /* Registerd the name of the source socket */ + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "OK", sizeof("OK")); + RpcQueueAPIRequestAfter(idinfo, sender, + (const char *)(readbuf + RPC_PACKET_HEADER_LEN), + size, buff); + } else { /* Not registered (in other words, first communication with the source client) */ + /* Authentication request to the client */ + RPC_THREAD_MUTEX_UNLOCK(idinfo->thread_info); + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "CERT", sizeof("CERT")); + rpc_free(buff); + break; + } + } else if (result == RPC_ERR_Busy) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "BUSY", sizeof("BUSY")); + } else { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RpcSendUdpResponse(idinfo, sender, RPC_SEND_TO_CLIENT, + RPC_RESPONSE_APICALL, + seq_num, "ERR", sizeof("ERR")); + RPC_LOG_ERR("queueing APIcall failed.(%d)", result); + goto exit_read_thread; + } // LCOV_EXCL_STOP + NotifyMainThread(th); + if (RPC_DEBUG != NULL) { // LCOV_EXCL_BR_LINE 7: debug + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + printf("RPC[%s]: notified APIcall\n", RPC_DEBUG); // LCOV_EXCL_LINE 7: debug + } + break; + + default: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + BUG_ASSERT(0, "Unknown UDP packet type"); // LCOV_EXCL_LINE 15: marco defined in rpc_internal.h + goto exit_read_thread; + break; + } /* switch(command) */ + }/* for(;;) */ + + /* Event to the stream socket for authentication */ + } else if ((i % 2 != 0) && ((wait_files[i].revents & POLLIN) == POLLIN)) { + unsigned int thread_info_num = ((i-1)/2 - 1); /* Compute thread_info[thread_info_num] with events */ + struct sockaddr_un client_sa_un; + socklen_t client_len = sizeof(struct sockaddr_un); + struct ucred cr; /* Structure of client credit info */ + RpcCertifyResult send_ret; /* Authentication result to pass to the client */ + RpcThreadInfo *th = thread_info[thread_info_num]; + RpcIdInfo *idinfo = th->srvr_id; + + send_ret.certify_res = CERTIFY_NG; + send_ret.srvr_pid = 0; + + /* Obtain client credit info from a connected socket */ + int accept_sock = accept4(wait_files[i].fd, (struct sockaddr *)&client_sa_un, &client_len, SOCK_CLOEXEC); + int ret = getsockopt(accept_sock, SOL_SOCKET, SO_PEERCRED, &cr, &client_len); + if (ret == 0) { // LCOV_EXCL_BR_LINE 5: fail safe for libc getsockopt + client_sa_un = (struct sockaddr_un )client_sa_un; + /* Check if UID of client is allowed to communicate */ + if (RPC_OK == RpcCheckClientCredential(idinfo, &cr)) { + + /* Obtain the socket name associated with the RPC_ID of the client from the socket info */ + char client_sock_name[SOCK_NAME_LEN]; + RpcGetClientNameFromSock(client_sa_un.sun_path, client_sock_name); + + /* Monitoring client processes with inotify */ + char intfy_fname[32]; + snprintf(intfy_fname, sizeof(intfy_fname), CL_INTFY_FILENAME_FORMAT, cr.pid); + int wd = inotify_add_watch(inotify_fd, intfy_fname, IN_DELETE_SELF); + if (0 > wd) { // LCOV_EXCL_BR_LINE 5: fail safe for libc inotify_add_watch + RPC_LOG_STATE("intfy_fname is Not Found [%s].", intfy_fname); + } + + /* Register the source socket name in the management table */ + RpcRegistSockName(idinfo, client_sock_name, &cr, wd); + + /* Send server credit info to the client */ + send_ret.certify_res = CERTIFY_OK; + send_ret.srvr_pid = getpid(); + } + } + + /* Send authentication result to client */ + send(accept_sock, (char*)&send_ret, sizeof(RpcCertifyResult), 0); + close(accept_sock); + + goto restart; + + } else if ((wait_files[i].revents & ~POLLIN) != 0) { // LCOV_EXCL_START 5: fail safe for libc poll + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + // POLLERR, etc. on UDP port + RPC_LOG_STATE("poll error %x", wait_files[i].revents); + + if ((wait_files[i].revents & POLLNVAL) == POLLNVAL) { + need_reset_sockfd = 1; + goto restart; + } + } /* if ((wait_files[i].revents & POLLIN) == POLLIN) */ // LCOV_EXCL_STOP + + } /* processing UDP packets finished */ + + } /* end of forever loop */ + +exit_read_thread: + + g_rpc_thread_alive = 0; + for(i = 0 ; i < num_thread_info ; i++) { // LCOV_EXCL_BR_LINE 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + NotifyMainThread(thread_info[i]); /* pgr0000 */ // LCOV_EXCL_LINE 6: double check + } + + close(inotify_fd); + + if (normal_exit == 0) { // LCOV_EXCL_BR_LINE 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_CRIT("sub thread ABNORMALLY exited."); // LCOV_EXCL_LINE 6: double check + } else { + RPC_LOG_DEBUG("sub thread normally exited."); + } + return NULL; +} + +/* Notification of sub-thread -> main-thread (via pipe) */ +RUNS_IN_READING_THREAD + static void +NotifyMainThread(RpcThreadInfo *th) { + rpc_assert(th->srvr_id->apicall != NULL); // LCOV_EXCL_BR_LINE 6: double check + char c = 0; + write(th->srvr_id->apicall->pipe_sub_main[PIPE_WRITE], &c, sizeof(c)); +} + +/* Notification of main-thread -> sub-thread(via pipe) */ +/* Termination instruction */ +RUNS_IN_CALLERS_THREAD + static void +KillRpcThread(void) { + char buf[RPC_MAIN_SUB_COMMAND_SIZE]; + sprintf(buf, RPC_MAIN_SUB_COMMAND, RPC_COMMAND_EXIT, (unsigned long)0); + write(g_rpc_pipe_main_sub[PIPE_WRITE], buf, sizeof(buf)); +} + +/* AddRPC_ID */ +RUNS_IN_CALLERS_THREAD + static void +NotifyAddServer(RpcThreadInfo *th) { + char buf[RPC_MAIN_SUB_COMMAND_SIZE]; + sprintf(buf, RPC_MAIN_SUB_COMMAND, RPC_COMMAND_ADD_SERVER, + (unsigned long)th); + write(g_rpc_pipe_main_sub[PIPE_WRITE], buf, sizeof(buf)); +} + +/* Remove RPC_ID */ +RUNS_IN_CALLERS_THREAD + static void +NotifyRemoveServer(RpcThreadInfo *th) { + char buf[RPC_MAIN_SUB_COMMAND_SIZE]; + sprintf(buf, RPC_MAIN_SUB_COMMAND, RPC_COMMAND_REMOVE_SERVER, + (unsigned long)th); + write(g_rpc_pipe_main_sub[PIPE_WRITE], buf, sizeof(buf)); +} + +/* Register the socket name of the source client in the management table. */ + static RPC_Result +RpcRegistSockName(RpcIdInfo *idinfo, char *client_sock_name, const struct ucred *cr, int wd) { + if ((NULL == idinfo) || (NULL == client_sock_name) || (NULL == cr) || (0 > cr->pid)) { // LCOV_EXCL_BR_LINE 6: void *RpcThreadMain(void *ptr) + RPC_LOG_ERR("RpcRegistSockName() : Invalid Param."); // LCOV_EXCL_START 6: void *RpcThreadMain(void *ptr) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RpcClientSockNameInfo *sock_name_buf, *current; + + sock_name_buf = rpc_malloc(sizeof(RpcClientSockNameInfo)); + // LCOV_EXCL_BR_START 5: fail safe for libc malloc + if( sock_name_buf == NULL ){ + return RPC_ERR_Fatal; + } + // LCOV_EXCL_BR_STOP + strcpy(sock_name_buf->client_sock_name, client_sock_name); /* Socket name */ + sock_name_buf->pid = cr->pid; /* PID */ + sock_name_buf->uid = cr->uid; /* UID */ + sock_name_buf->gid = cr->gid; /* GID */ + sock_name_buf->wd = wd; /* Non-negative inotify monitored descriptors */ + sock_name_buf->next = NULL; /* Pointer to next node (NULL since last node) */ + + if (0 == RPC_client_sock_name_num(idinfo)) { + RPC_sock_info_head(idinfo) = sock_name_buf; + } else { + for (current = RPC_sock_info_head(idinfo); current->next != NULL; current = current->next) + ; + current->next = sock_name_buf; + } + RPC_client_sock_name_num_inc(idinfo); + return RPC_OK; +} + +/* Check if the socket name of the source client is registered in the management table */ + static RPC_Result +RpcCheckSockName(RpcIdInfo *idinfo, RPC_ID client_id) { + if ((NULL == idinfo) || (client_id == RPC_NO_ID)) { // LCOV_EXCL_BR_LINE 6: void *RpcThreadMain(void *ptr) + RPC_LOG_ERR("RpcCheckSockName() : Invalid Param."); // LCOV_EXCL_START 6: void *RpcThreadMain(void *ptr) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + char buf[7], client_path_name[SOCK_NAME_LEN]; /* Client socket name */ + + /* Converting client_id to the socket name associated with RPC_ID */ + RpcSetClientName(buf, client_id); + memcpy(client_path_name, buf + 1, 5); + client_path_name[5] = '\0'; + RpcClientSockNameInfo *current = RPC_sock_info_head(idinfo); + + /* Search source socket name in management table */ + while (NULL != current) { + if (0 == strcmp(current->client_sock_name, client_path_name)) { /* Registered socket name (authenticated) */ + return RPC_OK; + } + current = current->next; + } + return RPC_ERR_Fatal; /* Not registerd socket name (unauthenticated) */ +} + +/* Remove source client socket name from management table */ + static RPC_Result +RpcDeleteSockName(RpcIdInfo *idinfo, int wd) { + if ((NULL == idinfo) || (0 > wd)) { + RPC_LOG_ERR("RpcDeleteSockName() : Invalid Param."); + return RPC_ERR_Fatal; + } + + RpcClientSockNameInfo *current, *previous; + current = RPC_sock_info_head(idinfo); + previous = current; + int cnt = 0; + + /* Remove Source Socket Name in Management Table */ + while (NULL != current) { + if (wd == current->wd) { /* Delete element */ + if (0 == cnt) { /* Delete the start element in the management table */ + RPC_sock_info_head(idinfo) = RPC_sock_info_head(idinfo)->next; + rpc_free(current); + current = RPC_sock_info_head(idinfo); + cnt = -1; + } else { /* Delete other than the start element in the management table */ + previous->next = current->next; + rpc_free(current); + current = previous->next; + } + RPC_client_sock_name_num_dec(idinfo); + } else { /* Refer to the next node without deleting */ + previous = current; + current = current->next; + } + cnt ++; + } + + return RPC_OK; +} + +/* Remove all source client socket names in the management table */ + static RPC_Result +RpcAllDeleteSockName(RpcIdInfo *idinfo, int inotify_fd) { + if (NULL == idinfo) { // LCOV_EXCL_BR_LINE 6: double check in void RpcDestroyThreadInfo(void) + RPC_LOG_ERR("RpcAllDeleteSockName() : Invalid Param."); // LCOV_EXCL_START 6: void RpcDestroyThreadInfo(void) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + RpcClientSockNameInfo *current = RPC_sock_info_head(idinfo); + + while (NULL != current) { + RpcClientSockNameInfo *previous = current; + current = current->next; + + if (0 <= previous->wd) { + inotify_rm_watch(inotify_fd, previous->wd); + } + + rpc_free(previous); + previous = NULL; + RPC_client_sock_name_num_dec(idinfo); + } + + return RPC_OK; +} + + +/* Check if client is allowed to communicate */ + static RPC_Result +RpcCheckClientCredential(RpcIdInfo *idinfo, const struct ucred *cr) { + if ((NULL == idinfo) || (NULL == cr)) { // LCOV_EXCL_BR_LINE 6: double check in void *RpcThreadMain(void *ptr) + RPC_LOG_ERR("RpcCheckClientCredential() : Invalid Param."); // LCOV_EXCL_START 6: void *RpcThreadMain(void *ptr) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + + /* Retern RPC_OK if authentication is not required */ + if (NO_SECURE_CHECK == RPC_secure_check(idinfo)) { + return RPC_OK; + } + + INT32 i = 0; /* Loop counter */ + + /* Search client UID in registered UID list */ + for(i = 0; i < RPC_uid_num(idinfo); i++) { + if(RPC_uid_list(idinfo, i) == cr->uid) { /* Found UID in registered UID list */ + return RPC_OK; + } + } + + /* Search client GID in registered GID list */ + for(i = 0; i < RPC_gid_num(idinfo); i++) { + if(RPC_gid_list(idinfo, i) == cr->gid) { /* Found GID in registered GID list. */ + return RPC_OK; + } + } + + RPC_LOG_ERR("[Client isn't authenticated!!!!]"); + return RPC_ERR_Fatal; /* Not found UID in registered UID list */ +} diff --git a/otherservice/rpc_library/library/src/rpc_udp.c b/otherservice/rpc_library/library/src/rpc_udp.c new file mode 100755 index 0000000..0d4d59f --- /dev/null +++ b/otherservice/rpc_library/library/src/rpc_udp.c @@ -0,0 +1,473 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file rpc_udp.c + * @brief RPC Library Internal Implementation--UDP Communication + * + */ +/** @addtogroup RPClib_in */ +/** @{ */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/poll.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> // for usleep + +#include <fcntl.h> +#include <sys/un.h> + +#include <sys/inotify.h> + +#include <other_service/rpc.h> +#include "rpc_internal.h" + +static /*inline*/ UINT32 +RpcGetSequenceNumber(RpcThreadInfo *th) { + RPC_THREAD_MUTEX_LOCK(th); + UINT32 ret = th->sequence_number; + (th->sequence_number)++; + if (th->sequence_number == RPC_SEQ_NUM_INVALID) { // LCOV_EXCL_BR_LINE 200: overflow check, but test time is too long + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + th->sequence_number = RPC_SEQ_NUM_START; // LCOV_EXCL_LINE 200: overflow check, but test time is too long + } + RPC_THREAD_MUTEX_UNLOCK(th); + return ret; +} + +/** + */ +int +RpcReadUdpPacket(const RpcIdInfo *id, UINT8 *buf) { + struct sockaddr_un sa; + socklen_t sa_len = sizeof(sa); + // sa passed to recvfrom does not require initialization + + for(;;) { + + ssize_t ret = recvfrom(RPC_my_sock(id), buf, RPC_UDP_PACKET_SIZE, + 0, (struct sockaddr *)&sa, &sa_len); + + if (ret < 0) { + if (errno == EAGAIN) { // LCOV_EXCL_BR_LINE 5: fail safe for libc recvfrom + //RPC_LOG_PERROR("recvfrom port %d", RPC_port(id)); + return 0; + } else if (errno == EINTR) { // LCOV_EXCL_START 5: fail safe for libc recvfrom + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; + } else { + RPC_LOG_PERROR("recvfrom port %d", RPC_port(id)); + return -1; + } // LCOV_EXCL_STOP + } else if (ret == 0) { + RPC_LOG_STATE("*** recvfrom ret 0"); + return 0; + } else { + return (int)ret; + } + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + } // LCOV_EXCL_LINE 10: final line +} + +/** Number of sendto retries */ +#define RPC_SENDTO_RETRY 5 + +RUNS_IN_CALLERS_THREAD +RUNS_IN_READING_THREAD +/** + */ +static int +RpcSendUdpPacket(RpcIdInfo *id, + struct sockaddr_un *to, int do_retry, + void *mesg, unsigned int bytes) { + int nretry = 0; + ssize_t ret; + int myerr; + retry: + ret = sendto(RPC_my_sock(id), mesg, bytes, 0, + (struct sockaddr *)to, RPC_SOCKET_ADDR_LEN); + myerr = errno; + + if (ret < 0) { + RPC_LOG_STATE("*** sendto %s ***", to->sun_path + 1); + if (myerr == EAGAIN || (do_retry && myerr==ECONNREFUSED && ++nretry <= RPC_SENDTO_RETRY)) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + usleep(100000); +#if defined(RPC_USE_UNIX_AUTOBIND) + RPC_LOG_DEBUG("*** sendto %s ***", to->sun_path + 1); +#else /* AUTOBIND */ + RPC_LOG_DEBUG("**************** sendto retry *********************"); +#endif /* !AUTOBIND */ + goto retry; + } + errno = myerr; +#if defined(RPC_USE_UNIX_AUTOBIND) + if (do_retry) { + RPC_LOG_PERROR("sendto %s", to->sun_path + 1); + } +#endif /* !AUTOBIND */ + return -1; + } else if ((unsigned int)ret != bytes) { + RPC_LOG_STATE("can't send all"); + return -1; + } + return 0; +} + +RUNS_IN_CALLERS_THREAD +RUNS_IN_READING_THREAD +/** + */ +int +RpcSendUdp(RpcIdInfo *id, const RPC_ID receiver, int direction, RPC_packet_type type, const void *mesg, unsigned int bytes) { // LCOV_EXCL_START 8: dead code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + rpc_send_buf sendbuf; + sendbuf.buf = mesg; + sendbuf.bytes = bytes; + + return RpcSendUdp2(id, receiver, direction, type, 1, &sendbuf); +} // LCOV_EXCL_STOP +RUNS_IN_CALLERS_THREAD +RUNS_IN_READING_THREAD +/** UDP packet transmission process + * + * UDP packet format + * @verbatim ++--------------+--------------+ +|*1|*2|*3|*4|*5| PAYLOAD | ++--------------+--------------+ +@endverbatim + * + * *1 to *5 indicate the header. @see RPC_PACKET_HEADER + * + * - *1: [@%-2d] Type of packet + * - @see RPC_packet_type + * - *2: [@%-5x] Source RPC_ID + * - *3: [@%-8x] Sequence number + * - Set the value incremented from 1. This value must be unique for each source thread. + * - In the case of response packets, this field contains the sequence number of the packet from which the response was received. + * - *4: [@%-4u] Size of send data + * - In the case of sending data consists of single packet in PAYLOAD, this field contains number of the packet. + * - For a multipacket, the first packet contains the sum of the PAYLOAD of all packets, + * the last packet contains the PAYLOAD bytes of the packet. + * All other intermediate packets are filled with 0.(With up to two packets in the current constraint, + * there are no intermediate packets.) + * - *5: [@%1d] Position of packet + * - @see rpc_packet_position + */ +int +RpcSendUdp2(struct RpcIdInfo *id, RPC_ID receiver, int direction, + RPC_packet_type type, unsigned int num, rpc_send_buf *sendbuf) { + unsigned char buf[RPC_UDP_PACKET_SIZE]; + UINT32 seq_num = RpcGetSequenceNumber(id->thread_info); + unsigned int bytes = 0; + rpc_send_buf *sendbufp = sendbuf; + int i, do_retry = 1; + for(i = 0 ; i < num ; i++) { + bytes += sendbufp->bytes; + sendbufp++; + } + rpc_assert(bytes <= RPC_UDP_PAYLOAD); // LCOV_EXCL_BR_LINE 6: double check + + struct sockaddr_un to; + memset(&to, 0, sizeof(to)); + to.sun_family = AF_UNIX; +#if defined(RPC_USE_UNIX_AUTOBIND) + if (direction != RPC_SEND_TO_CLIENT) { + RpcSetServerName(to.sun_path, receiver); + if (direction == RPC_SEND_TO_SERVER_NO_RETRY) { + do_retry = 0; + } + } else { + RpcSetClientName(to.sun_path, receiver); + } +#else /* !AUTOBIND */ + rpc_set_socket_name(to.sun_path, rpc_get_port(receiver)); +#endif /* !AUTOBIND */ + + sprintf((char *)buf, RPC_PACKET_HEADER, + (int)type, RPC_my_id(id), seq_num, bytes, + RPC_PACKET_POS_ONEANDONLY); + + unsigned char *bufp = buf + RPC_PACKET_HEADER_LEN; + for(i = 0 ; i < num ; i++) { + memcpy(bufp, sendbuf->buf, sendbuf->bytes); + bufp += sendbuf->bytes; + sendbuf++; + } + if (RpcSendUdpPacket(id, &to, do_retry, + buf, RPC_PACKET_HEADER_LEN + bytes) < 0) { + return -1; + } + return (int)seq_num; +} + +RUNS_IN_READING_THREAD +/** + */ +RPC_Result +RpcSendUdpResponse(RpcIdInfo *id, const RPC_ID receiver, int direction, + RPC_packet_type type, UINT32 seq_num, + char *mesg, UINT32 bytes) { + rpc_assert(bytes <= RPC_MAX_RESPONSE_MESSAGE_SIZE); // LCOV_EXCL_BR_LINE 6: double check + char buf[RPC_PACKET_HEADER_LEN + RPC_MAX_RESPONSE_MESSAGE_SIZE]; + sprintf(buf, RPC_PACKET_HEADER, + (int)type, RPC_my_id(id), seq_num, bytes, + (int)RPC_PACKET_POS_ONEANDONLY); + memcpy(buf + RPC_PACKET_HEADER_LEN, mesg, bytes); + + struct sockaddr_un sa; + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; +#if defined(RPC_USE_UNIX_AUTOBIND) + if (direction != RPC_SEND_TO_CLIENT) { + RpcSetServerName(sa.sun_path, receiver); + } else { + RpcSetClientName(sa.sun_path, receiver); + } +#else /* !AUTOBIND */ + rpc_set_socket_name(sa.sun_path, rpc_get_port(receiver)); +#endif /* !AUTOBIND */ + return RpcSendUdpPacket(id, &sa, 0, buf, RPC_PACKET_HEADER_LEN + bytes); +} + +/** + */ +RPC_Result +RpcParsePacketHeader(const char *str, RPC_packet_type *command, + RPC_ID_p id, UINT32 *seq_num, UINT32 *size) { + // LCOV_EXCL_BR_START 6: double check + rpc_assert(str != NULL && command != NULL && id != NULL + && seq_num != NULL && size != NULL); + // LCOV_EXCL_BR_STOP + + if (sscanf(str, RPC_PACKET_HEADER_scanf, (int *)command, id, seq_num, size) != 4) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + *command = RPC_PACKET_NONE; // LCOV_EXCL_START 5: fail safe for libc sscanf + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + BUG_ASSERT(0, "Parsing packet failed"); + // LCOV_EXCL_STOP + return RPC_ERR_Fatal; + } + return RPC_OK; +} + +#include <sys/time.h> + +RPC_Result +RpcClientWaitResponse(RpcIdInfo *idinfo, UINT32 seq_num, + UINT32 timeout_msec, UINT16 *response) { + unsigned char readbuf[RPC_UDP_PACKET_SIZE]; + fd_set fds; + int fd = idinfo->sock; + + struct timeval timeout; + timeout.tv_sec = (__time_t)(timeout_msec / 1000); + timeout.tv_usec = (__suseconds_t)((timeout_msec % 1000) * 1000); + + *response = RPC_RESPONSE_NONE; + + for(;;) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + int sret = select(fd + 1, &fds, NULL, NULL, &timeout); + if (sret < 0 && errno == EINTR) { /* signal interrupt */ // LCOV_EXCL_START 5: fail safe for libc select + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; + // LCOV_EXCL_STOP + } else if (sret == 0) { /* timeout */ + RPC_LOG_ERR("server response timeout"); + return RPC_ERR_No_Response; + } else if (sret > 0 && FD_ISSET(fd, &fds)) { // LCOV_EXCL_BR_LINE 5: fail safe for libc select + RPC_ID sender; + UINT32 seq; + UINT32 size; + RPC_packet_type command; + int readret = RpcReadUdpPacket(idinfo, readbuf); + if (readret <= 0) { // LCOV_EXCL_START 5: fail safe for libc recvfrom + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + /* debug code to see socket status */ + /* why recvfrom() returned 0 ? */ + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN|POLLHUP|POLLERR; + sret = poll(&pfd, 1, 0/* timeout 0 */); + RPC_LOG_STATE("** poll revents=%x", pfd.revents); + return RPC_ERR_Fatal; + } // LCOV_EXCL_STOP + if (RpcParsePacketHeader((const char *)readbuf, &command, &sender, &seq, &size) != RPC_OK) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + return RPC_ERR_Fatal; + } + unsigned char c; + if (seq == seq_num) { + switch(command) { + case RPC_RESPONSE_APICALL: + c = readbuf[RPC_PACKET_HEADER_LEN]; + switch(c) { + case 'O': + *response = RPC_RESPONSE_API_OK; + goto exit_loop_ok; + break; + case 'B': + *response = RPC_RESPONSE_API_BUSY; + goto exit_loop_ok; + break; + case 'E': + *response = RPC_RESPONSE_API_ERR; + goto exit_loop_ok; + break; + case 'D': + *response = RPC_RESPONSE_API_DEADLOCK; + goto exit_loop_ok; + break; + case 'C': + *response = RPC_RESPONSE_API_CERTIFY; + goto exit_loop_ok; + break; + default: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + BUG_ASSERT(0, "illegal response\n"); // LCOV_EXCL_LINE 15: marco defined in rpc_internal.h + return RPC_ERR_Fatal; + break; + } + break; + + default: + RPC_LOG_STATE("Unknown packet command=%d", command); + return RPC_ERR_Fatal; + break; + } + } else { /* sequence number mismatch == response to other request */ + RPC_LOG_DEBUG("unwanted response received(delayed response?)"); + continue; + } + } else { /* poll error */ + RPC_LOG_PERROR("select in wait response"); + return RPC_ERR_Fatal; + } + } + exit_loop_ok: + return RPC_OK; +} + +RPC_Result +RpcClientWaitResult(RpcIdInfo *idinfo, RPC_ID srvr_id) { + unsigned char readbuf[RPC_UDP_PACKET_SIZE]; + fd_set fds; + int fd = idinfo->sock; + int inotify_fd = RPC_clnt_inotify_fd(idinfo); + int maxfd; + RPC_Result result = RPC_OK; + + for(;;) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + FD_SET(inotify_fd, &fds); + + /* Determine the maximum value of fd to wait */ + if (fd > inotify_fd) { + maxfd = fd; + } else { + maxfd = inotify_fd; + } + + int sret = select(maxfd + 1, &fds, NULL, NULL, NULL); + if (sret < 0 && errno == EINTR) { /* signal interrupt */ // LCOV_EXCL_START 5: fail safe for libc select + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; + // LCOV_EXCL_STOP + } else if (sret > 0 && FD_ISSET(fd, &fds)) { /* success */ // LCOV_EXCL_BR_LINE 5: fail safe for libc select + RPC_ID sender; + UINT32 seq; + UINT32 size; + RPC_packet_type command; + int readret = RpcReadUdpPacket(idinfo, readbuf); + if (readret <= 0) { // LCOV_EXCL_START 5: fail safe for libc recvfrom + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + rpc_assert(readret >= 0); + result = RPC_ERR_Fatal; + goto exit_loop_ok; + } // LCOV_EXCL_STOP + if (RpcParsePacketHeader((const char *)readbuf, &command, &sender, &seq, &size) != RPC_OK) { // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint) + // LCOV_EXCL_START 5: fail safe for libc sscanf + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + result = RPC_ERR_Fatal; + goto exit_loop_ok; + } // LCOV_EXCL_STOP + switch(command) { + case RPC_PACKET_APIRETURN: + result = RpcSetAPIcallReturn(idinfo, + (const char *)(readbuf + RPC_PACKET_HEADER_LEN), + size); + if(result == RPC_OK) { // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc + if (sscanf((const char *)(readbuf + RPC_PACKET_HEADER_LEN), "%08x ", (unsigned int *)&result) != 1) { // LCOV_EXCL_BR_LINE 5: fail safe for libc sscanf + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + BUG_ASSERT(0, "Parsing packet failed"); // LCOV_EXCL_LINE 15: marco defined in rpc_internal.h + return RPC_ERR_Fatal; + } + } + goto exit_loop_ok; + default: + RPC_LOG_STATE("unwanted packet received while waiting for API return"); + continue; + break; + } + } else if (sret > 0 && FD_ISSET(inotify_fd, &fds)) { /* server process is terminate. */ + UINT32 read_len = 0; + int length = 0; + char *buffer; + buffer = (char *)rpc_malloc(BUF_LEN); + if (NULL == buffer) { // LCOV_EXCL_START 5: fail safe for libc malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_ERR("rpc_malloc() ERROR."); + } // LCOV_EXCL_STOP + + if((length = (int)read( inotify_fd, buffer, BUF_LEN )) < 0 ) { // LCOV_EXCL_START 5: fail safe for libc read + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_PERROR("inotify read() ERROR."); + } // LCOV_EXCL_STOP + while (read_len < length) { + struct inotify_event *event = ( struct inotify_event * )&buffer[read_len]; + + if (event->mask & IN_DELETE_SELF) { /* Terminating a Server Process */ + if (RPC_ERR_Server_Finish == RpcDeleteSrvrPid(idinfo, srvr_id, event->wd)) { + RPC_LOG_PERROR("server process is terminate. : srvr_ID = %x", srvr_id); + result = RPC_ERR_Fatal; + } + } + read_len += (UINT32)(EVENT_SIZE + event->len); /* Size of the inotify_event structure */ + } + rpc_free(buffer); + if (RPC_OK != result) { + goto exit_loop_ok; + } + + } else { /* poll error */ // LCOV_EXCL_START 5: fail safe for libc select + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + RPC_LOG_PERROR("select in wait result"); + result = RPC_ERR_Fatal; + goto exit_loop_ok; + // LCOV_EXCL_STOP + } + } +exit_loop_ok: + + return result; +} + +/** @} */ diff --git a/otherservice/rpc_library/tool/Makefile b/otherservice/rpc_library/tool/Makefile new file mode 100755 index 0000000..8ffd816 --- /dev/null +++ b/otherservice/rpc_library/tool/Makefile @@ -0,0 +1,62 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +all: rpc_apidef + +clean: + rm -rf $(CLEAN_FILES) + +YACC := bison +YFLAGS := -d -t +LEX := flex +LFLAGS := -d + +CPPFLAGS := -I../library/include -include $(SDKTARGETSYSROOT)/usr/agl/include/agl_types_obsoluted.h +CFLAGS := -Wall -Wno-unused-function -Wno-unused-variable -include $(SDKTARGETSYSROOT)/usr/agl/include/agl_types_obsoluted.h + +rpc_apidef: apidef.tab.o lex.yy.o apidef.o + $(CXX) $(CPPFLAGS) -o $@ $^ + +apidef.tab.o: apidef.tab.h apidef.tab.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ + +lex.yy.o: lex.yy.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ + +apidef.o: apidef.cc + $(CXX) $(CPPFLAGS) $(CFLAGS) -c $^ + +apidef.tab.h apidef.tab.c: apidef.y + $(YACC) $(YFLAGS) $< + +lex.yy.c: apidef.l apidef.tab.h + $(LEX) $(LFLAGS) $< + +CLEAN_FILES := rpc_apidef *.o apidef.tab.h apidef.tab.c lex.yy.c + +CLEAN_TARGET := clean-all clean-all-sub clean-sub +INSTALL_TARGET := install-header +EMPTY_TARGET := install-prog install-data install-lib install-arlib install-shlib +.PHONY: all install clean $(CLEAN_TARGET) $(INSTALL_TARGET) $(EMPTY_TARGET) + +$(CLEAN_TARGET): clean + +$(INSTALL_TARGET): install + +$(EMPTY_TARGET): + +include ../../other_service.mk + diff --git a/otherservice/rpc_library/tool/apidef.cc b/otherservice/rpc_library/tool/apidef.cc new file mode 100755 index 0000000..ec0a489 --- /dev/null +++ b/otherservice/rpc_library/tool/apidef.cc @@ -0,0 +1,1104 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file apidef.cc + * @brief RPC tools--Main processing(Implementations of APIDef classes) + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> + +#include <other_service/rpc.h> + +#include "apidef.h" +#include "apidef.tab.h" + +static APIDef *API_Def; + +extern "C" { // C interface functions + +void +ApidefDefineId(const char *id) { + if (id != NULL) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->DefineId(id); + } +} + +void +ApidefAddHeader(const char *filename) { + if (filename != NULL) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->AddHeader(filename); + } +} + +int +ApidefPushFunctionArg(int arg_code, int buffer_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, + const char *var_name) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + return API_Def->AddFunctionArg(arg_code, buffer_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, var_name); +} + +void +ApidefProcessFunction(const char *name) { + if (API_Def == NULL) { + API_Def = new APIDef(); + } + API_Def->NameFunction(name); +} + +void +ApidefListFunctions(int with_args) { + if (API_Def != NULL) { + API_Def->Print(with_args); + } +} + +void +ApidefFreeAllocation(void) { + if (API_Def != NULL) { + delete API_Def; + API_Def = NULL; + } +} + +int +ApidefMakeStubs(void) { + if (API_Def != NULL) { + API_Def->MakeStubs(); + return 0; + } else { + return 1; + } +} + +} // extern "C" + +/* + * Retrieving Argument Names Without Decorators + */ +void +Arg::GetUndecolatedName(string& name /* OUT */, int num) { + name = "v"; + if (num > 0) { + /* Making Variable Names Sequential Numbers */ + char num_str[5]; + sprintf(num_str, "%d", num); + name += num_str; + } else { + /* Use a user-supplied pseudo-variable name */ + name = m_name; + } +} + +int +Arg::PrintUndecoratedName(fstream& out, int num) { + /* Pointer argument */ + if (m_is_pointer) { + out << "*"; + } + + if (num > 0) { + /* Making Variable Names Sequential Numbers */ + out << "v" << num; + } else { + /* Use a user-supplied pseudo-variable name */ + out << m_name; + } + + return 0; +} + +/* + * Outputs one argument in a function prototype declaration + * out: Destination file + * num: Handling of Formal Argument Names + * 0 :Formal argument name specified in the API definition file + * Non-zero: Use "v" + specified number(Examples: v1, v2, ...) + */ +int +Arg::PrintPrototype(fstream& out, int num) { + const char *type = TypeCodeString(m_code); + if (type == NULL) { + type = m_type_name.c_str(); + } + if (type == NULL) { + cout << "Internal Error Occurrence!!\n"; + return 1; + } + + /* Const non-output pointers */ + if ((m_in_out & RPC_OUT_ARG) == 0 && (m_bytes != 0 || m_is_pointer != 0)) { + out << "const "; + } + out << type << " "; + if (m_is_pointer && m_bytes == 0) {/* Non-string pointer arguments */ + out << "*"; + } + + if (num > 0) {/* Making variable names sequential numbers */ + out << "v" << num; + } else {/* Use a user-supplied pseudo-variable name */ + out << m_name; + } + + /* Variable-length arrays */ + if (m_is_vararray != 0) { + out << "/* VAR_ARRAY */"; + } + + /* Variable-length arrays length */ + if (m_is_array_size != 0) { + out << "/* VAR_SIZE */"; + } + + /* + * Commenting on OUT/INOUT Arguments + * Maximum number of bytes of a string argument added to a comment + */ + if ((m_in_out & RPC_OUT_ARG) != 0 || m_bytes != 0) { + out << "/* "; + if ((m_in_out & RPC_OUT_ARG) != 0) { + if ((m_in_out & RPC_IN_ARG) != 0) { + out << "IN"; + } + out << "OUT "; + } + if (m_bytes) { + out << m_bytes << "Byte "; + } + out << "*/"; + } + + return 0; +} + +int +Arg::CreateMarshallArgs(fstream& out, int num) { + return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG)); +} + +int +Arg::CreateMarshallArgs(fstream& out, int num, string &array_size_name) { + return CreateMarshallArgs(out, num, (RPC_IN_ARG|RPC_OUT_ARG), array_size_name); +} + +int +Arg::CreateMarshallArgs(fstream& out, int num, int in_out) { + string dummy = ""; + return CreateMarshallArgs(out, num, in_out, dummy); +} + +/* + * The arguments to rpc_marshall_args() are generated for each API argument. + * for each API argument. + * out: Destination file + * num: Number given to the variable name of the argument (Examples: 1 for v1) + * in_out: Specifying the IN or OUT Attributes + * Output only if the argument has the specified attribute + */ +int +Arg::CreateMarshallArgs(fstream& out, int num, int in_out, string &array_size_name) { + if ((m_in_out & in_out) != 0) { + /* + * Collectively passes the argument type, pointer/non-pointer, IN/OUT attribute, + * and the maximum number of bytes of the argument type to one integer. + */ + RPC_marshall_flag flag; + flag.bits.code = m_code & ((1<<RPC_MARSHALL_FLAG_BITS_CODE)-1); + flag.bits.is_vararray = ((array_size_name.size() != 0) ? 1: 0) & + ((1<<RPC_MARSHALL_FLAG_BITS_IS_VARARRAY)-1); + flag.bits.is_pointer = m_is_pointer & ((1<<RPC_MARSHALL_FLAG_BITS_IS_POINTER)-1); + flag.bits.in_out = m_in_out & ((1<<RPC_MARSHALL_FLAG_BITS_IN_OUT)-1); + flag.bits.bytes = (UINT16)(m_bytes); + char str[11]; + sprintf(str, "0x%x", htonl(flag.all)); + out << "\t\t\t" << str; + + /* + * Add size of user-defined type to argument + */ + if (m_code == rpc_USER_DEFINED) { + if (array_size_name.size() != 0) { + out << " + ntohs(sizeof(" << m_type_name << ") * " << array_size_name << ")"; + } else { + out << " + ntohs(sizeof(" << m_type_name << "))"; + } + } else if (array_size_name.size() != 0) { + out << " + ntohs(sizeof(" << TypeCodeString(m_code) << ") * " << array_size_name << ")"; + } + + out << ", v" << num; + return 1; + } else { + return 0; + } +} + +int +Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num) { + return CreateDemarshallArgs(out, deliver_pointer, num, (RPC_IN_ARG|RPC_OUT_ARG)); +} + +int +Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, string &array_size_name) { + return CreateDemarshallArgs(out, deliver_pointer, num, (RPC_IN_ARG|RPC_OUT_ARG), array_size_name); +} + +int +Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out) { + string dummy = ""; + return CreateDemarshallArgs(out, deliver_pointer, num, in_out, dummy); +} + +/* + * The arguments to rpc_demarshall_args() are generated for each API argument. + * for each API argument. + * out: Destination file + * deliver_pointer: Passing a Variable Pointer(non-0) + * num: Number given to the variable name of the argument (Examples: 1 for v1) + * in_out: Specifying the IN or OUT Attributes + * Output only if the argument has the specified attribute + */ +int +Arg::CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out, string &array_size_name) { + if ((m_in_out & in_out) != 0) { + /* + * Collectively passes the argument type, pointer/non-pointer, IN/OUT attribute, + * and the maximum number of bytes of the argument type to one integer. + */ + RPC_marshall_flag flag; + flag.bits.code = m_code & ((1<<RPC_MARSHALL_FLAG_BITS_CODE)-1); + flag.bits.is_vararray = ((array_size_name.size() != 0) ? 1: 0) & + ((1<<RPC_MARSHALL_FLAG_BITS_IS_VARARRAY)-1); + flag.bits.is_pointer = m_is_pointer & ((1<<RPC_MARSHALL_FLAG_BITS_IS_POINTER)-1); + flag.bits.in_out = m_in_out & ((1<<RPC_MARSHALL_FLAG_BITS_IN_OUT)-1); + flag.bits.bytes = (UINT16)(m_bytes); + char str[11]; + sprintf(str, "0x%x", htonl(flag.all)); + out << "\t\t\t" << str; + + /* + * Add size of user-defined type to argument + */ + if (m_code == rpc_USER_DEFINED) { + out << " + ntohs(sizeof(" << m_type_name << "))"; + } + + out << ", "; + if (deliver_pointer) { + /* Pass a pointer */ + out << "&"; + } + out << "v" << num; + return 1; + } else { + return 0; + } +} + +int +Function::AppendArg(int code, int bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, const char *var_name) { + if (NumOfArgs() >= RPC_MAX_API_ARG_NUM) { + cout << "Too many API function arguments.\n"; + return -1; + } + Arg *a = new Arg(code, bytes, is_pointer, is_vararray, is_array_size, + var_type_name, in_out, var_name); + m_args.push_back(*a); + delete a; + return 0; +} + +/* + * Generate prototype declarations for a single API function + * out: Destination file + */ +int +Function::PrintPrototype(fstream& out, int server) { + int ret = 0; + + const char *return_type + = server ? RPC_API_SERVER_RETURN : RPC_API_CLIENT_RETURN; +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + out << return_type << " " << m_name << "("; + } else { + out << return_type << " __" << m_name << "("; + } +#else + out << return_type << " " << m_name << "("; +#endif + + list<Arg>::size_type num_args = m_args.size(); + if (num_args > 0) { + list<Arg>::iterator a; + a = m_args.begin(); + for (list<Arg>::size_type i = 1; i <= num_args; ++i, ++a) { + a->PrintPrototype(out); +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + if (i != num_args) { + out << ", "; + } + } else { + out << ", "; + } +#else + if (i != num_args) { + out << ", "; + } +#endif + } + } else { +#ifdef DBG_ENABLE + if ((server) || (!rpc_log_enable)) { + out << "void"; + } +#else + out << "void"; +#endif + } +#ifdef DBG_ENABLE + /* Debug information */ + if ((!server) && (rpc_log_enable)) { + out << "const char *filename, const char *funcname, int line "; + } +#endif + out << ");\n"; + return ret; +} + +#ifdef DBG_ENABLE +int +Function::PrintMacro(fstream& out) { + int ret = 0; + out << "#define " << m_name << "("; + + int num_args = m_args.size(); + if (num_args > 0) { + int i; + char c; + for (i = 1, c = 'a'; i <= num_args; i++, c++) { + out << c; + if (i != num_args) { + out << ", "; + } + } + out << ") \\\n\t"; + + /* Entity */ + out << "__" << m_name << "("; + for (i = 1, c = 'a'; i <= num_args; i++, c++) { + out << c << ", "; + } + out << "__FILE__, __func__, __LINE__)\n"; + } else { /* Without arguments */ + out << ") " << "__" << m_name << "(__FILE__, __func__, __LINE__)\n"; + } + + return ret; +} +#endif + +int +APIDef::MakeHeaderFiles(int server) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), + (server ? SERVER_HEADER_FILE : CLIENT_HEADER_FILE)); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "ERROR: File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Header file " << filename << " Creating.\n"; + + const char *define_str = + server ? SERVER_HEADER_DEFINE : CLIENT_HEADER_DEFINE; + const char *title = server ? SERVER_HEADER_TITLE : CLIENT_HEADER_TITLE; + + out << "#ifndef _" << m_lowerid << define_str << "\n"; + out << "#define _" << m_lowerid << define_str << "\n"; + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n\n"; + + list<string>::iterator i; + for (i = m_headers.begin(); i != m_headers.end(); ++i) { + out << "#include <" << *i << ">\n"; + } + out << "\n"; + + if (server) { + + out << EXTERN_C_START << "\n"; + + out << RPC_API_DISPATCH_RETURN << " " + << m_id << RPC_API_DISPATCH_FUNC_FULL << ";\n"; + + out << "#ifdef RPC_DISPATCH_FUNC\n" + << "#undef RPC_DISPATCH_FUNC\n" + << "#define RPC_DISPATCH_FUNC " << m_id << RPC_API_DISPATCH_FUNC_NAME + << "\n#else /* !RPC_DISPATCH_FUNC */\n" + << "#error \"Please include <rpc.h> first!!\"\n" + << "#endif /* !RPC_DISPATCH_FUNC */\n\n"; + + out << EXTERN_C_END << "\n"; + + } +#ifdef DBG_ENABLE + else if (rpc_log_enable) { + /* DEBUG INFORMATION EMBEDDED MACRO */ + out << "/* Debug information embedded macro definition */\n"; + list<Function>::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintMacro(out) != 0) { + ret = 1; + break; + } + } + out << "\n"; + } +#endif + + out << EXTERN_C_START << "\n"; + + out << "/* API definitions */\n"; + list<Function>::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintPrototype(out, server) != 0) { + ret = 1; + break; + } + } + out << "\n"; + + out << EXTERN_C_END << "\n"; + + out << "#endif /* _" << m_lowerid << define_str << " */\n"; + out.close(); + return ret; +} + +int +Function::PrintServerStub(fstream& out) { + int num_args = NumOfArgs(); + + out << "\tcase " << RPC_API_NUM_PREFIX << m_name << ": {\n"; + + list<Arg>::iterator a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + const char *type = TypeCodeString(a->Code()); + if (type == NULL) { + type = (a->TypeName()).c_str(); + } + if (type == NULL) { + return 1; + } + out << "\t\t" << type << " "; + if (a->Bytes() > 0 || a->IsPointer()) {/* Pointer-passing argument */ + if (a->Bytes() > 0) { + out << "v" << i << " = NULL;\n"; + } else if (a->IsPointer()) { + out << "*v" << i << " = NULL;\n"; + } + } else {/* Pass-by-value argument */ + out << "v" << i << ";\n"; + } + } + if (num_args > 0) { + out << "\t\tif (" << RPC_DEMARSHALL_FUNCTION + << " (args_string, args_size, 1, " << num_args << ",\n"; + /* In the STUB of servers for all pre-call demarshall */ + /* Passing Pointers to Local Variables in Server STUB */ + /* Pointer/ Buffer will alloc the required space in demarshall_arguments() */ + + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + a->CreateDemarshallArgs(out, 1, i, m_array_size_name); + } else { + a->CreateDemarshallArgs(out, 1, i); + } + if (i < num_args) { + out << ","; + } + out << "\n"; + } + out << "\t\t ) < 0) {\n"; + out << "\t\t\tgoto _" << m_name << "_Error;\n"; + out << "\t\t}\n"; + } + + out << "\t\tresult = " << m_name << "("; + for (int i = 1; i <= num_args; i++) { + out << "v" << i; + if (i < num_args) { + out << ", "; + } + } + out << ");\n"; + + int to_process = NumOfInOutArgs(RPC_OUT_ARG); + if (to_process > 0) { + /* Only OUT-arguments marshall after the server stub is called. */ + out << "\t\t/*if (result == RPC_OK) {*/\n"; + out << "\t\t *ret_string = " << RPC_MARSHALL_FUNCTION + << "(ret_size, 0, " << to_process << ",\n"; + + a = m_args.begin(); + int processed = 0; + int ret; + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG, m_array_size_name); + } else { + ret = a->CreateMarshallArgs(out, i, RPC_OUT_ARG); + } + if (ret) { + processed++; + if (processed < to_process) { + out << ","; + } + out << "\n"; + } + } + out << "\t\t );\n" + << "\t\t if (*ret_string == NULL) {\n" + << "\t\t\tresult = " << RPC_API_SERVER_ERROR << ";\n" + << "\t\t }\n" + << "\t\t/*}*/\n"; + } + + if (num_args > 0) { + out << "_" << m_name << "_Error:\n"; + } + int num_pointer_args = 0; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->Bytes() || a->IsPointer()) { + num_pointer_args++; + } + } + if (num_pointer_args > 0) { + int processed = 0; + out << "\t\t" << RPC_MARSHALL_FREE_FUNCTION + << "(" << num_pointer_args << ", "; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->Bytes() || a->IsPointer()) { + out << "v" << i; + processed++; + if (processed < num_pointer_args) { + out << ", "; + } + } + } + out << ");\n"; + } + out << "\t\tbreak;\n\t}\n"; + return 0; +} + +int +APIDef::MakeServerStub(void) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), SERVER_STUB_FILE); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Stub file " << filename << " Creating.\n"; + + const char *title = SERVER_STUB_TITLE; + + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n"; + out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n"; + out << "#include \"" << m_lowerid << SERVER_HEADER_FILE << "\"\n"; + out << "#include <netinet/in.h> /* for ntohs() */\n\n"; + + int api_num = 1; + list<Function>::iterator f; + + for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) { + if (api_num >= (1<<16)) { + cout << "Too many API functions.(Up to 65535)\n"; + return 1; + } + out << "#define " << RPC_API_NUM_PREFIX << f->Name() + << " " << api_num << "\n"; + } + out << "\n"; + + out << "RPC_Result\n"; + out << m_id << RPC_API_DISPATCH_FUNC_FULL << "\n"; + out << "{\n"; + out << "\tRPC_Result result = " << RPC_API_SERVER_ERROR << ";\n"; + out << "\t*ret_string = NULL;\n"; + out << "\tswitch(api_num) {\n"; + + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintServerStub(out) != 0) { + ret = 1; + break; + } + } + + if (ret != 0) { + return ret; + } + + out << "\tdefault:\n\t\tbreak;\n\t}\n"; + out << "\treturn result;\n"; + out << "}\n"; + + return ret; +} + +int +Function::PrintClientStub(const char *moduleid, fstream& out) { + int ret = 0; + + list<Arg>::iterator a; + /* Function Names and Arguments */ + out << RPC_API_CLIENT_RETURN << "\n"; +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "__" << m_name << "("; + } else { + out << m_name << "("; + } +#else + out << m_name << "("; +#endif + int num_args = (int)(m_args.size()); + if (num_args > 0) { + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->PrintPrototype(out, i)) { + return 1; + } +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << ", "; + } else { + if (i < num_args) { + out << ", "; + } + } +#else + if (i < num_args) { + out << ", "; + } +#endif + } + } else { +#ifndef DBG_ENABLE + out << "void"; +#else + if (!rpc_log_enable) { + out << "void"; + } +#endif + } +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "const char *filename, const char *funcname, int line "; + } +#endif + out << ")\n"; + + out << "{\n"; + + /* Contents of stub functions */ + + /* If the argument is present and the variable-length array does not exist */ + if ((num_args > 0) && (m_array_size_pos == 0)) { + int is_exist_mytype = 0; + /* Restricted specifications */ + out << "#ifdef RPC_STATIC_ASSERT\n"; + out << "\tchar RPC_TOTAL_ARGSIZE_ERROR_in_" << m_name << "[\n"; + out << "\t((("; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (i > 1) { + out << " + "; + } + out << "sizeof("; + a->PrintUndecoratedName(out, i); + out << ")"; + /* For user types */ + if ((!is_exist_mytype) && (NULL == TypeCodeString(a->Code()))) { + is_exist_mytype = 1; + } + } + out << ") > RPC_MAX_API_ARG_TOTAL_SIZE) ? -1: 1)\n"; + out << "\t]__attribute__((unused));\n"; + + /* Have a user type */ + if (is_exist_mytype) { + char c[3]; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (NULL == TypeCodeString(a->Code())) { + sprintf(c, "%d", i); + out << "\tchar RPC_ARGSIZE_ERROR_in_" << m_name << "_arg" << c; + out << "[\n\t(sizeof("; + a->PrintUndecoratedName(out, i); + out << ") > RPC_MAX_API_ARG_SIZE) ? -1: 1\n"; + out << "\t]__attribute__((unused));\n"; + } + } + } + + out << "#endif /* RPC_STATIC_ASSERT */\n"; + + } + + out << "\tRPC_Result result = " << RPC_API_CLIENT_ERROR << ";\n"; + out << "\tunsigned int args_size = 0, ret_size;\n"; + out << "\tchar retcode[9];\n"; + + if (num_args > 0) { + /* Advance preparation==Marshalling of arguments */ + out << "\tchar *args_string = " << RPC_MARSHALL_FUNCTION + << "(&args_size, 1, " << num_args << ",\n"; + /* In the clients STUB for all pre-call marshall */ + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + a->CreateMarshallArgs(out, i, m_array_size_name); + } else { + a->CreateMarshallArgs(out, i); + } + if (i < num_args) { + out << ","; + } + out << "\n"; + } + out << "\t);\n"; + out << "\tif (args_string == NULL) {\n" + << "\t\tgoto _" << m_name << "_Error;\n\t}\n"; + } else { + out << "\tchar *args_string = NULL;\n"; + } + +#ifdef DBG_ENABLE + if (rpc_log_enable) { + out << "\tif (" << moduleid << "_record_dbg_log(filename, funcname, line, \""; + out << m_name << "\") != 0) {\n"; + out << "\t\tgoto _" << m_name << "_Error;\n\t}\n"; + } +#endif + + /* RPC API call */ + out << "\tchar *ret_string = NULL; /* pgr0431 */\n"; +#ifdef RPC_STRING_ID + out << "\tresult=RPC_API_call(\"" << moduleid << "\", "; +#else + out << "\tresult=RPC_API_call(" << moduleid << "_RPC_ID, "; +#endif + out << RPC_API_NUM_PREFIX << m_name; + out << ", args_string, args_size, &ret_string, &ret_size);\n"; + + // 2007.08.25 To avoid over run within the sscanf + // Locally copies strings needed for determining return values and uses strtol instead of sscanf + // (Since there is no guarantee that the byte sequence to be grabbed by communication is 0-terminated) + out << "\n" + << "\tif (result == RPC_OK && ret_string != NULL) {\n" + << "\t strncpy(retcode, ret_string, 8);\n" + << "\t retcode[8] = '\\0';\n" + << "\t result = (RPC_Result)strtoul(retcode, NULL, 16);\n"; + + /* Post-processing==Arguments de-marshalling, free() */ + int num_of_out_args = NumOfInOutArgs(RPC_OUT_ARG); + if (num_of_out_args > 0) { + out << "\t if (" << RPC_DEMARSHALL_FUNCTION + << "(ret_string + RPC_RETCODE_LEN, ret_size - RPC_RETCODE_LEN, 0, " + << num_of_out_args << ",\n"; + + a = m_args.begin(); + int processed = 0; + int ret; + for (int i = 1; i <= num_args; ++i, ++a) { + if (a->IsVararray() != 0) { /* Variable-length arrays */ + ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG, m_array_size_name); + } else { + ret = a->CreateDemarshallArgs(out, 0, i, RPC_OUT_ARG); + } + if (ret) { + processed++; + if (processed < num_of_out_args) { + out << ","; + } + out << "\n"; + } + } + out << "\t ) < 0) {\n" + << "\t\tresult = " << RPC_API_CLIENT_ERROR << ";\n" + << "\t }\n"; + } + + out << "\t} else {\n\t //result = " << RPC_API_CLIENT_ERROR << ";\n" + << "\t}\n"; + + out << "\t" << RPC_RETURN_FREE_FUNCTION << "(ret_string);\n"; + out << "\t" << RPC_MARSHALL_FREE_FUNCTION << "(1, args_string);\n"; + + /* END, RETURN */ +#ifndef DBG_ENABLE + if (num_args) +#else + if ((num_args)||(rpc_log_enable)) +#endif + { + out << "_" << m_name << "_Error:\n"; + } + + out << "\treturn result;\n}\n"; + + return ret; +} + +int +APIDef::MakeClientStub(void) { + char filename[MAX_FILENAME_LEN+1]; + sprintf(filename, "%s%s", m_lowerid.c_str(), CLIENT_STUB_FILE); + int ret = 0; + + fstream out(filename, ios::out); + if (!out.is_open()) { + cout << "File " << filename << " Could not open.\n"; + return 1; + } + cout << "info: Stub file " << filename << " Creating.\n"; + + const char *title = CLIENT_STUB_TITLE; + + out << "/*\n"; + out << " * " << m_id << " " << title << " " << filename << "\n"; + out << " *\n"; + out << RPCTOOL_WARNING_STRING << "\n"; + out << " */\n"; + out << "#include <" RPC_GLOBAL_HEADER_FILE << ">\n"; + out << "#include <" << m_lowerid << CLIENT_HEADER_FILE << ">\n\n"; + out << "#include <stdio.h> /* for sscanf() */\n"; + out << "#include <stdlib.h> /* for getenv() */\n"; + out << "#include <string.h> /* for strncpy() */\n"; + out << "#include <netinet/in.h> /* for ntohs() */\n\n"; + + int api_num = 1; + list<Function>::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f, ++api_num) { + if (api_num >= (1<<16)) { + cout << "Too many API functions.(Up to 65535)\n"; + return 1; + } + out << "#define " << RPC_API_NUM_PREFIX << f->Name() + << " " << api_num << "\n"; + } + out << "\n"; + + /* Specification Restriction Debug Constants */ + out << "/*#define RPC_STATIC_ASSERT*/\n"; + out << "\n"; + +#ifdef DBG_ENABLE + if (rpc_log_enable) { + int m_id_work_cnt; + string m_id_work = m_id; + for (m_id_work_cnt = 0; m_id_work_cnt < m_id_work.length(); m_id_work_cnt++) { + m_id_work[m_id_work_cnt] = toupper(m_id_work[m_id_work_cnt]); + } + out << "int\n" << m_id << "_record_dbg_log(const char *filename, " << + "const char *funcname, int line, const char *apiname)\n"; + out << "{\n\t"; + out << "if (getenv(\"" << m_id_work << "_RPC_LOG\") != NULL) {\n\t\t"; + out << "return RPC_record_dbg_log(filename, funcname, line, apiname);\n\t"; + out << "}\n\t"; + out << "return 0;\n"; + out << "}\n\n"; + } +#endif + + /* API definitions */ + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->PrintClientStub(m_id.c_str(), out) != 0) { + ret = 1; + break; + } + } + return ret; +} + +int +Arg::IsArraySize(void) { + if (m_is_array_size != 0) { + if (IsTypeCodeNumeric(m_code) == 1) { + return 1; + } else { + cout << "Variable-length array length specification variables must be integers.\n"; + return -1; + } + } + return 0; +} + +int +Function::CheckFuncArraySize(void) { + int num_args = (int)(m_args.size()); + list<Arg>::iterator a; + a = m_args.begin(); + for (int i = 1; i <= num_args; ++i, ++a) { + int ret = a->IsArraySize(); + if (ret > 0) { + if (m_array_size_pos != 0) + { + cout << "Two or more variable array length specification arguments exist.\n"; + return 1; + } + m_array_size_pos = i; + a->GetUndecolatedName(m_array_size_name, i); + } else if (ret < 0) { + return 1; + } + } + return 0; +} + +int +APIDef::CheckAllArraySize(void) { + list<Function>::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + if (f->CheckFuncArraySize() != 0) { + return 1; + } + } + return 0; +} + +int +APIDef::MakeStubs(void) { + if (m_id.size() == 0) { + cout << "The module name is not specified.\n"; + return 1; + } + + if (m_id.size() > MAX_FILENAME_LEN - strlen(SERVER_STUB_FILE)) { + cout << "The module name is too long.\n"; + return 1; + } + + /* Pre-examine the ARRAYSIZE specification */ + //cout << "<check_all_array_size>\n"; + if (CheckAllArraySize() != 0) { + return 1; + } + + //cout << "<MakeHeaderFiles(0)>\n"; + if (MakeHeaderFiles(1) != 0) { + return 1; + } + + //cout << "<MakeHeaderFiles(1)>\n"; + if (MakeHeaderFiles(0) != 0) { + return 1; + } + + if (MakeServerStub() != 0) { + return 1; + } + + if (MakeClientStub() != 0) { + return 1; + } + + return 0; +} + +void +Arg::Print(void) { + cout << "\t"; + if (m_name.size() > 0) { + cout << "Variable name=" << m_name << " "; + } + cout << "Type=" << TypeCodeString(m_code) << "In bytes=" << m_bytes << " "; + if (m_is_pointer) { + cout << "Pointer "; + } + if ((m_in_out & RPC_OUT_ARG) != 0) { + cout << "Output "; + } + cout << "\n"; +} + +void +Function::Print(int with_args) { + printf("Function name=%s\n", m_name.c_str()); + if (with_args) { + list<Arg>::iterator a; + for (a = m_args.begin(); a != m_args.end(); ++a) { + a->Print(); + } + } +} + +void +APIDef::Print(int with_args) { + list<Function>::iterator f; + for (f = m_funcs.begin(); f != m_funcs.end(); ++f) { + f->Print(with_args); + } +} + +void +APIDef::IdTolower(void) { + char *lower = new char[m_id.size() + 1]; + strcpy(lower, m_id.c_str()); + char *p; + for (p = lower; *p; p++) { + *p = (char)(tolower(*p)); + } + m_lowerid = lower; + delete[] lower; +} diff --git a/otherservice/rpc_library/tool/apidef.h b/otherservice/rpc_library/tool/apidef.h new file mode 100755 index 0000000..b042a90 --- /dev/null +++ b/otherservice/rpc_library/tool/apidef.h @@ -0,0 +1,333 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file apidef.h + * @brief RPC tools--Function/macro definitions and APIDef class definitions + */ +/** @addtogroup RPCtool + * + * @brief Using the RPC Tool (rpc_apidef) + * + * rpc_apidef [CPP option...] API definition file name + * + * - CPP option + * The RPC tool calls the C preprocessor (CPP) internally + * for processing comments and #if directives. + * Here, you can specify options to be given to the CPP, such as symbol definitions + * for conditional branch descriptions in the API definition file. + * - API definition file name + * Pathname to the API definition file. + * The file name must be thread ID + ".api". + * + * The output file is as follows. + * "*" is a lowercase version of the API definition file name preceding ".api". + * - *_api.h(Client header files) + * - *_api_stub.c(Client stub file) + * - *_srvr.h(Server header file) + * - *_srvr_stub.c(Server stub file) + * + * Examples: + * - Examples1: rpc_apidef -DTEST XXX.api + * - Examples2: rpc_apidef XXX.api + * - => Xxx_api.h, xxx_api_stub.c, ... To the output + */ +#ifndef RPC_LIBRARY_TOOL_APIDEF_H_ +#define RPC_LIBRARY_TOOL_APIDEF_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef DBG_ENABLE +extern char rpc_log_enable; +#endif + +/* C++ to C I/F functions */ +const char *TypeCodeString(const int code); +int IsTypeCodeNumeric(const int code); + +/* + * C to C++ I/F functions (APIDef class) + */ +void ApidefDefineId(const char *id); +void ApidefAddHeader(const char *filename); +int ApidefPushFunctionArg(int arg_code, int buffer_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, + const char *var_name); +void ApidefProcessFunction(const char *funcname); +void ApidefListFunctions(int with_args); +void ApidefFreeAllocation(void); +int ApidefMakeStubs(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define RPC_IN_ARG 0x01 +#define RPC_OUT_ARG 0x02 +#define RPC_INOUT_ARG (RPC_IN_ARG|RPC_OUT_ARG) + +#define MAX_FILENAME_LEN 63 +#define SERVER_HEADER_FILE "_srvr.h" +#define CLIENT_HEADER_FILE "_api.h" +#define SERVER_STUB_FILE "_srvr_stub.c" +#define CLIENT_STUB_FILE "_api_stub.c" +#define SERVER_HEADER_DEFINE "_srvr_h_" +#define CLIENT_HEADER_DEFINE "_api_h_" + +#define SERVER_HEADER_TITLE "Server header files" +#define CLIENT_HEADER_TITLE "Client header files" +#define SERVER_STUB_TITLE "Server stub file" +#define CLIENT_STUB_TITLE "Client stub file" + +#define RPC_MARSHALL_FUNCTION "RPC_marshall_arguments" +#define RPC_DEMARSHALL_FUNCTION "RPC_demarshall_arguments" +#define RPC_MARSHALL_FREE_FUNCTION "RPC_marshall_free" +#define RPC_RETURN_FREE_FUNCTION "RPC_free_return_string" + +#define RPC_API_SERVER_RETURN "RPC_Result" +#define RPC_API_SERVER_ERROR "RPC_ERR_Fatal" +#define RPC_API_CLIENT_RETURN "RPC_Result" +#define RPC_API_CLIENT_ERROR "RPC_ERR_Fatal" +#define RPC_API_DISPATCH_TYPE "RPC_dispatch_func_t" +#define RPC_API_DISPATCH_RETURN "RPC_Result" +#define RPC_API_DISPATCH_FUNC_FULL "_API_dispatch(UINT16 api_num, const char *args_string, unsigned int args_size, char **ret_string, unsigned int *ret_size)" // NOLINT (readability/nolint) +#define RPC_API_DISPATCH_FUNC_NAME "_API_dispatch" +#define RPC_API_NUM_PREFIX "RPC_API_NUM_" +#define RPC_GLOBAL_HEADER_FILE "other_service/rpc.h" + +#define RPCTOOL_WARNING_STRING \ +" * The file created by the RPC tool.This file should not be edited." + +#define EXTERN_C_START \ +"#ifdef __cplusplus\n" \ +"extern \"C\" {\n" \ +"#endif\n" + +#define EXTERN_C_END \ +"#ifdef __cplusplus\n" \ +"}\n" \ +"#endif /* __cplusplus */\n" + +#ifdef __cplusplus +#include <iostream> +#include <fstream> +#include <string> +#include <list> + +using namespace std; // NOLINT (readability/nolint) + +/** @ingroup RPCtool + * @class Arg + * @brief Class that stores and processes the arguments of functions read from the API definition file + */ +class Arg { + protected: + int m_code; + int m_bytes; + int m_is_pointer; + int m_in_out; /* Bit OR of _IN_ARG and _OUT_ARG */ + int m_is_vararray; + int m_is_array_size; + string m_type_name; + string m_name; + + public: + Arg() { + m_code = m_bytes = m_is_pointer = m_in_out = m_is_vararray = m_is_array_size = 0; + } + Arg(int code, int bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *type_name, int in_out, + const char *var_name) { + m_code = code; + m_bytes = bytes; + m_is_pointer = is_pointer; + m_is_vararray = is_vararray; + m_is_array_size = is_array_size; + m_in_out = in_out; + if (type_name) { + m_type_name = type_name; + } + if (var_name) { + m_name = var_name; + } + } + ~Arg() {} + + int Code(void) { return m_code; } + int Bytes(void) { return m_bytes; } + int IsPointer(void) { return m_is_pointer; } + int InOut(void) { return m_in_out; } + string& TypeName(void) { return m_type_name; } + void GetUndecolatedName(string& name, int num); // NOLINT (readability/nolint) + + int PrintUndecoratedName(fstream& out, int num); + int PrintPrototype(fstream& out, int num); + int PrintPrototype(fstream& out) { return PrintPrototype(out, 0); } + + int CreateMarshallArgs(fstream& out, int num); + int CreateMarshallArgs(fstream& out, int num, string &array_size_name); // NOLINT (readability/nolint) + int CreateMarshallArgs(fstream& out, int num, int in_out); + int CreateMarshallArgs(fstream& out, int num, int in_out, string &array_size_name); // NOLINT (readability/nolint) + int CreateDemarshallArgs(fstream& out, int deliver_pointer, int num); + int CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, string &array_size_name); // NOLINT (readability/nolint) + int CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out); + int CreateDemarshallArgs(fstream& out, int deliver_pointer, int num, int in_out, string &array_size_name); // NOLINT (readability/nolint) + + int IsVararray(void) { return m_is_vararray; } + int IsArraySize(void); + void Print(void); +}; + +/** @ingroup RPCtool + * @class Function + * @brief Class that stores and processes function definitions read from the API definition file + */ +class Function { + protected: + string m_name; + list<Arg> m_args; + int m_array_size_pos; + string m_array_size_name; + + public: + Function():m_array_size_name("") { m_array_size_pos = 0; } + ~Function() { + list<Arg>::size_type size = m_args.size(); + for (list<Arg>::size_type i = 0 ; i < size ; i++) { + m_args.begin(); + m_args.pop_front(); + } + } + + const char *Name(void) { return m_name.c_str(); } + void SetName(const char *funcname) { + m_name = funcname; + } + + int NumOfArgs(void) { + return (int)(m_args.size()); // NOLINT (readability/nolint) + } + int NumOfInOutArgs(int in_out) { + int count = 0; + list<Arg>::iterator a; + for (a = m_args.begin(); a != m_args.end(); ++a) { + if ((a->InOut() & in_out) != 0) { + ++count; + } + } + return count; + } + + int AppendArg(int code, int bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, const char *var_name); + + int PrintPrototype(fstream& out); + int PrintPrototype(fstream& out, int server); +#ifdef DBG_ENABLE + int PrintMacro(fstream& out); +#endif + + int PrintServerStub(fstream& out); + int PrintClientStub(const char *moduleid, fstream& out); + + int CheckFuncArraySize(void); + void Print(int with_args); +}; + +/** @ingroup RPCtool + * @class APIDef + * @brief Class that stores and processes the result of reading the API definition file + */ +class APIDef { + protected: + list<Function> m_funcs; + Function *m_work; + string m_id; + string m_lowerid; + list<string> m_headers; + + public: + APIDef() { m_work = 0; } + ~APIDef() { + list<Function>::size_type size = m_funcs.size(); + for (list<Function>::size_type i = 0; i < size; i++) { + m_funcs.begin(); + m_funcs.pop_front(); + } + if (m_work != NULL) { + delete m_work; + } + size = m_headers.size(); + for (list<Function>::size_type i = 0; i < size; i++) { + m_headers.begin(); + m_headers.pop_front(); + } + } + + void IdTolower(void); + void DefineId(const char *id) { + m_id = id; + IdTolower(); + } + void AddHeader(const char *filename) { + string str = filename; + m_headers.push_back(str); + } + + int AddFunctionArg(int arg_code, int buffer_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, + const char *var_name) { + if (m_work == NULL) { + m_work = new Function(); + } + return m_work->AppendArg(arg_code, buffer_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, var_name); + } + void NameFunction(const char *funcname) { + if (m_work == NULL) { + m_work = new Function(); + } + m_work->SetName(funcname); + + AppendFunction(m_work); + delete m_work; + m_work = NULL; + } + + void AppendFunction(Function *pfunc) { + m_funcs.push_back(*pfunc); + } + + int CheckAllArraySize(void); + + int MakeStubs(void); + void Print(int with_args); + + private: + int MakeHeaderFiles(int server); + int MakeServerStub(void); + int MakeClientStub(void); +}; +#endif /* __cplusplus */ + +#endif // RPC_LIBRARY_TOOL_APIDEF_H_ diff --git a/otherservice/rpc_library/tool/apidef.l b/otherservice/rpc_library/tool/apidef.l new file mode 100755 index 0000000..c2f246a --- /dev/null +++ b/otherservice/rpc_library/tool/apidef.l @@ -0,0 +1,136 @@ +/** + * @file apidef.l + * @brief RPC tools--Defining lexical analysis rules for API definition files + * + */ +/** @ingroup RPCtool + * Defining Lexical Analysis Rules for Use with RPC Tools (apidef) + */ +%{ +#include <string.h> +#include <stdlib.h> +#include "apidef.tab.h" +%} + +ALPHA [A-Za-z_] +ALPHANUM [0-9\-A-Za-z_] +ALPHANUMDOT [0-9.\-A-Za-z_/] + +%x include +%s apidef +%x str_num + +%% +INCLUDE { BEGIN(include); return rpc_INCLUDE; } +<include>\< { return '<'; } +<include>{ALPHANUMDOT}+ { + yylval.strval = malloc(strlen(yytext)+1); + strcpy(yylval.strval, yytext); + return rpc_NAME_DOT; + } +<include>\> { BEGIN(INITIAL); return '>'; } +<include>. /* ignore */ + +RPC_Result { BEGIN(apidef); return RPC_RESULT; } + +<apidef>STRING/[0-9]+ { BEGIN(str_num); + yylval.ival = rpc_STRING; return rpc_STRING; } +<str_num>[0-9]+ { + BEGIN(apidef); + sscanf(yytext, "%d", &yylval.ival); + return rpc_NUM; + } +<str_num>. /* ignore */ + +<apidef>{ +char { yylval.ival = rpc_CHAR; return rpc_CHAR; } +int { yylval.ival = rpc_INT; return rpc_INT; } +signed[ \t\n]+int { yylval.ival = rpc_SINT; return rpc_SINT; } +unsigned[ \t\n]+int { yylval.ival = rpc_UINT; return rpc_UINT; } +INT8 { yylval.ival = rpc_INT8; return rpc_INT8; } +INT16 { yylval.ival = rpc_INT16; return rpc_INT16; } +INT32 { yylval.ival = rpc_INT32; return rpc_INT32; } +INT64 { yylval.ival = rpc_INT64; return rpc_INT64; } +UINT8 { yylval.ival = rpc_UINT8; return rpc_UINT8; } +UINT16 { yylval.ival = rpc_UINT16; return rpc_UINT16; } +UINT32 { yylval.ival = rpc_UINT32; return rpc_UINT32; } +UINT64 { yylval.ival = rpc_UINT64; return rpc_UINT64; } +float { yylval.ival = rpc_FLOAT; return rpc_FLOAT; } +double { yylval.ival = rpc_DOUBLE; return rpc_DOUBLE; } +void { yylval.ival = rpc_VOID; return rpc_VOID; } +IN { + fprintf(stderr, + "Specification change: IN Pointer argument needs to be prefixed \"const\" instead of \"IN\".\n" + ); + return rpc_UNKNOWN; + } +OUT { + fprintf(stderr, + "Specification change: OUT argument no longer needs to be prefixed with \"OUT\".\n" + ); + /* ignore */ + } +INOUT { yylval.ival = rpc_INOUT; return rpc_INOUT; } +const { yylval.ival = rpc_CONST; return rpc_CONST; } +VARARRAY { yylval.ival = rpc_VARARRAY; return rpc_VARARRAY; } +ARRAYSIZE { yylval.ival = rpc_ARRAYSIZE; return rpc_ARRAYSIZE; } + +{ALPHA}+{ALPHANUM}* { + yylval.strval = malloc(strlen(yytext)+1); + strcpy(yylval.strval, yytext); + return rpc_NAME; + } + +\( { return '('; } +\) { return ')'; } +\* { return '*'; } +, { return ','; } +\; { BEGIN(INITIAL); return ';'; } + +} /* end of <apidef> */ + +#.*\n /* ignore CPP directives */ + +{ALPHANUMDOT}+ { + fprintf(stderr, "Unknown keyword %s\n", yytext); + return rpc_UNKNOWN; + } + +[ \t\n]+ /* eat up whitespace */ + +%% +#ifdef OLD_STUFFS +%x portdef +%x addr_num +PORT { BEGIN(portdef); return DEFINE_PORT; } +<portdef>[0-9]+ { + BEGIN(INITIAL); + sscanf(yytext, "%d", &yylval.ival); + return NUM; + } + +<apidef>ADDR/[0-9]+ { BEGIN(addr_num); yylval.ival = _ADDR; return _ADDR; } +<addr_num>[0-9]+ { + BEGIN(apidef); + sscanf(yytext, "%d", &yylval.ival); + return NUM; + } +#endif + +/* + * function to free the buffer which flex allocates but not frees + */ +void +free_flex_buffer(void) +{ + yy_delete_buffer(YY_CURRENT_BUFFER); +} + +/* + * dummy function to avoid a warning of not using 'yyunput' + */ +void +dummy(void) +{ + yyunput(0, 0); +} diff --git a/otherservice/rpc_library/tool/apidef.y b/otherservice/rpc_library/tool/apidef.y new file mode 100755 index 0000000..ce20c9c --- /dev/null +++ b/otherservice/rpc_library/tool/apidef.y @@ -0,0 +1,615 @@ +/** + * @file apidef.y + * @brief RPC tools--API definition file syntax definition and read/front-end processing + * + */ + +/*---------------------------------------------------------------------------*/ +/* C declarative statement */ +/*---------------------------------------------------------------------------*/ +%{ +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +#include <stdio.h> +#include <stdlib.h> + +/* + * YACC to C I/F functions + */ +extern int yylex(void); /* LEX I/F */ +extern int yyerror(const char *); /* dummy */ + +#include "apidef.h" + +/* YACC to C I/F functions */ +static void AddHeader(const char *header_file); +static int push_function_arg(int arg_type, int num_of_bytes, + int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, + int is_out, const char *var_name); +static void process_function(const char *funcname); +static void free_string(char *funcname); + +static int var_type; +static int num_of_bytes; +static int is_pointer; +static int in_out; +static int is_vararray; +static int is_array_size; +static char *var_type_name = NULL; + +%} + +/*---------------------------------------------------------------------------*/ +/* Bison declarations */ +/*---------------------------------------------------------------------------*/ +%union { + int ival; + char *strval; +} + +%token '"' +%left ',' +%left '(' +%right ')' +%left '*' +%token '{' +%token '}' +%token ';' +%token '\n' +%token <strval> rpc_INCLUDE 257 +%token <strval> RPC_RESULT 258 +%token <strval> rpc_NAME_DOT 259 +%token <strval> rpc_NAME 260 +%type <strval> funcdefs funcdef args +%type <strval> nonvoid_args arg var_type +%type <strval> var_primitive_type var_string_type var_user_defined_type +/* +%token <strval> rpc_OUT +*/ +%token <strval> rpc_INOUT 261 +%token <strval> rpc_CONST 262 +%token <strval> rpc_VARARRAY 263 +%token <strval> rpc_ARRAYSIZE 264 +%token <ival> rpc_NUM 265 +%token <strval> rpc_VOID 266 +%token <ival> rpc_CHAR 267 +%token <ival> rpc_INT 268 +%token <ival> rpc_SINT 269 +%token <ival> rpc_UINT 270 +%token <ival> rpc_INT8 271 +%token <ival> rpc_INT16 272 +%token <ival> rpc_INT32 273 +%token <ival> rpc_INT64 274 +%token <ival> rpc_UINT8 275 +%token <ival> rpc_UINT16 276 +%token <ival> rpc_UINT32 277 +%token <ival> rpc_UINT64 278 +%token <ival> rpc_FLOAT 279 +%token <ival> rpc_DOUBLE 280 +%token <ival> rpc_STRING 281 +%token <ival> rpc_USER_DEFINED 282 +%token <ival> rpc_UNKNOWN 283 + +/*---------------------------------------------------------------------------*/ +/* Grammar rule */ +/*---------------------------------------------------------------------------*/ +%% +input: includes funcdefs +; + +includes: /* empty input */ + | includes include +; + +include: rpc_INCLUDE '<' rpc_NAME_DOT '>' + { AddHeader($3); free_string($3); } +; + +funcdefs: funcdef + | funcdefs funcdef +; + +funcdef: RPC_RESULT rpc_NAME '(' args ')' ';' + { process_function($2); free_string($2);} +; + +args: rpc_VOID + | nonvoid_args +; + +nonvoid_args: arg + | nonvoid_args ',' arg +; + +arg: var_type rpc_NAME + { + if (push_function_arg(var_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, $2) < 0) { + YYERROR; + } + if (var_type_name) { free_string(var_type_name); } + var_type_name = NULL; + free_string($2); + } + | var_type + { + if (push_function_arg(var_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, NULL) < 0) { + YYERROR; + } + if (var_type_name) { free_string(var_type_name); } + var_type_name = NULL; + } +; + +/* + * Standard IN pointers are not allowed. + * When used as an array address, it is not clear how many bytes to copy. + * ->You are asked to declare the type and pass the address. + * Otherwise, you can simply pass it by value. + */ +var_type: var_primitive_type /* INT8, .. DOUBLE */ + { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out =RPC_IN_ARG; } + | var_primitive_type '*' /* OUT INT8 *, ... OUT DOUBLE * */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + /* if allow primitive IN pointer + | rpc_CONST var_primitive_type '*' + { is_pointer = 1; in_out = RPC_IN_ARG; } + */ + | var_string_type + /* OUT STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_CONST var_string_type + /* IN STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + | var_user_defined_type + { is_pointer = 0; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + | var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_CONST var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_IN_ARG; } + + /* INOUT specification */ + | rpc_INOUT var_string_type + /* IN STRING128, ... */ + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; } + | rpc_INOUT var_user_defined_type '*' + { is_pointer = 1; is_vararray = 0; is_array_size = 0; in_out = RPC_INOUT_ARG; } + + /* Variable-length arrays */ + | rpc_CONST rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; } + | rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_INOUT rpc_VARARRAY var_primitive_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; } + | rpc_CONST rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_IN_ARG; } + | rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_OUT_ARG; } + | rpc_INOUT rpc_VARARRAY var_user_defined_type '*' + { is_pointer = 1; is_vararray = 1; is_array_size = 0; in_out = RPC_INOUT_ARG; } + + /* Variable length array size */ + | rpc_ARRAYSIZE var_primitive_type + { is_pointer = 0; is_vararray = 0; is_array_size = 1; in_out = RPC_IN_ARG; } +; + +var_primitive_type: + rpc_CHAR { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_SINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT8 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT16 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT32 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_INT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_UINT64 { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_FLOAT { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } + | rpc_DOUBLE { var_type = $1; num_of_bytes = 0; var_type_name = NULL; } +; + +var_string_type: rpc_STRING rpc_NUM + { var_type = $1; num_of_bytes = $2; var_type_name = NULL; } +; + +var_user_defined_type: rpc_NAME + { var_type = rpc_USER_DEFINED; num_of_bytes = 0; var_type_name = $1; } +; + +%% + +/*---------------------------------------------------------------------------*/ +/* C additional code */ +/*---------------------------------------------------------------------------*/ +/* Including an older bison results in an error */ +/*#include "apidef.tab.h"*/ + +#include <unistd.h> +#include <assert.h> +#include <string.h> +/* + * YACC/Lex interface functions/variables + */ +extern int yydebug; /* for YACC debug */ +extern int yyparse(void); +extern FILE *yyin; +extern int yy_flex_debug; /* for FLEX debug */ +/* my own function to free the buffer flex allocates */ +extern void free_flex_buffer(void); + +#ifdef DBG_ENABLE +char rpc_log_enable; +#endif + +/**/ +static void +AddHeader(const char *filename) +{ + ApidefAddHeader(filename); +} + +static int +push_function_arg(int arg_type, int num_of_bytes, int is_pointer, + int is_vararray, int is_array_size, + const char *var_type_name, int in_out, const char *var_name) +{ + switch(arg_type) { + case rpc_CHAR: + case rpc_INT: + case rpc_SINT: + case rpc_UINT: + case rpc_INT8: + case rpc_INT16: + case rpc_INT32: + case rpc_INT64: + case rpc_UINT8: + case rpc_UINT16: + case rpc_UINT32: + case rpc_UINT64: + case rpc_FLOAT: + case rpc_DOUBLE: + case rpc_STRING: + case rpc_USER_DEFINED: + return ApidefPushFunctionArg(arg_type, num_of_bytes, is_pointer, + is_vararray, is_array_size, + var_type_name, in_out, var_name); + break; + + default: + return -1; + break; + } +} + +static void +process_function(const char *funcname) +{ + ApidefProcessFunction(funcname); +} + +static void +free_string(char *s) +{ +#ifdef DEBUG + fprintf(stderr, "freed %s\n", s); +#endif + free(s); +} + +static void +extract_id(const char *filename, char **id) +{ + char *dotapi; + char *slash; + const char *start; + + if (id == NULL) { + return; + } + dotapi = strrchr(filename, '.'); + if (dotapi == NULL) { + return; + } + if (strcmp(dotapi, ".api")) { + return; + } + + slash = strrchr(filename, '/'); + start = filename; + if (slash != NULL) { + start = slash + 1; + } + + *id = malloc((size_t)(dotapi - start + 1)); + if (*id == NULL) { + return; + } + strncpy(*id, start, (size_t)(dotapi - start)); + (*id)[dotapi - start] = '\0'; +} + +static void +usage(const char *prog) +{ + fprintf(stdout, + "How to use: %s [CPPFLAGS] ... API definition file name\n", + prog); + fprintf(stdout, "Examples1: %s XXX.api\n", prog); + fprintf(stdout, "Examples2: %s -DSOME_DEFINES XXX.api\n", prog); +} + +#define CPP_PROG "cpp" +static void free_cpp_argv(char **argv); + +static char ** +prepare_cpp_argv(int argc, char *argv[]) +{ + char **cpp_argv; + char **ret; + + cpp_argv = malloc(sizeof(char *) * (long unsigned int)(argc+1)); + if (cpp_argv == NULL) { + return NULL; + } + memset(cpp_argv, 0, sizeof(char *) * (long unsigned int)(argc+1)); + ret = cpp_argv; + + cpp_argv[0] = malloc(strlen(CPP_PROG)+1); + if (cpp_argv[0] == NULL) { + free_cpp_argv(ret); + return NULL; + } + strcpy(cpp_argv[0], CPP_PROG); + cpp_argv++; + + for( ; *argv != NULL ; argv++, cpp_argv++) { + *cpp_argv = malloc(strlen(*argv)+1); + if (*cpp_argv == NULL) { + free_cpp_argv(ret); + return NULL; + } + strcpy(*cpp_argv, *argv); + } + *cpp_argv = NULL; + return ret; +} + +static void +free_cpp_argv(char **argv) +{ + char **orig; orig = argv; + while(*argv != NULL) { + free(*argv); + argv++; + } + free(orig); +} + +/** @ingroup RPCtool + * @brief RPCtool main functions + * + * Perform the following processing. + * + * - Lexical context analysis of the API definition file(See apidef.y and apidef.l) + * - The API function definition read from the definition file is stored in the APIDef class. + * - Outputs stub and header files from function definitions stored in APIDef after a successful read + */ +int +main(int argc, char *argv[]) +{ + int start; + char **cpp_argv; + int pipefd[2]; + int pid; + int ret; + + if (argc < 2) { + usage(argv[0]); + return 1; + } + + start = 1; + yy_flex_debug = 0; + + if (!strcmp(argv[1], "-d")) { + yydebug=1; + yy_flex_debug = 1; + if (argc > 2) { + start++; + } else { + usage(argv[0]); + return 1; + } + } + +#ifdef DBG_ENABLE + /* + * If the second-to-last argument is a log specification + */ + if ( ( argc >= 2 ) && (!strcmp(argv[argc-2], "-log")) ) { + rpc_log_enable = 1; + } else { + rpc_log_enable = 0; + } +#endif + + /* + * Extract ID from last argument (API definition file name) + */ + { + char *moduleid; + moduleid = NULL; + extract_id(argv[argc-1], &moduleid); + if (moduleid == NULL) { + fprintf(stdout, "%s: The API definition file name is invalid.\n", argv[0]); + usage(argv[0]); + return 1; + } + ApidefDefineId(moduleid); + free(moduleid); + } + + /* + * Preparing options to exec CPPs + */ + cpp_argv = prepare_cpp_argv(argc, argv + start); + if (cpp_argv == NULL) { + printf("No Memory!\n"); + return 1; + } + +#define PIPE_READ 0 +#define PIPE_WRITE 1 + + if (pipe(pipefd) != 0) { + perror("pipe"); + return 1; + } + + pid = fork(); + if (pid < 0) {/* fork error */ + close(pipefd[PIPE_READ]); + close(pipefd[PIPE_WRITE]); + perror("fork"); + return 1; + } + if (pid == 0) {/* child process */ + int must_be_1; + /* + * force stdout to be pipefd[PIPE_WRITE] + */ + close(pipefd[PIPE_READ]); + close(1); + must_be_1 = dup(pipefd[PIPE_WRITE]); + assert(must_be_1 == 1); + close(pipefd[PIPE_WRITE]); + /* + * invoke C preprocessor with flags + */ + execvp(CPP_PROG, cpp_argv); + perror("execvp"); + exit(0); + } else { + /* + * parent process + */ + int must_be_0; + free_cpp_argv(cpp_argv); + + /* + * force stdin to be pipefd[PIPE_READ] + */ + close(pipefd[PIPE_WRITE]); + close(0); + must_be_0 = dup(pipefd[PIPE_READ]); + assert(must_be_0 == 0); + close(pipefd[PIPE_READ]); + } + + ret = yyparse(); + + free_flex_buffer(); + + if (ret == 0) {/* Parsed successfully */ + //ApidefListFunctions(1); + ApidefMakeStubs(); + } else {/* Parse error occurred */ + fputs("The APIs that have been analyzed so far are as follows.\n", stdout); + fputs("-----start-----\n", stdout); + ApidefListFunctions(0); + fputs("------end------\n", stdout); + fputs("Check this API definition\n", stdout); + } + ApidefFreeAllocation(); + + return ret; +} + +int +yyerror(const char *s) +{ + printf("\nError: %s\n", s); + return 0; +} + +int +yywrap() +{ + return 1; +} + +static char const *Types[] = { + "char", + "int", + "signed int", + "unsigned int", + "INT8", + "INT16", + "INT32", + "INT64", + "UINT8", + "UINT16", + "UINT32", + "UINT64", + "float", + "double", + "char *", +}; + +static const int TypeCodes[] = { + rpc_CHAR, + rpc_INT, + rpc_SINT, + rpc_UINT, + rpc_INT8, + rpc_INT16, + rpc_INT32, + rpc_INT64, + rpc_UINT8, + rpc_UINT16, + rpc_UINT32, + rpc_UINT64, + rpc_FLOAT, + rpc_DOUBLE, + rpc_STRING, +}; + +const char * +TypeCodeString(const int code) +{ + int i; + int num; + num = sizeof(TypeCodes) / sizeof(int); + + for(i = 0 ; i < num ; i++) { + if (code == TypeCodes[i]) { + return Types[i]; + } + } + return NULL; +} + +int +IsTypeCodeNumeric( const int code ) +{ + int i; + + for(i = 0 ; i < sizeof(TypeCodes) / sizeof(TypeCodes[0]) ; i++) { + if (TypeCodes[i] == rpc_FLOAT) { + break; + } + if (code == TypeCodes[i]) { + return 1; + } + } + return 0; +} diff --git a/otherservice/rpc_library/tool_for_arm/Makefile b/otherservice/rpc_library/tool_for_arm/Makefile new file mode 100755 index 0000000..67121b4 --- /dev/null +++ b/otherservice/rpc_library/tool_for_arm/Makefile @@ -0,0 +1,50 @@ +# +# @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +all test: apidef.tab.h + +clean: + rm -rf $(CLEAN_FILES) + +YACC := bison +YFLAGS := -d -t + +VPATH += ../tool +CPPFLAGS += -I../tool +OUTPUTDIR += ../tool + +apidef.tab.h apidef.tab.c: apidef.y + cd ../tool; $(YACC) $(YFLAGS) $< + +CLEAN_FILES := ../tool/apidef.tab.h ../tool/apidef.tab.c + +CLEAN_TARGET := clean-test clean-all clean-all-test \ +clean-self clean-self-test clean-all-sub clean-self-sub #comment out for make clean errorclean-sub + +EMPTY_TARGET := install-test build-lib build-prog build-shlib build-arlib \ +build-test-mock-lib build-test-mock-arlib build-test-mock-shlib build-cfg \ +install install-header install-test-mock-header install-test-casename install-lib \ +install-shlib install-arlib install-prog install-data install-cfg install-preload + + +.PHONY: all install test clean $(CLEAN_TARGET) $(EMPTY_TARGET) + +$(CLEAN_TARGET): clean + +$(EMPTY_TARGET): + + +include ../../other_service.mk diff --git a/otherservice/vehicle_parameter_library/LICENSE b/otherservice/vehicle_parameter_library/LICENSE new file mode 100755 index 0000000..f433b1a --- /dev/null +++ b/otherservice/vehicle_parameter_library/LICENSE @@ -0,0 +1,177 @@ + + 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 diff --git a/otherservice/vehicle_parameter_library/Makefile.client b/otherservice/vehicle_parameter_library/Makefile.client new file mode 100755 index 0000000..172da8f --- /dev/null +++ b/otherservice/vehicle_parameter_library/Makefile.client @@ -0,0 +1,18 @@ +# +# @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# +SUBDIRS := library + +include ../other_service.mk diff --git a/otherservice/vehicle_parameter_library/library/Makefile b/otherservice/vehicle_parameter_library/library/Makefile new file mode 100755 index 0000000..ae99cfa --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/Makefile @@ -0,0 +1,40 @@ +# +# @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. +# +# 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. +# + +INST_SHLIBS = libvp + +VPATH = ./src ./include/$(COMPONENT_NAME) + +INST_HEADERS = VP_GetEnv.h env_vehicle.h \ + env_vehicleparameterlibrary.h env_vehicleparameterlibrary_serial.h env_ext.h \ + VP_FuncCheck_CanRcv.h vehicle_parameter_library.h + +libvp_SRCS = VP_FuncCheck_CanRcv.c VP_GetEnv.c + +LDLIBS += -Wl,--no-as-needed +LDLIBS += -Wl,-Bdynamic -lns_backup + +CPPFLAGS += -I./include +CPPFLAGS += -Werror=implicit-function-declaration +CPPFLAGS += -Werror=format-security +CPPFLAGS += -Wconversion +CPPFLAGS += -Wpointer-to-int-cast +CPPFLAGS += -Wint-to-pointer-cast +CPPFLAGS += -Wpointer-arith +CPPFLAGS += -Wformat +CPPFLAGS += -DVP_FUNCCHECK_CANRCV_CANRCV_ACTIVATE + +include ../../other_service.mk diff --git a/otherservice/vehicle_parameter_library/library/include/VP_FuncCheck_CanRcv_private.h b/otherservice/vehicle_parameter_library/library/include/VP_FuncCheck_CanRcv_private.h new file mode 100755 index 0000000..193e54a --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/VP_FuncCheck_CanRcv_private.h @@ -0,0 +1,90 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/* ====================================================================== */ +/** + * @file VP_FuncCheck_CanRcv_private.h + * @brief Get function existence API internal header file + * @attention Cannot be included from external functions + * + * Exported because it will be inconvenient at MT + */ +/* ====================================================================== */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_VP_FUNCCHECK_CANRCV_PRIVATE_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_VP_FUNCCHECK_CANRCV_PRIVATE_H_ + +/* ====================================================================== */ +/* Include public headers */ +/* ====================================================================== */ +#include <other_service/VP_FuncCheck_CanRcv.h> + +/* ====================================================================== */ +/* Internal definitions for debugging */ +/* ====================================================================== */ +#ifdef DEBUG_MT + #include <stdio.h> + + #define MT_STATIC /**< Static definitions - Remove the static in order to remove the file scope at MT. */ + + /**< Debugging output function - Compile the entity at MT */ + #define DEBUG_PRINT(msg) {printf("%s\n", (msg) ) ;} + /**< Debugging output function - Compile the entity at MT */ + #define DEBUG_PRINTF(format, msg) {printf((format), (msg) ) ;} + + /**< Static assertion */ + #define VP_DEBUG_STATIC_ASSERT(expr) do { int static_assert[ (expr)? 1:-1 ]; }while(0); +#else + /**< Static definitions. The scope shall be limited by static at the time of releasing. + * Remove the static in order to remove the file scope at MT. + */ + #define MT_STATIC static + + /**< Static definitions. The scope shall be limited by static at the time of releasing. + * Remove the static in order to remove the file scope at MT. + */ + #define DEBUG_PRINT(msg) + + /**< Static definitions. The scope shall be limited by static at the time of releasing. + * Remove the static in order to remove the file scope at MT. + */ + #define DEBUG_PRINTF(format, msg) + + /**< Static definitions. The scope shall be limited by static at the time of releasing. + * Remove the static in order to remove the file scope at MT. + */ + #define VP_DEBUG_STATIC_ASSERT(expr) +#endif + +/* ====================================================================== */ +/* General-purpose type definition - Redifined for internal use */ +/* ====================================================================== */ +/**< Internal boolean type - sys/type.h has no type definitions, so defined it here. FCCR: "F"unc"C"heck_"C"an"R"cv */ +typedef enum VP_FCCR_BOOL_Tag { + B_FALSE, /**< FALSE */ + B_TRUE /**< TRUE */ +} VP_FCCR_BOOL; + + +/* ====================================================================== */ +/* Structure */ +/* ====================================================================== */ +typedef struct TABLE_INDEX_INFO_tag { + char* code_str; /**< String that can be gotten from vehicle parameters */ + unsigned int index; /**< Index for function existence */ +} TABLE_INDEX_INFO; + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_VP_FUNCCHECK_CANRCV_PRIVATE_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/VP_FuncCheck_CanRcv.h b/otherservice/vehicle_parameter_library/library/include/other_service/VP_FuncCheck_CanRcv.h new file mode 100755 index 0000000..17b4503 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/VP_FuncCheck_CanRcv.h @@ -0,0 +1,133 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/* ====================================================================== */ +/** + * @file VP_FuncCheck_CanRcv.h + * @brief \~english Get function existence API header file + */ +/* ====================================================================== */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_FUNCCHECK_CANRCV_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_FUNCCHECK_CANRCV_H_ + +#include <sys/types.h> + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ + +// typedef unsigned char u_int8; + + +/** +* @~english XM Audio +*/ +#define XM_AUDIO ((u_int8_t)1) +/** +* @~english _CWORD76_ +*/ +#define _CWORD76_ ((u_int8_t)2) + +#define VP_CANRCV__CWORD27_ ((u_int8_t)3) /**< _CWORD27_ */ +/** +* @~english WiFi HotSpot +*/ +#define WIFI_HOTSPOT ((u_int8_t)4) +/** +* @~english standard driving rregulation of AREA1 +*/ +#define AREA1_STD_TRAF_LIMIT ((u_int8_t)5) +/** +* @~english HD Data (Include traffic) +*/ +#define HD_DATA ((u_int8_t)6) +/** +* @~english WiFi 5G +*/ +#define WIFI_5G ((u_int8_t)7) + +/** +* @~english definiton of return value of API(VP_FuncCheck_CanRcv),which is used to get status of function implemention +*/ +#define FUNCTION_CHECK_RESULT_OK ((u_int8_t)0) +/** +* @~english this function is invalid +*/ +#define FUNCTION_CHECK_RESULT_NG ((u_int8_t)1) +/** +* @~english this function does not exist +*/ +#define FUNCTION_CHECK_RESULT_UNKNOWN ((u_int8_t)2) +/** +* @~english reference out of AREA1 +*/ +#define FUNCTION_CHECK_RESULT_OUT_OF_AREA1 ((u_int8_t)3) + +/* Function prototype declaration */ +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup VP_FuncCheck_CanRcv +/// \~english @par Brief +/// VP_FuncCheck_CanRcv +/// \~english @param [in] FunctionName +/// function name +/// \~english @retval FUNCTION_CHECK_RESULT_OK: This function is available +/// \~english @retval FUNCTION_CHECK_RESULT_NG: This function is unavailable +/// \~english @retval FUNCTION_CHECK_RESULT_UNKNOWN: This function does not exist +/// \~english @retval FUNCTION_CHECK_RESULT_OUT_OF_AREA1: reference out of Area1 +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - To get the function check result from +/// - vehicle parameter:CAN info judge +/// - vehicle parameter:country ID +/// - country ID and function judge info in API +/// - When vehicle parameter:CAN info judge +/// is [CAN_judge] or [country_ID], +/// and if country_ID is unacquainted or undefined, the API returns [available]. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////// +u_int8_t VP_FuncCheck_CanRcv(u_int8_t FunctionName); + +#ifdef __cplusplus +} +#endif + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_FUNCCHECK_CANRCV_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/VP_GetEnv.h b/otherservice/vehicle_parameter_library/library/include/other_service/VP_GetEnv.h new file mode 100755 index 0000000..69f6df2 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/VP_GetEnv.h @@ -0,0 +1,114 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/* ====================================================================== */ +/** + * @file VP_GetEnv.h + * @brief \~english Get vehicle parameter environment variable API header file + */ +/* ====================================================================== */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_GETENV_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_GETENV_H_ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ +#include <other_service/env_ext.h> + +/** +* @~english the max length of vehicle parameter environment viarable +*/ + +#define VP_MAX_LENGTH 128 + +/** +* @~english definition of parameter environment viarable such as destination +* destination diff +*/ + +#define VEHICLEPARAMETERLIBRARY_AREA "VEHICLEPARAMETERLIBRARY_AREA" + +/** +* @~english brand diff +*/ +#define VEHICLEPARAMETERLIBRARY_BRAND "VEHICLEPARAMETERLIBRARY_BRAND" + +/** +* @~english definition of _CWORD31_ vehicle parameter environment viarable +*/ +#include <other_service/env_vehicle.h> + +/** +* @~english definition of vehicle parameter environment viarable +*/ +#include <other_service/env_vehicleparameterlibrary.h> + +/** +* @~english definition of Serial vehicle parameter environment viarable +*/ +#include <other_service/env_vehicleparameterlibrary_serial.h> + +/* Function prototype declaration */ +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// \ingroup VP_GetEnv +/// \~english @par Brief +/// VP_GetEnv +/// \~english @param [in] pEnvStr +/// The pointer of environment variable name string +/// \~english @param [out] pEnvBuff +/// The head address of saving environment variable value +/// \~english @retval None +/// \~english @par Prerequisite +/// None +/// \~english @par Change of internal state +/// None +/// \~english @par Conditions of processing failure +/// None +/// \~english @par Classification +/// Public +/// \~english @par Type +/// Sync Only +/// \~english @par Detail +/// - To get the environment variable value by the environment variable name, +/// and save it in pEnvBuff. +/// - When environment variable name is NULL or an undefined value, +/// a blank string shall be saved in pEnvBuff. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////// +void VP_GetEnv(const char *pEnvStr, char *pEnvBuff); + +#ifdef __cplusplus +} +#endif + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_VP_GETENV_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/env_ext.h b/otherservice/vehicle_parameter_library/library/include/other_service/env_ext.h new file mode 100755 index 0000000..266e510 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/env_ext.h @@ -0,0 +1,45 @@ +/* + * @copyright Copyright (c) 2019-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file env_ext.h + * @brief \~english Define of supplier vehicle parameter environment variable. + */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_EXT_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_EXT_H_ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ + +// +// Please describe supplier-specific definitions of the vehicle parameters. +// + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_EXT_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicle.h b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicle.h new file mode 100755 index 0000000..a0eaaf9 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicle.h @@ -0,0 +1,331 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file env_vehicle.h + * @brief \~english Define of _CWORD31_ vehicle parameter environment variable + */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLE_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLE_H_ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ + +/** +* @~english _CWORD31_ version +*/ +#define VP__CWORD31__VERSION "VP__CWORD31__version" +/** +* @~english _CWORD31_ class type of LAN +*/ + +#define VP__CWORD31__CLASS_TYPE_OF_LAN "VP__CWORD31__class_type_of_LAN" +/** +* @~english _CWORD31_ reverse signal +*/ + +#define VP__CWORD31__REVERSE "VP__CWORD31__reverse" +/** +* @~english _CWORD31_ PKB signal +*/ + +#define VP__CWORD31__PKB "VP__CWORD31__PKB" +/** +* @~english _CWORD31_ ADIM signal of _CWORD62_ +*/ + +#define VP__CWORD31__ADIM__CWORD62_ "VP__CWORD31__ADIM__CWORD62_" +/** +* @~english _CWORD31_ telematics function +*/ + +#define VP__CWORD31__TELEMATICS_FUNCTION "VP__CWORD31__telematics_function" +/** +* @~english _CWORD31_ opening picture +*/ + +#define VP__CWORD31__OPENING_PICTURE "VP__CWORD31__opening_picture" +/** +* @~english _CWORD31_ theme color +*/ + +#define VP__CWORD31__THEME_COLOR "VP__CWORD31__theme_color" +/** +* @~english _CWORD31_ vehicle design vehicle body +*/ +#define VP__CWORD31__VEHICLE_BODY "VP__CWORD31__vehicle_body" +/** +* @~english _CWORD31_ air conditioner on screen +*/ +#define VP__CWORD31__AC_ONSCREEN "VP__CWORD31__AC_onscreen" +/** +* @~english _CWORD31_ air conditioner screen operation +*/ +#define VP__CWORD31__AC_SCREEN_OPERATION "VP__CWORD31__AC_screen_operation" +/** +* @~english _CWORD31_ air conditioner home screen +*/ +#define VP__CWORD31__AC_SCREEN_HOME "VP__CWORD31__AC_screen_home" +/** +* @~english _CWORD31_ air conditioner switch concierge +*/ +#define VP__CWORD31__AC_SWITCH_CONCIERGE "VP__CWORD31__AC_switch_concierge" +/** +* @~english _CWORD31_ _CWORD113_ +*/ +#define VP__CWORD31___CWORD11_ "VP__CWORD31___CWORD11_" +/** +* @~english _CWORD31_ EF home screen +*/ +#define VP__CWORD31___CWORD11__HOME "VP__CWORD31___CWORD11__home" +/** +* @~english _CWORD31_ drive wheel of _CWORD113_ +*/ +#define VP__CWORD31___CWORD11__DRIVE_WHEEL "VP__CWORD31___CWORD11__drive_wheel" +/** +* @~english _CWORD31_ drive type of _CWORD113_ +*/ +#define VP__CWORD31___CWORD11__DRIVE_TYPE "VP__CWORD31___CWORD11__drive_type" +/** +* @~english _CWORD31_ battery position of _CWORD113_ +*/ +#define VP__CWORD31___CWORD11__BATTERY_POSITION "VP__CWORD31___CWORD11__battery_position" +/** +* @~english _CWORD31_ _CWORD112_ trip +*/ +#define VP__CWORD31___CWORD9__TRIP "VP__CWORD31___CWORD9__trip" +/** +* @~english _CWORD31_ FC home screen trip +*/ +#define VP__CWORD31___CWORD9__HOME_TRIP "VP__CWORD31___CWORD9__home_trip" +/** +* @~english _CWORD31_ _CWORD112_ fuel +*/ +#define VP__CWORD31___CWORD9__FUEL "VP__CWORD31___CWORD9__fuel" +/** +* @~english _CWORD31_ FC home screen fuel +*/ +#define VP__CWORD31___CWORD9__HOME_FUEL "VP__CWORD31___CWORD9__home_fuel" +/** +* @~english _CWORD31_ FC eco safety point service +*/ +#define VP__CWORD31__FC_ECO_SAFETY_POINT_SERVICE "VP__CWORD31__FC_eco_safety_point_service" +/** +* @~english _CWORD31_ FC GAS scale +*/ +#define VP__CWORD31__FC_SCALE_GAS "VP__CWORD31__FC_scale_GAS" +/** +* @~english _CWORD31_ FC HV scale +*/ +#define VP__CWORD31__FC_SCALE_HV "VP__CWORD31__FC_scale_HV" +/** +* @~english _CWORD31_ fuel consumption display function scale of fuel consumption (ForFC) +*/ +#define VP__CWORD31__FC_SCALE_FC "VP__CWORD31__FC_scale_FC" +/** +* @~english _CWORD31_ fuel consumption display function scale of fuel consumption (ForEV) +*/ +#define VP__CWORD31__FC_SCALE_EV "VP__CWORD31__FC_scale_EV" +/** +* @~english _CWORD31_ FC energy mark +*/ +#define VP__CWORD31__FC_ENERGY_MARK "VP__CWORD31__FC_energy_mark" +/** +* @~english _CWORD31_ _CWORD112_ type +*/ +#define VP__CWORD31___CWORD9__TYPE "VP__CWORD31___CWORD9__type" +/** +* @~english _CWORD31_ FC signal +*/ +#define VP__CWORD31__FC_SIGNAL "VP__CWORD31__FC_SIGNAL" +/** +* @~english _CWORD31_ display setting screen +*/ +#define VP__CWORD31__DISPLAY_SETTING_SCREEN "VP__CWORD31__display_setting_screen" +/** +* @~english _CWORD31_ clock type +*/ +#define VP__CWORD31__CLOCK_TYPE "VP__CWORD31__clock_type" +/** +* @~english _CWORD31_ start up BGM +*/ +#define VP__CWORD31__START_UP_BGM "VP__CWORD31__start_up_BGM" +/** +* @~english _CWORD31_ start up BGM type +*/ +#define VP__CWORD31__START_UP_BGM_TYPE "VP__CWORD31__start_up_BGM_type" +/** +* @~english _CWORD31_ font left DTV antenna +*/ +#define VP__CWORD31__DTV_ANTENNA_FL "VP__CWORD31__DTV_antenna_FL" +/** +* @~english _CWORD31_ font right DTV antenna +*/ +#define VP__CWORD31__DTV_ANTENNA_FR "VP__CWORD31__DTV_antenna_FR" +/** +* @~english _CWORD31_ rear left DTV antenna +*/ +#define VP__CWORD31__DTV_ANTENNA_RL "VP__CWORD31__DTV_antenna_RL" +/** +* @~english _CWORD31_ rear right DTV antenna +*/ +#define VP__CWORD31__DTV_ANTENNA_RR "VP__CWORD31__DTV_antenna_RR" +/** +* @~english _CWORD31_ DTV antenna +*/ +#define VP__CWORD31__DTV_ANTENNA "VP__CWORD31__DTV_antenna" +/** +* @~english _CWORD31_ antenna info antenna available / unavailable +*/ +#define VP__CWORD31__BEACON_ANTENNA "VP__CWORD31__beacon_antenna" +/** +* @~english _CWORD31_ HF voice quality type +*/ +#define VP__CWORD31__HF_VOICE_QUALITY_TYPE "VP__CWORD31__HF_voice_quality_type" +/** +* @~english _CWORD31_ DAB antenna +*/ +#define VP__CWORD31__DAB_ANTENNA "VP__CWORD31__DAB_antenna" +/** +* @~english _CWORD31_ DAB screen display +*/ +#define VP__CWORD31__DAB_SCREEN "VP__CWORD31__DAB_screen" +/** +* @~english _CWORD31_ hard switch beep +*/ +#define VP__CWORD31__HARD_SWITCH_BEEP "VP__CWORD31__hard_switch_beep" +/** +* @~english _CWORD31_ beep while hard SW being pressed +*/ +#define VP__CWORD31__SCREEN_SWITCH_BEEP "VP__CWORD31__screen_switch_beep" +/** +* @~english _CWORD31_ steering SW type of steering SW +*/ +#define VP__CWORD31__STEERING_SWITCH_TYPE "VP__CWORD31__steering_switch_type" +/** +* @~english _CWORD31_ TEL switch of steering +*/ +#define VP__CWORD31__STEERING_SWITCH_TEL "VP__CWORD31__steering_switch_tel" +/** +* @~english _CWORD31_ class circuit mode +*/ +#define VP__CWORD31__CLASS_CIRCUIT_MODE "VP__CWORD31__class_circuit_mode" +/** +* @~english _CWORD31_ panel microcomputer +*/ +#define VP__CWORD31__PANEL_MICROCOMPUTER "VP__CWORD31__panel_microcomputer" +/** +* @~english _CWORD31_ class watch at brake hold +*/ +#define VP__CWORD31__CLASS_WATCH_AT_BRAKE_HOLD "VP__CWORD31__class_watch_at_brake_hold" +/** +* @~english _CWORD31_ GPS antenna +*/ +#define VP__CWORD31__GPS_ANTENNA "VP__CWORD31__GPS_antenna" +/** +* @~english _CWORD31_ ILL- available / unavailable +*/ +#define VP__CWORD31__ILL_SIGNAL "VP__CWORD31__ILL_signal" +/** +* @~english _CWORD31_ switch trigger +*/ +#define VP__CWORD31__SWITCH_TRIGGER "VP__CWORD31__switch_trigger" +/** +* @~english _CWORD31_ sensitivity level +*/ +#define VP__CWORD31__SENSITIVITY_LEVEL "VP__CWORD31__sensitivity_level" +/** +* @~english _CWORD31_ hadsfree bluetooth device name / WiFi AP name selection +*/ +#define VP__CWORD31__BT_DEVICE_AP_NAME "VP__CWORD31__BT_device_AP_name" +/** +* @~english _CWORD31_ Eco drive max vol setting in D4 model +*/ +#define VP__CWORD31__ECO_RUN_D4_VOL_MAX "VP__CWORD31__eco_run_D4_VOL_max" +/** +* @~english _CWORD31_ thumbnail type +*/ +#define VP__CWORD31__THUMBNAIL_TYPE "VP__CWORD31__thumbnail_type" +/** +* @~english _CWORD31_ EOM function +*/ +#define VP__CWORD31__EOM_FUNCTION "VP__CWORD31__EOM_function" +/** +* @~english _CWORD31_ Microphone Type +*/ +#define VP__CWORD31__MICROPHONE_TYPE "VP__CWORD31__Microphone_Type" +/** +* @~english _CWORD31_ Microphone Location +*/ +#define VP__CWORD31__MICROPHONE_LOCATION "VP__CWORD31__Microphone_Location" +/** +* @~english _CWORD31_ VR microphone parameter vehicle noize level +*/ +#define VP__CWORD31__VEHICLE_NOIZE_LEVEL "VP__CWORD31__vehicle_noize_level" + +/** +* @~english _CWORD31_ wide band FM +*/ +#define VP__CWORD31__WIDE_BAND_FM "VP__CWORD31__Wide_band_FM" +/** +* @~english _CWORD31_ map color +*/ +#define VP__CWORD31__MAP_COLOR "VP__CWORD31__map_color" +/** +* @~english _CWORD31_ cloud eco +*/ +#define VP__CWORD31__CLOUD_ECO "VP__CWORD31__cloud_eco" +/** +* @~english _CWORD31_ eg type +*/ +#define VP__CWORD31__EG_TYPE "VP__CWORD31__EG_type" + +/** +* @~english _CWORD31_ display type +*/ +#define VP__CWORD31__DISPLAY_TYPE "VP__CWORD31__display_type" +/** +* @~english _CWORD31_ clock display +*/ +#define VP__CWORD31__CLOCK_DISPLAY "VP__CWORD31__clock_display" +/** +* @~english _CWORD31_ destination +*/ +#define VP__CWORD31__DESTINATION "VP__CWORD31__destination" +/** +* @~english _CWORD31_ class operation +*/ +#define VP__CWORD31__CLASS_OPERATION "VP__CWORD31__class_operation" +/** +* @~english _CWORD31_ DES function +*/ +#define VP__CWORD31__DES_FUNCTION "VP__CWORD31__DES_function" + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLE_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary.h b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary.h new file mode 100755 index 0000000..1c0020c --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary.h @@ -0,0 +1,138 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file env_vehicleparameterlibrary.h + * @brief \~english Define of vehicle parameter environment variable + */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_H_ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ + +/** +* @~english version +*/ +#define VP_VEHICLEPARAMETERLIBRARY_VERSION "VP_VEHICLEPARAMETERLIBRARY_version" +/** +* @~english maker ID +*/ +#define VP_VEHICLEPARAMETERLIBRARY_MAKER_ID "VP_VEHICLEPARAMETERLIBRARY_maker_ID" +/** +* @~english area +*/ +#define VP_VEHICLEPARAMETERLIBRARY_AREA "VP_VEHICLEPARAMETERLIBRARY_area" +/** +* @~english grade +*/ +#define VP_VEHICLEPARAMETERLIBRARY_GRADE "VP_VEHICLEPARAMETERLIBRARY_grade" +/** +* @~english destination country code +*/ +#define VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE "VP_VEHICLEPARAMETERLIBRARY_dest_c_code" +/** +* @~english DAB tuner number +*/ +#define VP_VEHICLEPARAMETERLIBRARY_DAB_TUNER_NUM "VP_VEHICLEPARAMETERLIBRARY_DAB_tuner_num" +/** +* @~english AM radio +*/ +#define VP_VEHICLEPARAMETERLIBRARY_AM_RADIO "VP_VEHICLEPARAMETERLIBRARY_AM_Radio" +/** +* @~english amp type +*/ +#define VP_VEHICLEPARAMETERLIBRARY_AMP_TYPE "VP_VEHICLEPARAMETERLIBRARY_AMP_type" +/** +* @~english display +*/ +#define VP_VEHICLEPARAMETERLIBRARY_DISPLAY "VP_VEHICLEPARAMETERLIBRARY_DISPLAY" +/** +* @~english touch panel +*/ +#define VP_VEHICLEPARAMETERLIBRARY_TOUCHPANEL "VP_VEHICLEPARAMETERLIBRARY_TOUCHPANEL" +/** +* @~english DECK +*/ +#define VP_VEHICLEPARAMETERLIBRARY_DECK "VP_VEHICLEPARAMETERLIBRARY_DECK" +/** +* @~english JP traffic information show +*/ +#define VP_VEHICLEPARAMETERLIBRARY_JPTRAFFICINFO_SHOW "VP_VEHICLEPARAMETERLIBRARY_JPTrafficInfo_show" +/** +* @~english connection server +*/ +#define VP_VEHICLEPARAMETERLIBRARY_CONNECTION_SERVER "VP_VEHICLEPARAMETERLIBRARY_CONNECTION_SERVER" +/** +* @~english _CWORD40_ generation +*/ +#define VP_VEHICLEPARAMETERLIBRARY__CWORD40_ "VP_VEHICLEPARAMETERLIBRARY__CWORD40_" + +/** +* @~english Radio reception level +*/ +#define VP_VEHICLEPARAMETERLIBRARY_RADIO_LV_DIAG "VP_VEHICLEPARAMETERLIBRARY_RADIO_LV_DIAG" + +/** +* @~english Navigation model +*/ +#define VP_VEHICLEPARAMETERLIBRARY_NAVI "VP_VEHICLEPARAMETERLIBRARY_NAVI" + +/** +* @~english Map update service +*/ +#define VP_VEHICLEPARAMETERLIBRARY_MAP_UPDATE "VP_VEHICLEPARAMETERLIBRARY_MAP_UPDATE" + +/** +* @~english Headunit identification +*/ +#define VP_HEAD_UNIT_ID "VP_HEAD_UNIT_ID" + +/** +* @~english Serius raido +*/ +#define VP_VEHICLEPARAMETERLIBRARY_SDARS "VP_VEHICLEPARAMETERLIBRARY_SDARS" + +/** +* @~english optional amp +*/ +#define VP_VEHICLEPARAMETERLIBRARY_ACCESSORY_AMP "VP_VEHICLEPARAMETERLIBRARY_ACCESSORY_AMP" + +/** +* @~english Key trace +*/ +#define VP_VEHICLEPARAMETERLIBRARY_KEY_TRACE "VP_VEHICLEPARAMETERLIBRARY_KEY_TRACE" + +/** +* @~english diatal TV +*/ +#define VP_VEHICLEPARAMETERLIBRARY_DTV "VP_VEHICLEPARAMETERLIBRARY_DTV" + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary_serial.h b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary_serial.h new file mode 100755 index 0000000..04ae10e --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/env_vehicleparameterlibrary_serial.h @@ -0,0 +1,46 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file env_vehicleparameterlibrary_serial.h + * @brief \~english Define of Serial vehicle parameter environment variable + */ + +#ifndef VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_SERIAL_H_ +#define VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_SERIAL_H_ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ + +/** + * \~english Enviroment variable _CWORD49__ID + */ +#define VP_VEHICLEPARAMETERLIBRARY_SER__CWORD49__ID "VP_VEHICLEPARAMETERLIBRARY_SER__CWORD49__ID" + +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // VEHICLE_PARAMETER_LIBRARY_LIBRARY_INCLUDE_OTHER_SERVICE_ENV_VEHICLEPARAMETERLIBRARY_SERIAL_H_ diff --git a/otherservice/vehicle_parameter_library/library/include/other_service/vehicle_parameter_library.h b/otherservice/vehicle_parameter_library/library/include/other_service/vehicle_parameter_library.h new file mode 100755 index 0000000..151bae5 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/include/other_service/vehicle_parameter_library.h @@ -0,0 +1,46 @@ +/* + * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file vehicle_parameter_library.h + * @brief \~english include all vehicle_parameter_library head files + */ + +#ifndef OTHERSERVICE_VEHICLEPARAMETERLIBRARY_H_ // NOLINT(build/header_guard) +#define OTHERSERVICE_VEHICLEPARAMETERLIBRARY_H_ // NOLINT(build/header_guard) + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup other_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup vehicle_parameter_library + * @ingroup other_service + * @{ + */ +#include <other_service/VP_FuncCheck_CanRcv.h> +#include <other_service/VP_GetEnv.h> +#include <other_service/env_vehicleparameterlibrary.h> +#include <other_service/env_vehicleparameterlibrary_serial.h> +#include <other_service/env_vehicle.h> +#include <other_service/env_ext.h> +/** @}*/ // end of vehicle_parameter_library +/** @}*/ // end of other_service +/** @}*/ // end of BaseSystem + +#endif // OTHERSERVICE_VEHICLEPARAMETERLIBRARY_H_ diff --git a/otherservice/vehicle_parameter_library/library/src/VP_FuncCheck_CanRcv.c b/otherservice/vehicle_parameter_library/library/src/VP_FuncCheck_CanRcv.c new file mode 100755 index 0000000..938ea7f --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/src/VP_FuncCheck_CanRcv.c @@ -0,0 +1,732 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/** + * @file VP_FuncCheck_CanRcv.c + * @brief Get function existence API + */ + + +/* ====================================================================== */ +/* Header */ +/* ====================================================================== */ +#include <assert.h> +#include <string.h> +#include <regex.h> + +#include <other_service/VP_GetEnv.h> +#include "VP_FuncCheck_CanRcv_private.h" + +/* ====================================================================== */ +/* Enumeration types */ +/* ====================================================================== */ +typedef enum VPFuncTableDestIndexTag{ + /* + * Note. + * This feature needs to be defined by the vendor. + */ + VP_FUNC_TABLE_DEST_INDEX_A , + VP_FUNC_TABLE_DEST_INDEX_B , + + VP_FUNC_TABLE_DEST_INDEX_MAX /**< Number of choices (index maximum value: 1) */ +} VP_FUNC_TABLE_DEST_INDEX; + +typedef enum VPFuncTableBrandTag{ + /* + * Note. + * This feature needs to be defined by the vendor. + */ + VP_FUNC_TABLE_BRAND_A, + VP_FUNC_TABLE_BRAND_B, + + VP_FUNC_TABLE_BRAND_INDEX_MAX /**< Number of choices (index maximum value: 1) */ +} VP_FUNC_TABLE_BRAND; + +typedef enum VPFuncTableGradeLTag{ + /* + * Note. + * This feature needs to be defined by the vendor. + */ + VP_FUNC_TABLE_GRADE_A1, + VP_FUNC_TABLE_GRADE_A2, + + VP_FUNC_TABLE_GRADE_A_INDEX_MAX /**< Number of choices (index maximum value: 1) */ +} VP_FUNC_TABLE_GRADE_A; + +typedef enum VPFuncTableGradeTTag{ + /* + * Note. + * This feature needs to be defined by the vendor. + */ + VP_FUNC_TABLE_GRADE_B1, + VP_FUNC_TABLE_GRADE_B2, + + VP_FUNC_TABLE_GRADE_B_INDEX_MAX /**< Number of choices (index maximum value: 1) */ +} VP_FUNC_TABLE_GRADE_B; + +typedef enum VPFuncTableFuncTypeIndexTag{ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_UNKNOWN , /**< Unknown function */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_XM_AUDIO , /**< XM Audio */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_VP_CANRCV__CWORD27_ , /**< _CWORD27_ */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_HOTSPOT , /**< Wifi Hotspot */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_RESTRICT_FUNCTION , /**< Travel Restriction */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_HD_DATA , /**< HD Data */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_5G , /**< Wifi 5G */ + + VP_FUNC_TABLE_FUNC_TYPE_INDEX_MAX /**< Number of choices (index maximum value: 1) */ +} VP_FUNC_TABLE_FUNC_TYPE; + +/** Processing definitions for CAN information availability */ +typedef enum CANFuncCheckSwitchTag{ + CAN_FUNC_CHEK_AVAILABLE , + CAN_FUNC_CHEK_UNAVAILABLE , + CAN_FUNC_CHEK_COUNTRY_CODE +} CAN_FUNC_CHEK_SWITCH; + + + +/**< Definition of number of functions (required for initial definition of function availability table) */ + +#define VP_FUNC_TABLE_FUNCTION_INDEX_MAX ((unsigned int)7) + +/* ====================================================================== */ +/* Macro definitions */ +/* ====================================================================== */ +/* Definition for return value from string functions */ +#define RET_STD_LIB_STRING_STR_CMP_OK ((int)0) /**< The return value of the strncmp. this value is returned when matched. */ + +/* Default index values */ +#define DEFAULT_TABLE_INDEX_DEST (VP_FUNC_TABLE_DEST_INDEX_A) /* Initial value changed by the specification which returns the setting of the belonging property when the undefined country code is gotten. */ +#define DEFAULT_TABLE_INDEX_BRAND (VP_FUNC_TABLE_BRAND_A) +#define DEFAULT_TABLE_INDEX_GRADE_A (VP_FUNC_TABLE_GRADE_A1) +#define DEFAULT_TABLE_INDEX_GRADE_B (VP_FUNC_TABLE_GRADE_B1) +#define DEFAULT_CAN_JUDGE_STATUS (CAN_FUNC_CHEK_COUNTRY_CODE) + +/* ====================================================================== */ +/* Constant definitions */ +/* ====================================================================== */ + +/* ====================================================================== */ +/* Structures */ +/* ====================================================================== */ + +/* ====================================================================== */ +/* Internal function prototype declarations */ +/* ====================================================================== */ +#ifdef VP_FUNCCHECK_CANRCV_CANRCV_ACTIVATE +MT_STATIC u_int8_t getResult_CanJudge( unsigned int idx_func ); +MT_STATIC unsigned int getIndexOfFunc( u_int8_t func ); +MT_STATIC unsigned int getIndexOfTable( const char vp_param_str[] , const TABLE_INDEX_INFO table_index_info[] , unsigned int info_size, unsigned int default_index ); +MT_STATIC VP_FCCR_BOOL hasMultipleCoutnry( const char dest_str[] , const char multiple_country_code_desig[] ); +#endif +/* ====================================================================== */ +/* Public function definitions */ +/* ====================================================================== */ +/** + * @fn + * u_int8_t VP_FuncCheck_CanRcv( u_int8_t FunctionName ) + * @brief Get function existence API(Public) + * @param[in] (FunctionName) Function Name (Number) + * @return FUNCTION_CHECK_RESULT_OK :This function is available + * FUNCTION_CHECK_RESULT_NG :This function is unavailable + * FUNCTION_CHECK_RESULT_UNKNOWN :This function does not exist + * @details Read the function name as feature name specified in the argument, then return one of the + * "This function is available"/"This function is unavailable"/"This function does not exist" + * of the feature as the following check-result: + * - vehicle parameter:CAN information availability(destination package) judge + * - vehicle parameter:country code + * - Whether or not supported the features corresponding to the country code in this API + * + * When CAN information availability (destination package) in vehicle parameters is + * "Control ON/OFF according to CAN information" or "Country code", return "This function is available" + * if this function is called when the country code from CAN is unacquired or undetermined country code. + */ +/* ====================================================================== */ +u_int8_t VP_FuncCheck_CanRcv( u_int8_t FunctionName ) +{ +#ifndef VP_FUNCCHECK_CANRCV_CANRCV_ACTIVATE + u_int8_t result; + + switch(FunctionName) { + case XM_AUDIO: + result = FUNCTION_CHECK_RESULT_NG; + break; + + case VP_CANRCV__CWORD27_: + case WIFI_HOTSPOT: + case AREA1_STD_TRAF_LIMIT: + case HD_DATA: + case WIFI_5G: + result = FUNCTION_CHECK_RESULT_OK; + break; + default: + result = FUNCTION_CHECK_RESULT_UNKNOWN; + break; + } + + return result; +#else + + /* ====================================================================== */ + /* Internal table definition */ + /* ====================================================================== */ + /** Vehicle Parameter "CAN information Support/Not Support"- processing selector translation table */ + const TABLE_INDEX_INFO TABLE_STATUS_INFO_CAN_JUDGE[] = + { + { "available" , CAN_FUNC_CHEK_AVAILABLE }, // Yes + { "unavailable" , CAN_FUNC_CHEK_UNAVAILABLE }, // None + { "CAN_judge" , CAN_FUNC_CHEK_COUNTRY_CODE }, // Control ON/OFF according to CAN information + { "country_ID" , CAN_FUNC_CHEK_COUNTRY_CODE } // Country code + }; + + /* ====================================================================== */ + /* Table Size Definition */ + /* ====================================================================== */ + const unsigned int LENGTHOF_TABLE_INDEX_INFO_CAN_JUDGE = ( sizeof(TABLE_STATUS_INFO_CAN_JUDGE ) / sizeof( TABLE_INDEX_INFO ) ); + + /* ====================================================================== */ + /* Internal variable declarations */ + /* ====================================================================== */ + u_int8_t result = FUNCTION_CHECK_RESULT_UNKNOWN; + + unsigned int idx_func = 0; + + unsigned int can_judge_status = CAN_FUNC_CHEK_COUNTRY_CODE; + char VP_canjudge[ VP_MAX_LENGTH ]; + char VP_area[ VP_MAX_LENGTH ]; + + /* ====================================================================== */ + /* Process */ + /* ====================================================================== */ + /* Get vehicle parameter */ + VP_GetEnv( VEHICLEPARAMETERLIBRARY_AREA , &(VP_area[0]) ); + + DEBUG_PRINTF( "AREA = %s; " , VP_area ) + + /* Get feature name index */ + idx_func = getIndexOfFunc( FunctionName ); + + DEBUG_PRINTF( "Function = %d; " , FunctionName ) + DEBUG_PRINTF( "idx_func = %d\n" , idx_func ) + + /* Judge as other than area1 because it is not a area1 */ + if ( strncmp( VP_area, "AREA1", VP_MAX_LENGTH ) != RET_STD_LIB_STRING_STR_CMP_OK ) + { + result = FUNCTION_CHECK_RESULT_OUT_OF_AREA1; + } + else + { + /* If the feature is unknown, it is judged to be unknown before checking CAN information. */ + if ( VP_FUNC_TABLE_FUNC_TYPE_INDEX_UNKNOWN == idx_func ) + { + result = FUNCTION_CHECK_RESULT_UNKNOWN; + } + else + { + /* Get vehicle parameter */ /* It is unnecessary to get the parameter every time, but because there is no process to check the change, it is gotten every time as a precaution. */ + VP_GetEnv( VP__CWORD31__TELEMATICS_FUNCTION , &(VP_canjudge[0]) ); + + /* Choose processing according to CAN information Support/Not Support. */ + can_judge_status = getIndexOfTable( + &(VP_canjudge[0]), + &(TABLE_STATUS_INFO_CAN_JUDGE[0]), + LENGTHOF_TABLE_INDEX_INFO_CAN_JUDGE, + DEFAULT_CAN_JUDGE_STATUS + ); + + DEBUG_PRINTF( "VP_canjudge = %s; ", VP_canjudge ) + + /* When judging from CAN information or country code */ + if ( CAN_FUNC_CHEK_COUNTRY_CODE == can_judge_status ) + { + DEBUG_PRINT( "CAN judge : C_CODE or CAN_JUDGE" ) + result = getResult_CanJudge( idx_func ); + } + else + { + /* For available/unavailable */ + /* Standard travel restriction of AREA1 */ + if ( AREA1_STD_TRAF_LIMIT == idx_func ) + { + result = FUNCTION_CHECK_RESULT_OK; + } + else + { + switch( can_judge_status ) + { + case CAN_FUNC_CHEK_UNAVAILABLE: + DEBUG_PRINT( "CAN judge : UNAVAILABLE" ) + result = FUNCTION_CHECK_RESULT_NG; + break; + + case CAN_FUNC_CHEK_AVAILABLE: + default: /* If the default value of canjudge_status are set correctly, the default cannot be selected */ + DEBUG_PRINT( "CAN judge : AVAILABLE" ) + result = FUNCTION_CHECK_RESULT_OK; + break; + } + } + } + } + } + DEBUG_PRINTF( "RESULT = %d\n", result ) + + return result; + +#endif +} + +/* ====================================================================== */ +/* Internal function definitions */ +/* ====================================================================== */ +#ifdef VP_FUNCCHECK_CANRCV_CANRCV_ACTIVATE +/* ====================================================================== */ +/** + * @brief Get function existence in consideration of country code + * @detials Internal-use functions - Processing when CAN information availability is "Country Code" + * @param[in] idx_func Table index corresponding to the feature (takes as its argument the value after conversion to a table index, not the feature name) + * @return Availability of the feature in current vehicle parameters + */ +/* ====================================================================== */ +MT_STATIC u_int8_t getResult_CanJudge( unsigned int idx_func ) +{ + /* ====================================================================== */ + /* Internal constant definition */ + /* ====================================================================== */ + static const char MULTIPLE_COUNTRY_CODE_DESIG[] = "^[0-9]{3}(;[0-9]{3})+;{0,1}"; /**< Regular Expression String for Multiple Countries (Attributes). Make sure at least two country codes are stored / delimited */ + + /* ====================================================================== */ + /* Internal table definitions */ + /* ====================================================================== */ + /** Feature table index conversion table (country code) */ + const TABLE_INDEX_INFO TABLE_INDEX_INFO_DESTINATION[] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + { "101" , VP_FUNC_TABLE_DEST_INDEX_A }, // Detination A + { "102" , VP_FUNC_TABLE_DEST_INDEX_B } // Detination B + }; + + /** @todo The consideration. For the feature table by country code, if it can be summarized the GRADE A1/GRADE A2 and GRADE B1/GRADE B2, + It can be also summarized the translation table. + However, it must be able to guarantee that there are no differences in the table format in L/T. */ + /** Index Ttranslation Table for feature availability table (for grade A) */ + const TABLE_INDEX_INFO TABLE_INDEX_INFO_GRADE_A[] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + { "A1" , VP_FUNC_TABLE_GRADE_A1 }, // GRADE A1 + { "A2" , VP_FUNC_TABLE_GRADE_A2 } // GRADE A2 + }; + + /** Index Translation Table for feature availability table (for grade B) */ + const TABLE_INDEX_INFO TABLE_INDEX_INFO_GRADE_B[] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + { "B1" , VP_FUNC_TABLE_GRADE_B1 }, // GRADE B1 + { "B2" , VP_FUNC_TABLE_GRADE_B2 }, // GRADE B2 + }; + + /** Index Translation Table for feature availability table (brand) */ + const TABLE_INDEX_INFO TABLE_INDEX_INFO_BRAND[] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + { "A" , VP_FUNC_TABLE_BRAND_A }, // BRAND A + { "B" , VP_FUNC_TABLE_BRAND_B } // BRAND B + }; + + /* ====================================================================== */ + /** + * @brief Feature availability table for BRAND A + * @details Array of type u_int8_t accessed by the following index + */ + /* ====================================================================== */ + const u_int8_t VP_FUNC_CHECK_CANRCV_TABLE_A[ VP_FUNC_TABLE_DEST_INDEX_MAX ] + [ VP_FUNC_TABLE_GRADE_A_INDEX_MAX ] + [ VP_FUNC_TABLE_FUNCTION_INDEX_MAX ] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + /* Destination A */ + { + // Unknown , XM Audio , _CWORD27_ , Wifi HotSpot , Travel Restriction , HD Data Wifi 5G + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK }, // GRADE A1 + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK } // GRADE A2 + }, + + /* Destination B */ + { + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK }, // GRADE A1 + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_NG } // GRADE A2 + } + }; + + /* ====================================================================== */ + /** + * @brief Feature availability table for BRAND B + */ + /* ====================================================================== */ + const u_int8_t VP_FUNC_CHECK_CANRCV_TABLE_B[ VP_FUNC_TABLE_DEST_INDEX_MAX ] + [ VP_FUNC_TABLE_GRADE_B_INDEX_MAX ] + [ VP_FUNC_TABLE_FUNCTION_INDEX_MAX ] = + { + /* + * Note. + * This feature needs to be defined by the vendor. + */ + /* Destination A */ + { + // Unknown , XM Audio , _CWORD27_ , Wifi HotSpot , Travel Restriction , HD Data , Wifi 5G + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK }, // GRADE B1 + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK }, // GRADE B2 + }, + + /* Detination B */ + { + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK }, // GRADE B1 + { FUNCTION_CHECK_RESULT_UNKNOWN, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_OK, FUNCTION_CHECK_RESULT_NG, FUNCTION_CHECK_RESULT_NG }, // GRADE B2 + } + }; + + /* ====================================================================== */ + /* Table Size Definitions */ + /* ====================================================================== */ + const unsigned int SIZE_TABLE_INDEX_INFO_BRAND = ( sizeof(TABLE_INDEX_INFO_BRAND ) / sizeof( TABLE_INDEX_INFO ) ); + const unsigned int SIZE_TABLE_INDEX_INFO_GRADE_A = ( sizeof(TABLE_INDEX_INFO_GRADE_A ) / sizeof( TABLE_INDEX_INFO ) ); + const unsigned int SIZE_TABLE_INDEX_INFO_GRADE_B = ( sizeof(TABLE_INDEX_INFO_GRADE_B ) / sizeof( TABLE_INDEX_INFO ) ); + const unsigned int SIZE_TABLE_INDEX_INFO_DESTINATION = ( sizeof(TABLE_INDEX_INFO_DESTINATION) / sizeof( TABLE_INDEX_INFO ) ); + + /* ====================================================================== */ + /* Variable declarations */ + /* ====================================================================== */ + u_int8_t result = FUNCTION_CHECK_RESULT_UNKNOWN; + + VP_FCCR_BOOL isMultipleCountry = B_FALSE; + + unsigned int idx_dest = 0; + unsigned int idx_brand = 0; + unsigned int idx_grade = 0; + + char VP_destination[ VP_MAX_LENGTH ]; + char VP_brand[ VP_MAX_LENGTH ]; + char VP_grade[ VP_MAX_LENGTH ]; + + /* ====================================================================== */ + /* Static assertion */ + /* ====================================================================== */ + /* The following are expected to be identical */ + VP_DEBUG_STATIC_ASSERT( SIZE_TABLE_INDEX_INFO_BRAND == VP_FUNC_TABLE_BRAND_INDEX_MAX ) + VP_DEBUG_STATIC_ASSERT( SIZE_TABLE_INDEX_INFO_GRADE_A == VP_FUNC_TABLE_GRADE_A_INDEX_MAX ) + + /* Country code does not match because there are multiple countries. */ + VP_DEBUG_STATIC_ASSERT( VP_FUNC_TABLE_DEST_INDEX_MAX > SIZE_TABLE_INDEX_INFO_DESTINATION ) + + /* ====================================================================== */ + /* Process */ + /* ====================================================================== */ + + /* Argument check */ + if ( VP_FUNC_TABLE_FUNC_TYPE_INDEX_MAX <= idx_func ) + { + DEBUG_PRINTF( "ERROR : tebale index overed idx_func = %d\n", idx_func ) + + // Return unknown if the table size is exceeded. (However, this function can be called only from the API at the moment.) + result = FUNCTION_CHECK_RESULT_UNKNOWN; + } + else + { + + /* Get vehicle parameter */ + VP_GetEnv( VP__CWORD31__DESTINATION, &(VP_destination[0]) ); + VP_GetEnv( VEHICLEPARAMETERLIBRARY_BRAND , &(VP_brand[0]) ); + VP_GetEnv( VP_VEHICLEPARAMETERLIBRARY_GRADE , &(VP_grade[0]) ); + + DEBUG_PRINTF( "VP_destination = %s\n", VP_destination ) + + /* Append NULL at the end just in case. (so as not to cause any problems using the strlen or regcomp later) */ + VP_destination[ VP_MAX_LENGTH - 1 ] = '\0'; + VP_brand[ VP_MAX_LENGTH - 1 ] = '\0'; + VP_grade[ VP_MAX_LENGTH - 1 ] = '\0'; + + /* Check if the country code is NULL */ + if ( VP_destination[0] == '\0' ) + { + /* If NULL, set the index for the country code of the US. */ + idx_dest = VP_FUNC_TABLE_DEST_INDEX_A; + DEBUG_PRINTF( "[debug]idx_dest = %d\n", idx_dest ) + } + else + { + /* Check whether it is a member (multiple countries) */ + isMultipleCountry = hasMultipleCoutnry( &(VP_destination[0]), &(MULTIPLE_COUNTRY_CODE_DESIG[0]) ); + + /* Get the index for a country code */ + if ( B_TRUE == isMultipleCountry ) + { + /* If it is dependent (multiple countries), set the index for the country code of the dependent */ + DEBUG_PRINT( "isMultipleCountry = TRUE" ) + + idx_dest = VP_FUNC_TABLE_DEST_INDEX_B; + } + else + { + /* If it is not dependent (multiple countries), it searches the translation table and sets the index. */ + DEBUG_PRINT( "isMultipleCountry = FALSE" ) + + idx_dest = getIndexOfTable( &(VP_destination[0]), &(TABLE_INDEX_INFO_DESTINATION[0]), SIZE_TABLE_INDEX_INFO_DESTINATION, DEFAULT_TABLE_INDEX_DEST ); + } + } + DEBUG_PRINTF( "idx_dest = %d\n", idx_dest ) + + /* Get brand index */ + idx_brand = getIndexOfTable( &(VP_brand[0]) , &(TABLE_INDEX_INFO_BRAND[0]) , SIZE_TABLE_INDEX_INFO_BRAND , DEFAULT_TABLE_INDEX_BRAND ); + + /* + * Get grade index + * Setting Defaults for each brand + * e.g. The default is A, so if it is not B, it is determined to be A. + */ + if ( VP_FUNC_TABLE_BRAND_B == idx_brand ) + { + DEBUG_PRINT( "idx_brand = B") + + idx_grade = getIndexOfTable( &(VP_grade[0]) , &(TABLE_INDEX_INFO_GRADE_B[0]) , SIZE_TABLE_INDEX_INFO_GRADE_B , DEFAULT_TABLE_INDEX_GRADE_B ); + + /* Table access */ + result = VP_FUNC_CHECK_CANRCV_TABLE_B[idx_dest][idx_grade][idx_func]; + + } + else + { + DEBUG_PRINT( "idx_brand = A") + + idx_grade = getIndexOfTable( &(VP_grade[0]) , &(TABLE_INDEX_INFO_GRADE_A[0]) , SIZE_TABLE_INDEX_INFO_GRADE_A , DEFAULT_TABLE_INDEX_GRADE_A ); + + /* Table access */ + result = VP_FUNC_CHECK_CANRCV_TABLE_A[idx_dest][idx_grade][idx_func]; + + } + + //DEBUG_PRINTF( "RESULT = %d\n", result ) + } + + return result; +} + + +/* ====================================================================== */ +/** + * @brief Feature-Table Index Translation Function + * @detials Internal-use functions. It is translate the feature definition number to an index for the table. + * @param[in] Feature name defined by the func define + * @return The table index corresponding to the feature. If the given country code is invalid, return the index given by default_idx + */ + /* ====================================================================== */ +MT_STATIC unsigned int getIndexOfFunc( u_int8_t func ) +{ + /* ====================================================================== */ + /* Internal table definitions */ + /* ====================================================================== */ + /** Index translation table for feature table (Features) */ + const VP_FUNC_TABLE_FUNC_TYPE GET_INDEX_OF_FUNC[] = { + VP_FUNC_TABLE_FUNC_TYPE_INDEX_UNKNOWN , //#define VP_FUNCCHECK_CANRCV_UNKNOWN ((u_int8_t)0) /* Unknown Features */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_XM_AUDIO , //#define XM_AUDIO ((u_int8_t)1) /* XM Audio */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_VP_CANRCV__CWORD27_ , //#define _CWORD27_ ((u_int8_t)3) /* _CWORD27_ */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_HOTSPOT , //#define WIFI_HOTSPOT ((u_int8_t)4) /* WiFi HotSpot */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_RESTRICT_FUNCTION , //#define AREA1_STD_TRAF_LIMIT ((u_int8_t)5) /* Standard Travel Restriction of AREA1 */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_HD_DATA , //#define HD_DATA ((u_int8_t)6) /* HD Data (Include traffic) */ + VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_5G //#define WIFI_5G ((u_int8_t)7) /* WiFi 5G */ + + }; + + + /* ====================================================================== */ + /* Variable declarations */ + /* ====================================================================== */ + const unsigned int index_table_size = sizeof( GET_INDEX_OF_FUNC ) / sizeof( VP_FUNC_TABLE_FUNC_TYPE ); + + u_int8_t table_index = VP_FUNC_TABLE_FUNC_TYPE_INDEX_UNKNOWN; + + /* ====================================================================== */ + /* Static assertions */ + /* ====================================================================== */ + /* In the current configuration, the feature's defined value and index match, so the translation table size should also match (remove this assertion if there is no match) */ + VP_DEBUG_STATIC_ASSERT( index_table_size == VP_FUNC_TABLE_FUNCTION_INDEX_MAX ) + + /* Translation tables or the enumeration pair (VP_FUNC_TABLE_FUNC_TYPE) must also be modified when the definition value changes. + It may also be changed, added, or deleted following asserts as appropriate according to the defined value. */ + VP_DEBUG_STATIC_ASSERT( XM_AUDIO == VP_FUNC_TABLE_FUNC_TYPE_INDEX_XM_AUDIO ) + + VP_DEBUG_STATIC_ASSERT( VP_CANRCV__CWORD27_ == VP_FUNC_TABLE_FUNC_TYPE_INDEX_VP_CANRCV__CWORD27_ ) + VP_DEBUG_STATIC_ASSERT( WIFI_HOTSPOT == VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_HOTSPOT ) + VP_DEBUG_STATIC_ASSERT( AREA1_STD_TRAF_LIMIT == VP_FUNC_TABLE_FUNC_TYPE_INDEX_RESTRICT_FUNCTION ) + VP_DEBUG_STATIC_ASSERT( HD_DATA == VP_FUNC_TABLE_FUNC_TYPE_INDEX_HD_DATA ) + VP_DEBUG_STATIC_ASSERT( WIFI_5G == VP_FUNC_TABLE_FUNC_TYPE_INDEX_WIFI_5G ) + + + /* ====================================================================== */ + /* Process */ + /* ====================================================================== */ + + /* Argument check: Treat as unknown feature if it is larger than index translation table */ + if ( index_table_size <= func ) + { + table_index = VP_FUNC_TABLE_FUNC_TYPE_INDEX_UNKNOWN; + } + else + { + table_index = (u_int8_t)(GET_INDEX_OF_FUNC[func]); + } + + return table_index; + +} + +/* ====================================================================== */ +/** + * @brief Vehicle parameter string to integer conversion function + * @detials Internal-use function. Convert the given string (vehicle parameter) into an index for the table. + * The value gotten using VP_GetEnv() is assumed. Thus, the maximum length is VP_MAX_LENGTH. + * Return the value set in default_index if the conversion is failed. + * @param[in] vp_param_str String as source of convetion to the table index + * @param[in] table_index_info String corresponding to table index and an array of structs with table indexes set + * @param[in] info_size Size of the table_index_info array + * @param[in] default_index Default index. Return this value if none of table_index_info matches + * @return The table index corresponding to the vehicle parameter string given by the argument. Return the value given by the default_index argument if the given country code is invalid. + */ + /* ====================================================================== */ +MT_STATIC unsigned int getIndexOfTable( const char vp_param_str[], const TABLE_INDEX_INFO table_index_info[], unsigned int info_size, unsigned int default_index ) +{ + unsigned int table_index = 0; + + table_index = default_index; /* Set as initial value so that it can return the set default if it is unknown */ + + //DEBUG_PRINTF("info_size = %d\n", info_size) + + /* NULL checking */ + if ( NULL != vp_param_str ) + { + if ( NULL != table_index_info ) + { + unsigned int i = 0; + + for ( i = 0; i < info_size; i++ ) + { + if ( RET_STD_LIB_STRING_STR_CMP_OK == strncmp( &(vp_param_str[0]), &((table_index_info[i]).code_str[0]), VP_MAX_LENGTH ) ) + { + table_index = (table_index_info[i]).index; + + break; + } + } + } + else + { + DEBUG_PRINT( "ERROR!! the Bad Teble overd." ) + } + } + + return table_index; +} + +/* ====================================================================== */ +/** + * @brief Function to check whether country code is multiple countries or not + * @detials Internal-use functions. Check if the country code given in the argument contains more than one country. + * The determination whether multiple country code or not shall be true if it exactly matches the specified + * regular expression which is a characteristic of multiple countries. + * The exact match determination shall be the exact match if the length of the matched character matches + * the length of the character passed in the argument. + * @param[in] dest_str Country code string. The value gotten using VP_GetEnv() is assumed. Therefore, the maximum length is VP_MAX_LENGTH. + * @param[in] multiple_country_code_desig String for determining multiple country codes. Regular expression strings if a regular expression library is used. Otherwise, a single-character string representing the delimiter. + * If it gets trapped inside a function, it will have to stub the regcomp during function unit tests, which is very cumbersome and can be removed as arguments. + * @return True if country code indicates multiple countries, otherwise false + */ +/* ====================================================================== */ +MT_STATIC VP_FCCR_BOOL hasMultipleCoutnry( const char dest_str[], const char multiple_country_code_desig[] ) +{ + /* ====================================================================== */ + /* Variable declarations */ + /* ====================================================================== */ + VP_FCCR_BOOL isMultiple = B_FALSE; + + /* ====================================================================== */ + /* Processing */ + /* ====================================================================== */ + + /* NULL checking for arguments */ + if ( ( NULL != dest_str ) && ( NULL != multiple_country_code_desig ) ) + { + regex_t preg; + + if ( 0 == regcomp( &preg, multiple_country_code_desig, REG_EXTENDED ) ) + { + regmatch_t pmatch = { 0, 0 }; + + if ( REG_NOMATCH != regexec( &preg, &(dest_str[0]), 1, &pmatch, 0) ) + { + /** @note Exactly match is considered if the end-of-match offset matches the string length. + * Assumed that it should not be used as the end-of-line character so that "$" is not included in the C base character set. + */ + if ( (strnlen( dest_str, VP_MAX_LENGTH ) == (unsigned int)(pmatch.rm_eo) ) ) + { + isMultiple = B_TRUE; + } + else + { + isMultiple = B_FALSE; + } + + DEBUG_PRINT( "FOUND" ) + } + else + { + isMultiple = B_FALSE; + + DEBUG_PRINT( "NOT FOUND" ) + } + + regfree( &preg ); + } + else + { + /* In the case of a library error, + * return false so that the default value that is set by high layer works. + */ + + /** @todo Should output using FRAMEWORKUNIFIEDLOG for library errors? */ + isMultiple = B_FALSE; + + DEBUG_PRINT( "FOUND" ) + } + } + + return isMultiple; + +} +#endif diff --git a/otherservice/vehicle_parameter_library/library/src/VP_GetEnv.c b/otherservice/vehicle_parameter_library/library/src/VP_GetEnv.c new file mode 100755 index 0000000..c6cd6a7 --- /dev/null +++ b/otherservice/vehicle_parameter_library/library/src/VP_GetEnv.c @@ -0,0 +1,291 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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. + */ + +/* ====================================================================== */ +/** + * @file VP_GetEnv.c + * @brief API to get vehicle parameter environment variable + */ +/* ====================================================================== */ + + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <other_service/VP_GetEnv.h> +#include <native_service/ns_backup.h> +#include <native_service/ns_backup_id.h> + +#include "VP_FuncCheck_CanRcv_private.h" + +// copy from vpsvc.h +#define VPSVC_COUNTRY_MAX (0x10) // Maximal number of country codes for 1 destination + +// copy from VehicleSens_Vpupdate.cpp + +#define VP_VEHICLEPARAMETERLIBRARY_DEST_LEN_MIN 5 // At least 5 characters for 1 destination(e.g. "I:104") +#define VP_VEHICLEPARAMETERLIBRARY_DEST_NUM_MAX (VP_MAX_LENGTH/VP_VEHICLEPARAMETERLIBRARY_DEST_LEN_MIN) +#define DS_PACK2_LEN_MAX 2+1 // Max. digits of destination package 2(+\0) + +typedef struct { + char dest_bdb[2]; // Destination symbol + char ds_pack2[DS_PACK2_LEN_MAX]; // Destination package 2 + uint8_t coutry_num; // Number of Country Codes + uint16_t country_no[VPSVC_COUNTRY_MAX]; // Country Code +} VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE_t; + +VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE_t g_vp_vehicleparameterlibrary_dest[VP_VEHICLEPARAMETERLIBRARY_DEST_NUM_MAX]; // Destination information get from environment variables +static uint32_t g_vp_vehicleparameterlibrary_dest_num; // Number of destination information get from environment variables + +static void AnalyzeVpVehicleparameterlibraryDestEnv(void) { + char p_env_variable[VP_MAX_LENGTH] = {}; + char dest_buf[VP_MAX_LENGTH] = { 0 }; // Destination data for environment variables + char *c_code_ascii; // Country Code(ASCII) + char *dest_bdb_buf; // Destination symbol + uint32_t dest_num = 0; // Number of destinations + int country_num = 0; // Number of Country Codes per Destination + char *token1, *saveptr1; // Destination break token + char *token2, *saveptr2; // Delimiter tokens in each destination + VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE_t *p_dest; + uint16_t *p_country; + + g_vp_vehicleparameterlibrary_dest_num = 0; + memset(&g_vp_vehicleparameterlibrary_dest, 0x00, sizeof(VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE_t)); + + // Get environment variables + VP_GetEnv(VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE, p_env_variable); + if (0 == strncmp(p_env_variable, "", VP_MAX_LENGTH)) { + DEBUG_PRINT("VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE is NULL"); + return; + } + + DEBUG_PRINTF("VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE=[%s]\n", p_env_variable); + + // Begin analysis First, separate with "," + token1 = strtok_r(p_env_variable, ",", &saveptr1); + while (token1 != NULL) { + snprintf(dest_buf, VP_MAX_LENGTH, "%s", token1); + DEBUG_PRINTF("dest_buf\t[%s]", dest_buf); + p_dest = &g_vp_vehicleparameterlibrary_dest[dest_num]; + + // Get the country code 000-999 + country_num = 0; + c_code_ascii = strchr(dest_buf, (int32_t)(':')); + if (c_code_ascii != NULL) { + c_code_ascii += 1; + token2 = strtok_r(c_code_ascii, "/", &saveptr2); + while (token2 != NULL) { + p_country = &(p_dest->country_no[country_num]); + errno = 0; + long int val = strtol(token2, (char **)NULL, 10); + if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) + || (errno != 0 && val == 0)) { + DEBUG_PRINTF("country No format error [%s]", token2); + return; + } + *p_country = (uint16_t)val; + + if (country_num >= VPSVC_COUNTRY_MAX) { + DEBUG_PRINTF("country num over [%s]", token2); + return; + } + country_num++; + token2 = strtok_r(NULL, "/", &saveptr2); + } + p_dest->coutry_num = (uint8_t)(country_num); + DEBUG_PRINTF("country_num\t[%d]", country_num); + } + + // Get destination symbol (may not be available) + dest_bdb_buf = strchr(dest_buf, (int32_t)('&')); + if (dest_bdb_buf != NULL) { + p_dest->dest_bdb[0] = *(dest_bdb_buf + 1); + DEBUG_PRINTF("dest_bdb\t[%s]", p_dest->dest_bdb); + } else { + DEBUG_PRINT("dest_bdb is noting"); + } + + // Get destination packages + token2 = strtok_r(dest_buf, "&:", &saveptr2); + snprintf(p_dest->ds_pack2, DS_PACK2_LEN_MAX, "%s", token2); + DEBUG_PRINTF("ds_pack2\t[%s]\n", p_dest->ds_pack2); + + dest_num++; + token1 = strtok_r(NULL, ",", &saveptr1); + } + + g_vp_vehicleparameterlibrary_dest_num = dest_num; +} + +// based VP_DspackToCountryCode +// dest [in] Destination codes read from the bkup_manager +// country_code [out] Country code string, separated by ";" for multi-country codes +static BOOL VP_DspackToCountryCode(uint8_t* dest, char *country_code) { + BOOL ret = FALSE; + VP_VEHICLEPARAMETERLIBRARY_DEST_C_CODE_t *p; + typedef struct { + char dest_bdb[2]; // Destination symbol + char ds_pack2[DS_PACK2_LEN_MAX]; // Destination package 2 + } VEHICLE_CAN_DEST_t; + VEHICLE_CAN_DEST_t can_dest = {}; + + AnalyzeVpVehicleparameterlibraryDestEnv(); + + // Setting CAN data + can_dest.dest_bdb[0] = (int8_t)dest[0]; // Get destination symbol + + if (isalpha(dest[2]) != 0) { // Get destination packages + can_dest.ds_pack2[0] = (int8_t)dest[2]; + } else { + DEBUG_PRINTF("ds_pack2 is neither Alpha character[%c]", (int32_t)dest[2]); + return ret; + } + + // Comparison with vehicle parameter + for (uint32_t i = 0; i < g_vp_vehicleparameterlibrary_dest_num; i++) { + p = &g_vp_vehicleparameterlibrary_dest[i]; + // Determination of destination packages + if (strncmp(p->ds_pack2, can_dest.ds_pack2, sizeof(can_dest.ds_pack2)) != 0) { + continue; + } + + // Determination of destination symbol + if (p->dest_bdb[0] == 0) { + ret = TRUE; // When the destination code judgment is not required + break; + } + + if (strncmp(p->dest_bdb, can_dest.dest_bdb, sizeof(can_dest.dest_bdb)) == 0) { + ret = TRUE; + break; + } + } + + // Returned as a country code string + if (ret == TRUE) { + snprintf(country_code, VP_MAX_LENGTH, "%03d", p->country_no[0]); + for (uint32_t i = 1; i < p->coutry_num; i++) { + char buf[VP_MAX_LENGTH] = {}; + snprintf(buf, VP_MAX_LENGTH, "%s;%03d", country_code, p->country_no[i]); + strncpy(country_code, buf, VP_MAX_LENGTH); + } + } + return ret; +} +// end of copy from VehicleSens_Vpupdate.cpp + +// copy from vehicle unit +typedef struct { + uint8_t uc_hv; /* hv */ + uint8_t uc_hv_status; /* hv status */ + uint8_t uc_2wd4wd; /* 2wd4wd */ + uint8_t uc_2wd4wd_status; /* 2wd4wd status */ + uint8_t uc_dest[3]; /* Destination */ + uint8_t uc_dest_status; /* Destination status */ + uint8_t uc_stwheel; /* STEERING_WHEEL */ + uint8_t uc_stwheel_status; /* STEERING_WHEEL status */ + uint8_t uc_reserve[6]; /* Reserve */ +} VEHICLESENS_NON_VOLATILE_DATA; + +/* ====================================================================== */ +/** + * @fn + * void VP_GetVp_CWORD31_Destination(char *pEnvBuff) + * @breaf Get environment variables + * @param[out] (pEnvBuff) Start address of the area to store the get environment variable value + * @return None + * @detail Read and analyze D_BK_ID_VEHICLE_STABLE_DATA from BackupManager. + * The country code string is stored in the argument and returned. + */ +/* ====================================================================== */ +static void VP_GetVp_CWORD31_Destination(char *pEnvBuff) +{ + int32_t ret_api = BKUP_RET_NORMAL; + VEHICLESENS_NON_VOLATILE_DATA pstback_up_data; + memset(&pstback_up_data, 0x00, sizeof(VEHICLESENS_NON_VOLATILE_DATA)); + char env_string[VP_MAX_LENGTH]; + + VP_GetEnv(VP__CWORD31__TELEMATICS_FUNCTION, env_string); + + if ('\0' == env_string[0]) { + *pEnvBuff = '\0'; + return; + } else { + // read from backup + ret_api = Backup_DataRd(D_BK_ID_VEHICLE_STABLE_DATA, + 0, + &pstback_up_data, + sizeof(VEHICLESENS_NON_VOLATILE_DATA)); + if (BKUP_RET_NORMAL != ret_api) { + *pEnvBuff = '\0'; + return; + } + } + + if (0 == strncmp(env_string, "country_ID", strlen("country_ID"))) { + uint32_t country_code = 0; + country_code += (pstback_up_data.uc_dest[1]); // countory_code 3rd and 2nd digit + country_code = (country_code << 4); // shift + country_code += (pstback_up_data.uc_dest[2] >> 4); // countory_code 1st digit + snprintf(pEnvBuff, VP_MAX_LENGTH, "%x", country_code); + } else if(0 == strncmp(env_string, "CAN_judge", strlen("CAN_judge"))) { + VP_DspackToCountryCode(pstback_up_data.uc_dest, pEnvBuff); + } else { + *pEnvBuff = '\0'; + } +} + +/* ====================================================================== */ +/** + * @fn + * void VP_GetEnv(char *pEnvStr, char *pEnvBuff ) + * @breaf Get Environment Variable + * @param[in] (pEnvStr) Pointer to the string of the environment variable name to be gotten + * @param[out] (pEnvBuff) Start address of the area to store the gotten value of the environment variable + * @return None + * @detail Read the value (string) of the environment variable specified by the argument and stores it in the specified address. + */ +/* ====================================================================== */ +void VP_GetEnv(const char *pEnvStr, char *pEnvBuff ) +{ + const char *env_string; + size_t length; + + if ((pEnvStr != NULL) && (pEnvBuff != NULL)) { + if (0 == strncmp(pEnvStr, VP__CWORD31__DESTINATION, strlen(VP__CWORD31__DESTINATION))) { + VP_GetVp_CWORD31_Destination(pEnvBuff); + } else { + env_string = getenv(pEnvStr); + + if (env_string == NULL) { + *pEnvBuff = '\0'; + } else { + length = strlen( env_string ); + if (length < ((size_t)VP_MAX_LENGTH)) { + (void)strcpy(pEnvBuff, env_string); + } else { + (void)strncpy(pEnvBuff, env_string, (VP_MAX_LENGTH - 1)); + pEnvBuff[ VP_MAX_LENGTH - 1 ] = '\0'; + } + } + } + } else { + if(pEnvBuff != NULL) { + *pEnvBuff = '\0'; + } + } +} |