diff --git a/doc/rst/configuration.rst b/doc/rst/configuration.rst index 1b169bb224..3c361e3db9 100644 --- a/doc/rst/configuration.rst +++ b/doc/rst/configuration.rst @@ -14,3 +14,4 @@ Configuration configuration/npcap configuration/player configuration/options + configuration/runtime_configuration diff --git a/doc/rst/configuration/runtime_configuration.rst b/doc/rst/configuration/runtime_configuration.rst new file mode 100644 index 0000000000..5c62120e76 --- /dev/null +++ b/doc/rst/configuration/runtime_configuration.rst @@ -0,0 +1,68 @@ +.. include:: /include.txt + +.. _configuration_runtime_configuration: + +===================== +Runtime configuration +===================== + +eCAL provides an interface to access and modify its options before initialization. +The corresponding structure reflects the configuration file (:ref:`configuration_options`). + +Custom types +============ + +In order to rule out configuration errors, custom datatypes for IP addresses (IpAddressV4) and sizes (constrained integer) are introduced. + +**IpAddressV4:** For assigning an IP address simply assign a string with the desired address. +Decimal and hexadecimal format is supported. +In case the IP address is not valid, the type will throw a std::invalid_argument exception. + +The IP address can be used like a normal string object. For example: + +.. code-block:: c++ + + eCAL::Types::IpAddressV4 ip_address = std::string("192.168.7.1"); // in hex: "C0.A8.7.1" + std::cout << ip_address << "\n"; + +**ConstrainedInteger**: ConstrainedInteger are specified with a minimum (default: 0), step (default: 1) and maximum (default: maximum of int) value. +In case the assigned value does not fit into the specified limitation, the type will throw a std::invalid_argument exception. + +The size object can be used like a normal integer. + +.. code-block:: c++ + + eCAL::Types::ConstrainedInteger<1024, 512, 8192> size_4mb = 1024 + 6 * 512; + std::cout << size_4mb << "\n"; + +For specifying sizes in the ecal configuration object, refer to the .ini file or "ecal/config/configuration.h" for the limitations. + +Global configuration initialization +=================================== + +The configuration will be first initialized with the default values specified by eCAL. +If you want to use the systems eCAL .ini file, call the ``InitConfigWithDefaultIni()`` function of the config object. + +In case the .ini to use is specified via command line parameter, this one is chosen instead. +The object will throw an error, in case the specified .ini file cannot be found. + +It is also possible to specify the .ini by calling the function ``InitConfig(std::string _ini_path)`` of the config object. + +* |fa-file-alt| :file:`hello_config/main.cpp`: + + .. literalinclude:: src/hello_config/main.cpp + :language: cpp + :linenos: + +Individual publisher/subscriber configuration +============================================= + +Like a global configuration to pass at initialization, it is also possible to create indiviual configurations for publisher and subscriber. +That means it is possible to, e.g., create two publisher which send on different transport layers: + +* |fa-file-alt| :file:`publisher/main.cpp`: + + .. literalinclude:: src/publisher_config/main.cpp + :language: cpp + :linenos: + diff --git a/doc/rst/configuration/src/hello_config/CMakeLists.txt b/doc/rst/configuration/src/hello_config/CMakeLists.txt new file mode 100644 index 0000000000..dd21b4264e --- /dev/null +++ b/doc/rst/configuration/src/hello_config/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.0) +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) + +project(hello_config) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(eCAL REQUIRED) + +set(source_files + main.cpp +) + +add_executable(${PROJECT_NAME} ${source_files}) + +target_link_libraries(${PROJECT_NAME} + eCAL::core +) \ No newline at end of file diff --git a/doc/rst/configuration/src/hello_config/main.cpp b/doc/rst/configuration/src/hello_config/main.cpp new file mode 100644 index 0000000000..68a4967ad1 --- /dev/null +++ b/doc/rst/configuration/src/hello_config/main.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + // Create a configuration object with the command line arguments + eCAL::Configuration custom_config(argc, argv); + + // Use the .ini file of the system if available + custom_config.InitConfigWithDefaultIni(); + + // Set the values in a try/catch block, as wrong configuration leads to exceptions + try + { + // In case you decided to specify an own .ini file to use + // Configuration based on previous ini file will be overwritten + custom_config.InitConfig("C:\\eCAL_local.ini"); + + // Set the communication layer to network + custom_config.transport_layer.network_enabled = true; + + // Set a custom udp multicast group, correct IP address necessary + custom_config.transport_layer.mc_options.group = std::string("239.0.1.1"); + + // Increase the send buffer, size increase in 1024 bytes steps + custom_config.transport_layer.mc_options.sndbuf = (5242880 + 10 * 1024); + } + catch (std::invalid_argument& e) + { + throw std::runtime_error("Error while configuring eCALConfig: " + std::string(e.what())); + } + + // Initialize eCAL with the prepared configuration object + eCAL::Initialize(custom_config, "UserConfigExample", eCAL::Init::Default); + + // ... + // Use eCAL for your needs + // ... + + // Finalize eCAL API + eCAL::Finalize(); + + return 0; +} \ No newline at end of file diff --git a/doc/rst/configuration/src/publisher_config/CMakeLists.txt b/doc/rst/configuration/src/publisher_config/CMakeLists.txt new file mode 100644 index 0000000000..53f8f8fc47 --- /dev/null +++ b/doc/rst/configuration/src/publisher_config/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.0) +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) + +project(publisher_config) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(eCAL REQUIRED) + +set(source_files + main.cpp +) + +add_executable(${PROJECT_NAME} ${source_files}) + +target_link_libraries(${PROJECT_NAME} + eCAL::core +) \ No newline at end of file diff --git a/doc/rst/configuration/src/publisher_config/main.cpp b/doc/rst/configuration/src/publisher_config/main.cpp new file mode 100644 index 0000000000..c3cea80141 --- /dev/null +++ b/doc/rst/configuration/src/publisher_config/main.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "PublisherConfig", eCAL::Init::All); + + // create publisher config + eCAL::Publisher::Configuration pub_config; + + // disable all layers except for SHM + pub_config.shm.enable = true; + pub_config.udp.enable = false; + pub_config.tcp.enable = false; + + // create publisher 1 + eCAL::string::CPublisher pub_1("topic_1", pub_config); + + // enable for the second publisher also tcp + pub_config.tcp.enable = true; + + // create publisher 2 + eCAL::string::CPublisher pub_2("topic_2", pub_config); + + int counter {0}; + while (eCAL::Ok()) + { + std::string msg = "Send message number: " + std::to_string(counter++); + + // send message + pub_1.Send(msg); + pub_2.Send(msg); + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + + // finalize eCAL API + eCAL::Finalize(); +} \ No newline at end of file diff --git a/ecal/core/CMakeLists.txt b/ecal/core/CMakeLists.txt index 33caca1dda..699efdd52c 100644 --- a/ecal/core/CMakeLists.txt +++ b/ecal/core/CMakeLists.txt @@ -63,10 +63,14 @@ endif() # config ###################################### set(ecal_config_src + src/config/ecal_cmd_parser.cpp src/config/ecal_config.cpp + src/config/ecal_config_initializer.cpp src/config/ecal_config_reader.cpp src/config/ecal_config_reader.h src/config/ecal_config_reader_hlp.h + src/types/ecal_custom_data_types.cpp + src/types/ecal_registration_options.cpp ) ###################################### @@ -450,10 +454,11 @@ endif() set(ecal_header_cmn include/ecal/types/logging.h include/ecal/types/monitoring.h + include/ecal/config/publisher.h + include/ecal/config/subscriber.h include/ecal/ecal.h include/ecal/ecal_callback.h include/ecal/ecal_client.h - include/ecal/ecal_config.h include/ecal/ecal_core.h include/ecal/ecal_deprecate.h include/ecal/ecal_init.h @@ -465,16 +470,15 @@ set(ecal_header_cmn include/ecal/ecal_process.h include/ecal/ecal_process_severity.h include/ecal/ecal_publisher.h - include/ecal/ecal_publisher_config.h include/ecal/ecal_server.h include/ecal/ecal_service_info.h include/ecal/ecal_subscriber.h - include/ecal/ecal_subscriber_config.h include/ecal/ecal_time.h include/ecal/ecal_timer.h include/ecal/ecal_tlayer.h include/ecal/ecal_types.h include/ecal/ecal_util.h + include/ecal/config/configuration.h ) set(ecal_header_cimpl diff --git a/ecal/core/cfg/ecal.ini b/ecal/core/cfg/ecal.ini index f474579552..1fb5a73896 100644 --- a/ecal/core/cfg/ecal.ini +++ b/ecal/core/cfg/ecal.ini @@ -178,7 +178,7 @@ filter_excl = ^eCALSysClient$|^eCALSysGUI$|^eCALSys$ ; shm_monitoring_enabled = false Enable distribution of monitoring/registration information via shared memory ; shm_monitoring_domain = ecal_monitoring Domain name for shared memory based monitoring/registration ; shm_monitoring_queue_size = 1024 Queue size of monitoring/registration events -; network_monitoring_disabled = false Disable distribution of monitoring/registration information via network +; network_monitoring_enabled = true Enable distribution of monitoring/registration information via network ; ; drop_out_of_order_messages = false Enable dropping of payload messages that arrive out of order ; -------------------------------------------------- @@ -186,5 +186,5 @@ filter_excl = ^eCALSysClient$|^eCALSysGUI$|^eCALSys$ shm_monitoring_enabled = false shm_monitoring_domain = ecal_mon shm_monitoring_queue_size = 1024 -network_monitoring_disabled = false +network_monitoring_enabled = true drop_out_of_order_messages = false diff --git a/ecal/core/include/ecal/config/application.h b/ecal/core/include/ecal/config/application.h new file mode 100644 index 0000000000..e08367a24a --- /dev/null +++ b/ecal/core/include/ecal/config/application.h @@ -0,0 +1,57 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_application_config.h + * @brief eCAL configuration for applications +**/ + +#pragma once + +#include +#include +#include + +namespace eCAL +{ + namespace Application + { + namespace Sys + { + struct Configuration + { + std::string filter_excl; //!< + }; + } + + namespace Startup + { + struct Configuration + { + std::string terminal_emulator; //!< + }; + } + + struct Configuration + { + Sys::Configuration sys; //!< + Startup::Configuration startup; //!< + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/config/configuration.h b/ecal/core/include/ecal/config/configuration.h new file mode 100644 index 0000000000..101c890dea --- /dev/null +++ b/ecal/core/include/ecal/config/configuration.h @@ -0,0 +1,80 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file configuration.h + * @brief eCAL configuration interface +**/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "ecal/ecal_os.h" +#include "ecal/ecal_log_level.h" + +#include +#include +#include +#include + +namespace eCAL +{ + struct Configuration + { + TransportLayer::Configuration transport_layer{}; + Registration::Configuration registration{}; + Monitoring::Configuration monitoring{}; + Subscriber::Configuration subscriber{}; + Publisher::Configuration publisher{}; + Time::Configuration timesync{}; + Service::Configuration service{}; + Application::Configuration application{}; + Logging::Configuration logging{}; + Cli::Configuration command_line_arguments{}; + + ECAL_API Configuration(); + ECAL_API Configuration(int argc_ , char **argv_); + ECAL_API Configuration(std::vector& args_); + + ECAL_API void InitConfigWithDefaultIni(); + ECAL_API void InitConfig(std::string ini_path_ = std::string("")); + + ECAL_API std::string GetIniFilePath(); + + friend class CmdParser; + + protected: + std::string ecal_ini_file_path{}; + + private: + ECAL_API void Init(std::vector& args_); + }; +} \ No newline at end of file diff --git a/ecal/core/include/ecal/config/logging.h b/ecal/core/include/ecal/config/logging.h new file mode 100644 index 0000000000..bb1ae9ef45 --- /dev/null +++ b/ecal/core/include/ecal/config/logging.h @@ -0,0 +1,41 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_logging_config.h + * @brief eCAL configuration for logging +**/ + +#pragma once + +#include + +namespace eCAL +{ + namespace Logging + { + struct Configuration + { + eCAL_Logging_Filter filter_log_con{}; /*!< Log messages logged to console (all, info, warning, error, fatal, debug1, debug2, debug3, debug4) + (Default: info, warning, error, fatal)*/ + eCAL_Logging_Filter filter_log_file{}; //!< Log messages to logged into file system (Default: "") + eCAL_Logging_Filter filter_log_udp{}; //!< Log messages logged via udp network (Default: info, warning, error, fatal) + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/config/monitoring.h b/ecal/core/include/ecal/config/monitoring.h new file mode 100644 index 0000000000..2c116202ff --- /dev/null +++ b/ecal/core/include/ecal/config/monitoring.h @@ -0,0 +1,73 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_monitoring_config.h + * @brief eCAL configuration for monitoring +**/ + +#pragma once + +#include + +namespace eCAL +{ + namespace Monitoring + { + namespace Types + { + enum Mode + { + none = 0, + udp_monitoring = 1 << 0, + shm_monitoring = 1 << 1 + }; + + using Mode_Filter = char; + } + + namespace UDP + { + struct Configuration + { + }; + } + + namespace SHM + { + struct Configuration + { + std::string shm_monitoring_domain{}; //!< Domain name for shared memory based monitoring/registration (Default: ecal_mon) + size_t shm_monitoring_queue_size{}; //!< Queue size of monitoring/registration events (Default: 1024) + }; + } + + struct Configuration + { + Types::Mode_Filter monitoring_mode{}; //!< Specify which monitoring is enabled (Default: none) + eCAL::Types::ConstrainedInteger<1000, 1000> monitoring_timeout{}; //!< Timeout for topic monitoring in ms (Default: 5000) + bool network_monitoring{}; //!< Enable distribution of monitoring/registration information via network (Default: true) + UDP::Configuration udp_options{}; + SHM::Configuration shm_options{}; + + std::string filter_excl{}; //!< Topics blacklist as regular expression (will not be monitored) (Default: "__.*") + std::string filter_incl{}; //!< Topics whitelist as regular expression (will be monitored only) (Default: "") + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/ecal_publisher_config.h b/ecal/core/include/ecal/config/publisher.h similarity index 76% rename from ecal/core/include/ecal/ecal_publisher_config.h rename to ecal/core/include/ecal/config/publisher.h index a54cf62a29..1af155c9b3 100644 --- a/ecal/core/include/ecal/ecal_publisher_config.h +++ b/ecal/core/include/ecal/config/publisher.h @@ -18,7 +18,7 @@ */ /** - * @file ecal_publisher_config.h + * @file publisher.h * @brief eCAL publisher configuration * * This publisher configuration struct can be used to define the behavior of an eCAL publisher. Additional information on @@ -89,6 +89,7 @@ #pragma once #include +#include #include @@ -98,46 +99,46 @@ namespace eCAL { namespace SHM { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer - bool zero_copy_mode = false; //!< enable zero copy shared memory transport mode - int acknowledge_timeout_ms = 0; /*!< force connected subscribers to send acknowledge event after processing the message - the publisher send call is blocked on this event with this timeout (0 == no handshake) */ - size_t memfile_min_size_bytes = 4096; //!< default memory file size for new publisher - size_t memfile_reserve_percent = 50; //!< dynamic file size reserve before recreating memory file if topic size changes - size_t memfile_buffer_count = 1; //!< maximum number of used buffers (needs to be greater than 1, default = 1) + bool enable; //!< enable layer + bool zero_copy_mode; //!< enable zero copy shared memory transport mode + unsigned int acknowledge_timeout_ms; /*!< force connected subscribers to send acknowledge event after processing the message + the publisher send call is blocked on this event with this timeout (0 == no handshake) */ + Types::ConstrainedInteger<4096, 4096> memfile_min_size_bytes; //!< default memory file size for new publisher + Types::ConstrainedInteger<50, 1, 100> memfile_reserve_percent; //!< dynamic file size reserve before recreating memory file if topic size changes + Types::ConstrainedInteger<1, 1> memfile_buffer_count; //!< maximum number of used buffers (needs to be greater than 1, default = 1) }; } namespace UDP { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer - bool loopback = false; //!< enable to receive udp messages on the same local machine - int sndbuf_size_bytes = (5*1024*1024); //!< udp send buffer size in bytes (default 5MB) + bool enable; //!< enable layer + bool loopback; //!< enable to receive udp messages on the same local machine + Types::ConstrainedInteger<5242880, 1024> sndbuf_size_bytes; //!< udp send buffer size in bytes (default 5MB) }; } namespace TCP { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer + bool enable; //!< enable layer }; } - struct ECAL_API Configuration + struct Configuration { - Configuration(); + ECAL_API Configuration(); SHM::Configuration shm; UDP::Configuration udp; TCP::Configuration tcp; - bool share_topic_type = true; //!< share topic type via registration - bool share_topic_description = true; //!< share topic description via registration + bool share_topic_type; //!< share topic type via registration + bool share_topic_description; //!< share topic description via registration }; } } diff --git a/ecal/core/include/ecal/config/registration.h b/ecal/core/include/ecal/config/registration.h new file mode 100644 index 0000000000..46c88f5b0d --- /dev/null +++ b/ecal/core/include/ecal/config/registration.h @@ -0,0 +1,64 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_registration_config.h + * @brief eCAL configuration for the registration layer +**/ + +#pragma once + +#include "ecal/ecal_os.h" + +#include +#include + +namespace eCAL +{ + namespace Registration + { + /** + * @brief Struct for storing RegistrationOptions. + * If not specified, registration timeout and refresh times from eCAL predefines will be used. + * When specifying: reg_timeout >= reg_refresh. If not, an invalid_argument exception will be thrown. + * By default, share_ttype and share_tdesc is true based on eCAL predefines. + * + * @param reg_timeout_ Timeout for topic registration in ms + * @param reg_refresh_ Topic registration refresh cylce in ms + * + * @throws std::invalid_argument exception. + **/ + struct Configuration + { + public: + ECAL_API Configuration(); + ECAL_API Configuration(unsigned int reg_timeout_, unsigned int reg_refresh_); + + ECAL_API unsigned int getTimeoutMS() const; //!< Timeout for topic registration in ms (internal) (Default: 60000) + ECAL_API unsigned int getRefreshMS() const; //!< Topic registration refresh cylce (has to be smaller then registration timeout!) (Default: 1000) + + bool share_ttype; //!< Share topic type via registration layer (Default: true) + bool share_tdesc; //!< Share topic description via registration layer (switch off to disable reflection) (Default: true) + + private: + unsigned int m_registration_timeout; + unsigned int m_registration_refresh; + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/config/service.h b/ecal/core/include/ecal/config/service.h new file mode 100644 index 0000000000..74f4b54291 --- /dev/null +++ b/ecal/core/include/ecal/config/service.h @@ -0,0 +1,39 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_service_config.h + * @brief eCAL configuration for services +**/ + +#pragma once + +#include + +namespace eCAL +{ + namespace Service + { + struct Configuration + { + bool protocol_v0{}; //!< Support service protocol v0, eCAL 5.11 and older (Default: true) + bool protocol_v1{}; //!< Support service protocol v1, eCAL 5.12 and newer (Default: true) + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/ecal_subscriber_config.h b/ecal/core/include/ecal/config/subscriber.h similarity index 75% rename from ecal/core/include/ecal/ecal_subscriber_config.h rename to ecal/core/include/ecal/config/subscriber.h index 5e2221c820..d306250d43 100644 --- a/ecal/core/include/ecal/ecal_subscriber_config.h +++ b/ecal/core/include/ecal/config/subscriber.h @@ -34,31 +34,31 @@ namespace eCAL { namespace SHM { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer + bool enable; //!< enable layer }; } namespace UDP { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer + bool enable; //!< enable layer }; } namespace TCP { - struct ECAL_API Configuration + struct Configuration { - bool enable = false; //!< enable layer + bool enable; //!< enable layer }; } - struct ECAL_API Configuration + struct Configuration { - Configuration(); + ECAL_API Configuration(); SHM::Configuration shm; UDP::Configuration udp; diff --git a/ecal/core/include/ecal/config/time.h b/ecal/core/include/ecal/config/time.h new file mode 100644 index 0000000000..dbe62028c3 --- /dev/null +++ b/ecal/core/include/ecal/config/time.h @@ -0,0 +1,47 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @file time.h + * @brief eCAL time configuration +**/ + +#pragma once + +#include + +namespace eCAL +{ + namespace Time + { + struct Configuration + { + std::string timesync_module_rt{}; /*!< Time synchronisation interface name (dynamic library) + The name will be extended with platform suffix (32|64), debug suffix (d) and platform extension (.dll|.so) + Available modules are: + - ecaltime-localtime local system time without synchronization + - ecaltime-linuxptp For PTP / gPTP synchronization over ethernet on Linux + (device configuration in ecaltime.ini) + (Default: ecaltime-localtime)*/ + std::string timesync_module_replay{}; //!< (Default: "") + }; + } +} + + diff --git a/ecal/core/include/ecal/config/transport_layer.h b/ecal/core/include/ecal/config/transport_layer.h new file mode 100644 index 0000000000..41aa5ad5ae --- /dev/null +++ b/ecal/core/include/ecal/config/transport_layer.h @@ -0,0 +1,94 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file transport_layer.h + * @brief eCAL configuration for the transport layer +**/ + +// TODO PG: Deprecated when configuration is implemented in all modules? +#pragma once + +#include + +namespace eCAL +{ + namespace TransportLayer + { + namespace TCPPubSub + { + struct Configuration + { + size_t num_executor_reader{}; //!< Tcp_pubsub reader amount of threads that shall execute workload (Default: 4) + size_t num_executor_writer{}; //!< Tcp_pubsub writer amount of threads that shall execute workload (Default: 4) + size_t max_reconnections{}; //!< Tcp_pubsub reconnection attemps the session will try to reconnect in (Default: 5) + }; + } + + namespace SHM + { + struct Configuration + { + std::string host_group_name{}; /*!< Common host group name that enables interprocess mechanisms across + (virtual) host borders (e.g, Docker); by default equivalent to local host name (Default: "")*/ + Types::ConstrainedInteger<4096, 4096> memfile_minsize{}; //!< Default memory file size for new publisher (Default: 4096) + Types::ConstrainedInteger<50, 1, 100> memfile_reserve{}; //!< Dynamic file size reserve before recreating memory file if topic size changes in % (Default: 50) + unsigned int memfile_ack_timeout{}; //!< Publisher timeout for ack event from subscriber that memory file content is processed (Default: 0) + Types::ConstrainedInteger<0, 1> memfile_buffer_count{}; //!< Number of parallel used memory file buffers for 1:n publish/subscribe ipc connections (Default = 1) + bool drop_out_of_order_messages{}; //!< (Default: ) + bool memfile_zero_copy{}; //!< Allow matching subscriber to access memory file without copying its content in advance (Default: false) + }; + } + + namespace UDPMC + { + struct Configuration + { + Types::UdpConfigVersion config_version{}; /*!< UDP configuration version (Since eCAL 5.12.) + v1: default behavior + v2: new behavior, comes with a bit more intuitive handling regarding masking of the groups (Default: v1) */ + Types::IpAddressV4 group{}; //!< UDP multicast group base (Default: 239.0.0.1) + Types::IpAddressV4 mask{}; /*!< v1: Mask maximum number of dynamic multicast group (Default: 0.0.0.1-0.0.0.255) + v2: masks are now considered like routes masking (Default: 255.0.0.0-255.255.255.255)*/ + Types::ConstrainedInteger<14000, 10> port{}; /*!< UDP multicast port number (eCAL will use at least the 2 following port + numbers too, so modify in steps of 10 (e.g. 1010, 1020 ...)(Default: 14000) */ + unsigned int ttl{}; /*!< UDP ttl value, also known as hop limit, is used in determining + the intermediate routers being traversed towards the destination(Default: 2) */ + // TODO PG: are these minimum limits correct? + Types::ConstrainedInteger<5242880, 1024> sndbuf{}; //!< UDP send buffer in bytes (Default: 5242880) + Types::ConstrainedInteger<5242880, 1024> recbuf{}; //!< UDP receive buffer in bytes (Default: 5242880) + bool join_all_interfaces{}; /*!< Linux specific setting to enable joining multicast groups on all network interfacs + independent of their link state. Enabling this makes sure that eCAL processes + receive data if they are started before network devices are up and running. (Default: false)*/ + + bool npcap_enabled{}; //!< Enable to receive UDP traffic with the Npcap based receiver (Default: false) + }; + } + + struct Configuration + { + bool network_enabled{}; /*!< true = all eCAL components communicate over network boundaries + false = local host only communication (Default: false) */ + bool drop_out_of_order_messages{}; //!< Enable dropping of payload messages that arrive out of order (Default: false) + UDPMC::Configuration mc_options{}; + TCPPubSub::Configuration tcp_options{}; + SHM::Configuration shm_options{}; + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/config/user_arguments.h b/ecal/core/include/ecal/config/user_arguments.h new file mode 100644 index 0000000000..6f64cdf16a --- /dev/null +++ b/ecal/core/include/ecal/config/user_arguments.h @@ -0,0 +1,45 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file user_arguments.h + * @brief Arguments given by the user via command line +**/ + +#pragma once + +#include +#include +#include + +namespace eCAL +{ + namespace Cli + { + using ConfigKey2DMap = std::map>; //!< Config key storage: Map[Section][Option] = Value + + struct Configuration + { + std::vector config_keys{}; //!< will be deprecated soon + ConfigKey2DMap config_keys_map; //!< The config keys given via command line and the --config-keys parameter (Default: empty) + std::string specified_config{}; //!< The used eCAL ini file (Default: "") + bool dump_config{}; //!< If specified, output configuration via standart output (Default: false) + }; + } +} \ No newline at end of file diff --git a/ecal/core/include/ecal/ecal.h b/ecal/core/include/ecal/ecal.h index 43669cb85b..0bfbc13886 100644 --- a/ecal/core/include/ecal/ecal.h +++ b/ecal/core/include/ecal/ecal.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,3 +42,4 @@ #include #include #include +#include diff --git a/ecal/core/include/ecal/ecal_config.h b/ecal/core/include/ecal/ecal_config.h index 78ea92e557..570d01e579 100644 --- a/ecal/core/include/ecal/ecal_config.h +++ b/ecal/core/include/ecal/ecal_config.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,117 +23,115 @@ #include #include #include +#include "ecal/config/configuration.h" #include //@{ namespace eCAL { + ECAL_API Configuration& GetConfiguration(); + namespace Config { - enum class UdpConfigVersion - { - V1 = 1, // Legacy - V2 = 2 - }; - ///////////////////////////////////// // common ///////////////////////////////////// - ECAL_API std::string GetLoadedEcalIniPath (); - ECAL_API int GetRegistrationTimeoutMs (); - ECAL_API int GetRegistrationRefreshMs (); + ECAL_API std::string GetLoadedEcalIniPath (); + ECAL_API int GetRegistrationTimeoutMs (); + ECAL_API int GetRegistrationRefreshMs (); ///////////////////////////////////// // network ///////////////////////////////////// - ECAL_API bool IsNetworkEnabled (); - ECAL_API UdpConfigVersion GetUdpMulticastConfigVersion (); - ECAL_API std::string GetUdpMulticastGroup (); - ECAL_API std::string GetUdpMulticastMask (); - ECAL_API int GetUdpMulticastPort (); - ECAL_API int GetUdpMulticastTtl (); + ECAL_API bool IsNetworkEnabled (); + ECAL_API Types::UdpConfigVersion GetUdpMulticastConfigVersion (); + ECAL_API std::string GetUdpMulticastGroup (); + ECAL_API std::string GetUdpMulticastMask (); + ECAL_API int GetUdpMulticastPort (); + ECAL_API int GetUdpMulticastTtl (); - ECAL_API int GetUdpMulticastSndBufSizeBytes (); - ECAL_API int GetUdpMulticastRcvBufSizeBytes (); + ECAL_API int GetUdpMulticastSndBufSizeBytes (); + ECAL_API int GetUdpMulticastRcvBufSizeBytes (); - ECAL_API bool IsUdpMulticastJoinAllIfEnabled (); + ECAL_API bool IsUdpMulticastJoinAllIfEnabled (); - ECAL_API bool IsUdpMulticastRecEnabled (); - ECAL_API bool IsShmRecEnabled (); - ECAL_API bool IsTcpRecEnabled (); + ECAL_API bool IsUdpMulticastRecEnabled (); + ECAL_API bool IsShmRecEnabled (); + ECAL_API bool IsTcpRecEnabled (); - ECAL_API bool IsNpcapEnabled (); + ECAL_API bool IsNpcapEnabled (); - ECAL_API int GetTcpPubsubReaderThreadpoolSize (); - ECAL_API int GetTcpPubsubWriterThreadpoolSize (); - ECAL_API int GetTcpPubsubMaxReconnectionAttemps (); + ECAL_API int GetTcpPubsubReaderThreadpoolSize (); + ECAL_API int GetTcpPubsubWriterThreadpoolSize (); + ECAL_API int GetTcpPubsubMaxReconnectionAttemps (); - ECAL_API std::string GetHostGroupName (); + ECAL_API std::string GetHostGroupName (); ///////////////////////////////////// // time ///////////////////////////////////// - ECAL_API std::string GetTimesyncModuleName (); - + ECAL_API std::string GetTimesyncModuleName (); + ECAL_API std::string GetTimesyncModuleReplay (); + ///////////////////////////////////// // process ///////////////////////////////////// - ECAL_API std::string GetTerminalEmulatorCommand (); + ECAL_API std::string GetTerminalEmulatorCommand (); ///////////////////////////////////// // monitoring ///////////////////////////////////// - ECAL_API int GetMonitoringTimeoutMs (); - ECAL_API std::string GetMonitoringFilterExcludeList (); - ECAL_API std::string GetMonitoringFilterIncludeList (); - ECAL_API eCAL_Logging_Filter GetConsoleLogFilter (); - ECAL_API eCAL_Logging_Filter GetFileLogFilter (); - ECAL_API eCAL_Logging_Filter GetUdpLogFilter (); + ECAL_API int GetMonitoringTimeoutMs (); + ECAL_API std::string GetMonitoringFilterExcludeList (); + ECAL_API std::string GetMonitoringFilterIncludeList (); + ECAL_API eCAL_Logging_Filter GetConsoleLogFilter (); + ECAL_API eCAL_Logging_Filter GetFileLogFilter (); + ECAL_API eCAL_Logging_Filter GetUdpLogFilter (); ///////////////////////////////////// // sys ///////////////////////////////////// - ECAL_API std::string GetEcalSysFilterExcludeList (); + ECAL_API std::string GetEcalSysFilterExcludeList (); ///////////////////////////////////// // publisher ///////////////////////////////////// - ECAL_API TLayer::eSendMode GetPublisherShmMode (); - ECAL_API TLayer::eSendMode GetPublisherTcpMode (); - ECAL_API TLayer::eSendMode GetPublisherUdpMulticastMode (); + ECAL_API bool GetPublisherShmMode (); + ECAL_API bool GetPublisherTcpMode (); + ECAL_API bool GetPublisherUdpMulticastMode (); - ECAL_API size_t GetMemfileMinsizeBytes (); - ECAL_API size_t GetMemfileOverprovisioningPercentage (); - ECAL_API int GetMemfileAckTimeoutMs (); - ECAL_API bool IsMemfileZerocopyEnabled (); - ECAL_API size_t GetMemfileBufferCount (); + ECAL_API size_t GetMemfileMinsizeBytes (); + ECAL_API size_t GetMemfileOverprovisioningPercentage (); + ECAL_API int GetMemfileAckTimeoutMs (); + ECAL_API bool IsMemfileZerocopyEnabled (); + ECAL_API size_t GetMemfileBufferCount (); - ECAL_API bool IsTopicTypeSharingEnabled (); - ECAL_API bool IsTopicDescriptionSharingEnabled (); + ECAL_API bool IsTopicTypeSharingEnabled (); + ECAL_API bool IsTopicDescriptionSharingEnabled (); ///////////////////////////////////// // service ///////////////////////////////////// - ECAL_API bool IsServiceProtocolV0Enabled (); - ECAL_API bool IsServiceProtocolV1Enabled (); + ECAL_API bool IsServiceProtocolV0Enabled (); + ECAL_API bool IsServiceProtocolV1Enabled (); ///////////////////////////////////// // experimental ///////////////////////////////////// namespace Experimental { - ECAL_API bool IsShmMonitoringEnabled (); - ECAL_API bool IsNetworkMonitoringDisabled (); - ECAL_API size_t GetShmMonitoringQueueSize (); - ECAL_API std::string GetShmMonitoringDomain (); - ECAL_API bool GetDropOutOfOrderMessages (); + ECAL_API bool IsShmMonitoringEnabled (); + ECAL_API bool IsNetworkMonitoringDisabled (); + ECAL_API size_t GetShmMonitoringQueueSize (); + ECAL_API std::string GetShmMonitoringDomain (); + ECAL_API bool GetDropOutOfOrderMessages (); } } } diff --git a/ecal/core/include/ecal/ecal_core.h b/ecal/core/include/ecal/ecal_core.h index ce8aa1edc7..a725191b75 100644 --- a/ecal/core/include/ecal/ecal_core.h +++ b/ecal/core/include/ecal/ecal_core.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ #include #include +#include namespace eCAL { @@ -82,6 +83,17 @@ namespace eCAL **/ ECAL_API int Initialize(std::vector args_, const char *unit_name_ = nullptr, unsigned int components_ = Init::Default); + /** + * @brief Initialize eCAL API. + * + * @param config_ User defined configuration object. + * @param unit_name_ Defines the name of the eCAL unit. + * @param components_ Defines which component to initialize. + * + * @return Zero if succeeded, 1 if already initialized, -1 if failed. + **/ + ECAL_API int Initialize(eCAL::Configuration& config_, const char *unit_name_ = nullptr, unsigned int components_ = Init::Default); + /** * @brief Finalize eCAL API. * diff --git a/ecal/core/include/ecal/ecal_publisher.h b/ecal/core/include/ecal/ecal_publisher.h index 80c651434f..08dcaa7bff 100644 --- a/ecal/core/include/ecal/ecal_publisher.h +++ b/ecal/core/include/ecal/ecal_publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include diff --git a/ecal/core/include/ecal/ecal_subscriber.h b/ecal/core/include/ecal/ecal_subscriber.h index 0ed5ea9f80..15f9cc3d43 100644 --- a/ecal/core/include/ecal/ecal_subscriber.h +++ b/ecal/core/include/ecal/ecal_subscriber.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff --git a/ecal/core/include/ecal/msg/capnproto/publisher.h b/ecal/core/include/ecal/msg/capnproto/publisher.h index bf6b3d6ef1..60192fd4ae 100644 --- a/ecal/core/include/ecal/msg/capnproto/publisher.h +++ b/ecal/core/include/ecal/msg/capnproto/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/flatbuffers/publisher.h b/ecal/core/include/ecal/msg/flatbuffers/publisher.h index 6e9e836715..8e6cf3a3c5 100644 --- a/ecal/core/include/ecal/msg/flatbuffers/publisher.h +++ b/ecal/core/include/ecal/msg/flatbuffers/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/messagepack/publisher.h b/ecal/core/include/ecal/msg/messagepack/publisher.h index 70a7298a2f..5d7904c43a 100644 --- a/ecal/core/include/ecal/msg/messagepack/publisher.h +++ b/ecal/core/include/ecal/msg/messagepack/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/protobuf/dynamic_publisher.h b/ecal/core/include/ecal/msg/protobuf/dynamic_publisher.h index 1a7ca4f2a1..717ab81fe0 100644 --- a/ecal/core/include/ecal/msg/protobuf/dynamic_publisher.h +++ b/ecal/core/include/ecal/msg/protobuf/dynamic_publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/protobuf/publisher.h b/ecal/core/include/ecal/msg/protobuf/publisher.h index e583292877..b6b79bd869 100644 --- a/ecal/core/include/ecal/msg/protobuf/publisher.h +++ b/ecal/core/include/ecal/msg/protobuf/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/publisher.h b/ecal/core/include/ecal/msg/publisher.h index 5f3b0625f2..74e993c6c9 100644 --- a/ecal/core/include/ecal/msg/publisher.h +++ b/ecal/core/include/ecal/msg/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/msg/string/publisher.h b/ecal/core/include/ecal/msg/string/publisher.h index f1d45d58af..03cbf886c3 100644 --- a/ecal/core/include/ecal/msg/string/publisher.h +++ b/ecal/core/include/ecal/msg/string/publisher.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ecal/core/include/ecal/types/ecal_custom_data_types.h b/ecal/core/include/ecal/types/ecal_custom_data_types.h new file mode 100644 index 0000000000..8162c099ac --- /dev/null +++ b/ecal/core/include/ecal/types/ecal_custom_data_types.h @@ -0,0 +1,104 @@ +/* =========================== LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * =========================== LICENSE ================================= + */ + +/** + * @file ecal_custom_types.h + * @brief eCAL custom types for configuration declarations +**/ + +#pragma once + +#include "ecal/ecal_os.h" + +#include +#include +#include +#include + +namespace eCAL +{ + namespace Types + { + /** + * @brief Class for evaluation and storing an IPv4/IPv6 address. + * Invalid addresses: 255.255.255.255, 127.0.0.1, 0.0.0.0 + * + * @param ip_address_ The IP address as std::string. + * + * @throws std::invalid_argument exception. + **/ + class IpAddressV4 + { + public: + ECAL_API IpAddressV4(); + ECAL_API IpAddressV4(const std::string& ip_address_); + + std::string Get() const; + + ECAL_API IpAddressV4& operator=(const std::string& ip_string); + ECAL_API operator std::string(); + + private: + ECAL_API void validateIpString(const std::string& ip_address_); + ECAL_API static void throwException(const std::string& ip_address_ = std::string("")); + + std::string m_ip_address{}; + }; + + /** + * @brief Template class to specify sizes with a concrete minimum, maximum and step size definition. + * + * @tparam MIN Optional minimum possible size. Default: 0 + * @tparam STEP Optional step size. Default: 1 + * @tparam MAX Optional maximum possible size. Default: std::numeric_limits::max() + * + * @param size_ Optional size value. If not set, ConstrainedInteger will return the MIN value. + * + * @throws std::invalid_argument exception. + **/ + template::max()> + class ConstrainedInteger + { + public: + ConstrainedInteger(int size_ = MIN) + { + if (size_ >= MIN && size_ <= MAX && size_ % STEP == 0 && MAX >= MIN) + { + m_size = size_; + } + else + { + throw std::invalid_argument("[ConstrainedInteger] Faulty size configuration or assignment. MIN: " + std::to_string(MIN) + " MAX: " + std::to_string(MAX) + " STEP: " + std::to_string(STEP) + " VALUE:" + std::to_string(size_)); + } + }; + + operator int() const { return m_size; }; + bool operator==(const ConstrainedInteger& other) const { return this->m_size == other; }; + + private: + int m_size{}; + }; + + enum class UdpConfigVersion + { + V1 = 1, + V2 = 2 + }; + } +} \ No newline at end of file diff --git a/ecal/core/src/config/ecal_cmd_parser.cpp b/ecal/core/src/config/ecal_cmd_parser.cpp new file mode 100644 index 0000000000..b2567657b4 --- /dev/null +++ b/ecal/core/src/config/ecal_cmd_parser.cpp @@ -0,0 +1,254 @@ +#include "config/ecal_cmd_parser.h" + +#include "ecal/ecal_defs.h" +#include "ecal_def.h" +#include "ecal_utils/filesystem.h" +#include "util/getenvvar.h" + +#if ECAL_CORE_COMMAND_LINE + #include "util/advanced_tclap_output.h" +#endif + +#include + +// for cwd +#ifdef ECAL_OS_WINDOWS + #include + // to remove deprecated warning + #define getcwd _getcwd +#endif +#ifdef ECAL_OS_LINUX + #include +#endif + +namespace +{ + // copied and adapted from ecal_config_reader.cpp +#ifdef ECAL_OS_WINDOWS + const char path_separator('\\'); +#endif /* ECAL_OS_WINDOWS */ +#ifdef ECAL_OS_LINUX + const char path_separator('/'); +#endif /* ECAL_OS_LINUX */ + + bool setPathSep(std::string& file_path_) + { + if (!file_path_.empty()) + { + if (file_path_.back() != path_separator) + { + file_path_ += path_separator; + } + return true; + } + + return false; + } + + std::string eCALDataEnvPath() + { + std::string ecal_data_path = getEnvVar("ECAL_DATA"); + setPathSep(ecal_data_path); + return ecal_data_path; + } + + std::string cwdPath() + { + std::string cwd_path = { getcwd(nullptr, 0) }; + + if (cwd_path.empty()) + throw std::runtime_error("getcwd() : cannot read current working directory."); + + setPathSep(cwd_path); + return cwd_path; + } + + std::string eCALDataCMakePath() + { + std::string cmake_data_path; +#ifdef ECAL_OS_LINUX + const std::string ecal_install_config_dir(ECAL_INSTALL_CONFIG_DIR); + const std::string ecal_install_prefix(ECAL_INSTALL_PREFIX); + + if ((!ecal_install_config_dir.empty() && (ecal_install_config_dir[0] == path_separator)) + || ecal_install_prefix.empty()) + { + cmake_data_path = ecal_install_config_dir; + } + else if (!ecal_install_prefix.empty()) + { + cmake_data_path = ecal_install_prefix + path_separator + ecal_install_config_dir; + } + setPathSep(cmake_data_path); +#endif /* ECAL_OS_LINUX */ + return cmake_data_path; + } + + std::string eCALDataSystemPath() + { + std::string system_data_path; +#ifdef ECAL_OS_WINDOWS + system_data_path = getEnvVar("ProgramData"); + if(setPathSep(system_data_path)) + { + system_data_path += std::string("eCAL"); + setPathSep(system_data_path); + } +#endif /* ECAL_OS_WINDOWS */ + +#ifdef ECAL_OS_LINUX + system_data_path = "/etc/ecal"; + setPathSep(system_data_path); +#endif /* ECAL_OS_LINUX */ + return system_data_path; + } + + void appendFileNameToPathIfPathIsValid(std::string& path_, const std::string& file_name_) + { + if (!path_.empty()) + path_ += file_name_; + } + + void parseConfigKeysToMap(const std::vector& config_keys_, eCAL::Cli::ConfigKey2DMap& map_) + { + // each string has the format "section/key:value" + for (const auto& full_key : config_keys_) + { + auto sec_pos = full_key.find_last_of('/'); + if (sec_pos == std::string::npos) continue; + const std::string section = full_key.substr(0, sec_pos); + std::string key = full_key.substr(sec_pos+1); + + auto val_pos = key.find_first_of(':'); + if (val_pos == std::string::npos) continue; + const std::string value = key.substr(val_pos+1); + key = key.substr(0, val_pos); + + map_[section][key] = value; + } + } + + bool isValidConfigFilePath(const std::string& file_path_) + { + // check existence of user defined file + const EcalUtils::Filesystem::FileStatus ecal_ini_status(file_path_, EcalUtils::Filesystem::Current); + return ecal_ini_status.IsOk() && (ecal_ini_status.GetType() == EcalUtils::Filesystem::Type::RegularFile); + } + + std::string checkForValidConfigFilePath(const std::string& config_file_) + { + // differences to ecal_config_reader implementation are: + // 1. does not use the default ini file name, instead uses the specified file + // 2. searches relative to the executable path and takes it as highest priority + // 3. throws a runtime error, if it cannot find the specified file + + // ----------------------------------------------------------- + // precedence 1: relative path to executable + // ----------------------------------------------------------- + std::string cwd_directory_path = cwdPath(); + appendFileNameToPathIfPathIsValid(cwd_directory_path, config_file_); + + // ----------------------------------------------------------- + // precedence 2: ECAL_DATA variable (windows and linux) + // ----------------------------------------------------------- + std::string ecal_data_path = eCALDataEnvPath(); + appendFileNameToPathIfPathIsValid(ecal_data_path, config_file_); + + // ----------------------------------------------------------- + // precedence 3: cmake configured data paths (linux only) + // ----------------------------------------------------------- + std::string cmake_data_path = eCALDataCMakePath(); + appendFileNameToPathIfPathIsValid(cmake_data_path, config_file_); + + // ----------------------------------------------------------- + // precedence 4: system data path + // ----------------------------------------------------------- + std::string system_data_path = eCALDataSystemPath(); + appendFileNameToPathIfPathIsValid(system_data_path, config_file_); + + // Check for first directory which contains the ini file. + std::vector search_directories{ cwd_directory_path, ecal_data_path, cmake_data_path, system_data_path }; + + auto it = std::find_if(search_directories.begin(), search_directories.end(), isValidConfigFilePath); + // We should have encountered a valid path + if (it != search_directories.end()) + return (*it); + + // Check if user specified complete path, in case all other precedence paths exist + if (isValidConfigFilePath(config_file_)) + { + return std::string(config_file_); + } + + // If valid path is not encountered, throw error + throw std::runtime_error("[CMD Parser] Specified config file: \"" + config_file_ + "\" not found."); + } +} + +namespace eCAL +{ + namespace Config + { + CmdParser::CmdParser() + : m_dump_config{false} + {} + + CmdParser::CmdParser(std::vector& arguments_) + : CmdParser() + { + parseArguments(arguments_); + } + + void CmdParser::parseArguments(std::vector& arguments_) + { +#if ECAL_CORE_COMMAND_LINE + if (!arguments_.empty()) + { + // define command line object + TCLAP::CmdLine cmd("", ' ', ECAL_VERSION); + + // define command line arguments + TCLAP::SwitchArg dump_config_arg ("", "ecal-dump-config", "Dump current configuration.", false); + TCLAP::ValueArg default_ini_file_arg("", "ecal-ini-file", "Load default configuration from that file.", false, ECAL_DEFAULT_CFG, "string"); + TCLAP::MultiArg set_config_key_arg ("", "ecal-set-config-key", "Overwrite a specific configuration key (ecal-set-config-key \"section/key:value\".", false, "string"); + + TCLAP::UnlabeledMultiArg dummy_arg("__dummy__", "Dummy", false, ""); // Dummy arg to eat all unrecognized arguments + + cmd.add(dump_config_arg); + cmd.add(default_ini_file_arg); + cmd.add(set_config_key_arg); + cmd.add(dummy_arg); + + CustomTclap::AdvancedTclapOutput advanced_tclap_output(&std::cout, 75); + advanced_tclap_output.setArgumentHidden(&dummy_arg, true); + cmd.setOutput(&advanced_tclap_output); + + // parse command line + cmd.parse(arguments_); + + // set globals + if (dump_config_arg.isSet()) + { + m_dump_config = true; + } + if (default_ini_file_arg.isSet()) + { + m_user_ini = checkForValidConfigFilePath(default_ini_file_arg.getValue()); + } + if (set_config_key_arg.isSet()) + { + m_config_keys = set_config_key_arg.getValue(); + parseConfigKeysToMap(set_config_key_arg.getValue(), m_config_key_map); + } + } +#endif + m_task_parameter = arguments_; + } + + bool CmdParser::getDumpConfig() const { return m_dump_config; }; + std::vector& CmdParser::getConfigKeys() { return m_config_keys; }; + std::vector& CmdParser::getTaskParameter() { return m_task_parameter; }; + std::string& CmdParser::getUserIni() { return m_user_ini; }; + Cli::ConfigKey2DMap& CmdParser::getConfigKeysMap() { return m_config_key_map; }; + } +} diff --git a/ecal/core/src/config/ecal_cmd_parser.h b/ecal/core/src/config/ecal_cmd_parser.h new file mode 100644 index 0000000000..dd1ed957bf --- /dev/null +++ b/ecal/core/src/config/ecal_cmd_parser.h @@ -0,0 +1,66 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Utility class for parsing cmd line arguments into eCAL useful structures. +**/ + +#pragma once + +#include + +#include +#include +#include + +namespace eCAL +{ + namespace Config + { + /** + * @brief Class for parsing and storing command line arguments and their values. + * Defaults as empty strings, vectors and false booleans. + * + * @param argc_ Number of arguments + * @param argv_ Array of arguments + * + **/ + class CmdParser + { + public: + CmdParser(std::vector& arguments_); + CmdParser(); + + void parseArguments(std::vector& arguments_); + + bool getDumpConfig() const; + std::vector& getConfigKeys(); + std::vector& getTaskParameter(); + std::string& getUserIni(); + Cli::ConfigKey2DMap& getConfigKeysMap(); + + private: + std::vector m_config_keys; + Cli::ConfigKey2DMap m_config_key_map; + bool m_dump_config; + std::vector m_task_parameter; + std::string m_user_ini; + }; + } +} \ No newline at end of file diff --git a/ecal/core/src/config/ecal_config.cpp b/ecal/core/src/config/ecal_config.cpp index ffb4543dcf..14f23cf803 100644 --- a/ecal/core/src/config/ecal_config.cpp +++ b/ecal/core/src/config/ecal_config.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -89,99 +89,91 @@ namespace eCAL // common ///////////////////////////////////// - ECAL_API std::string GetLoadedEcalIniPath () { return g_default_ini_file; } - ECAL_API int GetRegistrationTimeoutMs () { return eCALPAR(CMN, REGISTRATION_TO); } - ECAL_API int GetRegistrationRefreshMs () { return eCALPAR(CMN, REGISTRATION_REFRESH); } + ECAL_API std::string GetLoadedEcalIniPath () { return GetConfiguration().GetIniFilePath(); } + ECAL_API int GetRegistrationTimeoutMs () { return GetConfiguration().registration.getTimeoutMS(); } + ECAL_API int GetRegistrationRefreshMs () { return GetConfiguration().registration.getRefreshMS(); } ///////////////////////////////////// // network ///////////////////////////////////// - ECAL_API bool IsNetworkEnabled () { return eCALPAR(NET, ENABLED); } + ECAL_API bool IsNetworkEnabled () { return GetConfiguration().transport_layer.network_enabled; } - ECAL_API UdpConfigVersion GetUdpMulticastConfigVersion() - { - const std::string udp_config_version_string = eCALPAR(NET, UDP_MULTICAST_CONFIG_VERSION); - if (udp_config_version_string == "v1") - return UdpConfigVersion::V1; - if (udp_config_version_string == "v2") - return UdpConfigVersion::V2; - // TODO: Log error. However not sure if logging is initialized at this place. - return UdpConfigVersion::V1; - } + ECAL_API Types::UdpConfigVersion GetUdpMulticastConfigVersion () { return GetConfiguration().transport_layer.mc_options.config_version; } - ECAL_API std::string GetUdpMulticastGroup () { return eCALPAR(NET, UDP_MULTICAST_GROUP); } - ECAL_API std::string GetUdpMulticastMask () { return eCALPAR(NET, UDP_MULTICAST_MASK); } - ECAL_API int GetUdpMulticastPort () { return eCALPAR(NET, UDP_MULTICAST_PORT); } - ECAL_API int GetUdpMulticastTtl () { return eCALPAR(NET, UDP_MULTICAST_TTL); } + ECAL_API std::string GetUdpMulticastGroup () { return GetConfiguration().transport_layer.mc_options.group; } + ECAL_API std::string GetUdpMulticastMask () { return GetConfiguration().transport_layer.mc_options.mask; } + ECAL_API int GetUdpMulticastPort () { return GetConfiguration().transport_layer.mc_options.port; } + ECAL_API int GetUdpMulticastTtl () { return GetConfiguration().transport_layer.mc_options.ttl; } - ECAL_API int GetUdpMulticastSndBufSizeBytes () { return eCALPAR(NET, UDP_MULTICAST_SNDBUF); } - ECAL_API int GetUdpMulticastRcvBufSizeBytes () { return eCALPAR(NET, UDP_MULTICAST_RCVBUF); } - ECAL_API bool IsUdpMulticastJoinAllIfEnabled () { return eCALPAR(NET, UDP_MULTICAST_JOIN_ALL_IF_ENABLED); } + ECAL_API int GetUdpMulticastSndBufSizeBytes () { return GetConfiguration().transport_layer.mc_options.sndbuf; } + ECAL_API int GetUdpMulticastRcvBufSizeBytes () { return GetConfiguration().transport_layer.mc_options.recbuf; } + ECAL_API bool IsUdpMulticastJoinAllIfEnabled () { return GetConfiguration().transport_layer.mc_options.join_all_interfaces; } - ECAL_API bool IsUdpMulticastRecEnabled () { return eCALPAR(NET, UDP_MC_REC_ENABLED); } - ECAL_API bool IsShmRecEnabled () { return eCALPAR(NET, SHM_REC_ENABLED); } - ECAL_API bool IsTcpRecEnabled () { return eCALPAR(NET, TCP_REC_ENABLED); } + ECAL_API bool IsUdpMulticastRecEnabled () { return GetConfiguration().subscriber.udp.enable; } + ECAL_API bool IsShmRecEnabled () { return GetConfiguration().subscriber.shm.enable; } + ECAL_API bool IsTcpRecEnabled () { return GetConfiguration().subscriber.tcp.enable; } - ECAL_API bool IsNpcapEnabled () { return eCALPAR(NET, NPCAP_ENABLED); } + ECAL_API bool IsNpcapEnabled () { return GetConfiguration().transport_layer.mc_options.npcap_enabled; } - ECAL_API int GetTcpPubsubReaderThreadpoolSize () { return eCALPAR(NET, TCP_PUBSUB_NUM_EXECUTOR_READER); } - ECAL_API int GetTcpPubsubWriterThreadpoolSize () { return eCALPAR(NET, TCP_PUBSUB_NUM_EXECUTOR_WRITER); } - ECAL_API int GetTcpPubsubMaxReconnectionAttemps () { return eCALPAR(NET, TCP_PUBSUB_MAX_RECONNECTIONS); } + ECAL_API int GetTcpPubsubReaderThreadpoolSize () { return static_cast(GetConfiguration().transport_layer.tcp_options.num_executor_reader); } + ECAL_API int GetTcpPubsubWriterThreadpoolSize () { return static_cast(GetConfiguration().transport_layer.tcp_options.num_executor_writer); } + ECAL_API int GetTcpPubsubMaxReconnectionAttemps () { return static_cast(GetConfiguration().transport_layer.tcp_options.max_reconnections); } - ECAL_API std::string GetHostGroupName () { return eCALPAR(NET, HOST_GROUP_NAME); } + ECAL_API std::string GetHostGroupName () { return GetConfiguration().transport_layer.shm_options.host_group_name; } ///////////////////////////////////// // time ///////////////////////////////////// - ECAL_API std::string GetTimesyncModuleName () { return eCALPAR(TIME, SYNC_MOD_RT); } + ECAL_API std::string GetTimesyncModuleName () { return GetConfiguration().timesync.timesync_module_rt; } + ECAL_API std::string GetTimesyncModuleReplay () { return GetConfiguration().timesync.timesync_module_replay; } ///////////////////////////////////// // process ///////////////////////////////////// - ECAL_API std::string GetTerminalEmulatorCommand () { return eCALPAR(PROCESS, TERMINAL_EMULATOR); } + ECAL_API std::string GetTerminalEmulatorCommand () { return GetConfiguration().application.startup.terminal_emulator; } ///////////////////////////////////// // monitoring ///////////////////////////////////// - ECAL_API int GetMonitoringTimeoutMs () { return eCALPAR(MON, TIMEOUT); } - ECAL_API std::string GetMonitoringFilterExcludeList () { return eCALPAR(MON, FILTER_EXCL); } - ECAL_API std::string GetMonitoringFilterIncludeList () { return eCALPAR(MON, FILTER_INCL); } - ECAL_API eCAL_Logging_Filter GetConsoleLogFilter () { return ParseLogLevel(eCALPAR(MON, LOG_FILTER_CON)); } - ECAL_API eCAL_Logging_Filter GetFileLogFilter () { return ParseLogLevel(eCALPAR(MON, LOG_FILTER_FILE)); } - ECAL_API eCAL_Logging_Filter GetUdpLogFilter () { return ParseLogLevel(eCALPAR(MON, LOG_FILTER_UDP)); } + ECAL_API int GetMonitoringTimeoutMs () { return GetConfiguration().monitoring.monitoring_timeout; } + ECAL_API std::string GetMonitoringFilterExcludeList () { return GetConfiguration().monitoring.filter_excl; } + ECAL_API std::string GetMonitoringFilterIncludeList () { return GetConfiguration().monitoring.filter_incl; } + ECAL_API eCAL_Logging_Filter GetConsoleLogFilter () { return GetConfiguration().logging.filter_log_con; } + ECAL_API eCAL_Logging_Filter GetFileLogFilter () { return GetConfiguration().logging.filter_log_file; } + ECAL_API eCAL_Logging_Filter GetUdpLogFilter () { return GetConfiguration().logging.filter_log_udp; } ///////////////////////////////////// // sys ///////////////////////////////////// - ECAL_API std::string GetEcalSysFilterExcludeList () { return eCALPAR(SYS, FILTER_EXCL); } + ECAL_API std::string GetEcalSysFilterExcludeList () { return GetConfiguration().application.sys.filter_excl; } ///////////////////////////////////// // publisher ///////////////////////////////////// - ECAL_API TLayer::eSendMode GetPublisherUdpMulticastMode () { return TLayer::eSendMode(eCALPAR(PUB, USE_UDP_MC)); } - ECAL_API TLayer::eSendMode GetPublisherShmMode () { return TLayer::eSendMode(eCALPAR(PUB, USE_SHM)); } - ECAL_API TLayer::eSendMode GetPublisherTcpMode () { return TLayer::eSendMode(eCALPAR(PUB, USE_TCP)); } + ECAL_API bool GetPublisherUdpMulticastMode () { return GetConfiguration().publisher.udp.enable; } + ECAL_API bool GetPublisherShmMode () { return GetConfiguration().publisher.shm.enable; } + ECAL_API bool GetPublisherTcpMode () { return GetConfiguration().publisher.tcp.enable; } - ECAL_API size_t GetMemfileMinsizeBytes () { return static_cast(eCALPAR(PUB, MEMFILE_MINSIZE)); } - ECAL_API size_t GetMemfileOverprovisioningPercentage () { return static_cast(eCALPAR(PUB, MEMFILE_RESERVE)); } - ECAL_API int GetMemfileAckTimeoutMs () { return eCALPAR(PUB, MEMFILE_ACK_TO); } - ECAL_API bool IsMemfileZerocopyEnabled () { return (eCALPAR(PUB, MEMFILE_ZERO_COPY) != 0); } - ECAL_API size_t GetMemfileBufferCount () { return static_cast(eCALPAR(PUB, MEMFILE_BUF_COUNT)); } + ECAL_API size_t GetMemfileMinsizeBytes () { return GetConfiguration().transport_layer.shm_options.memfile_minsize; } + ECAL_API size_t GetMemfileOverprovisioningPercentage () { return GetConfiguration().transport_layer.shm_options.memfile_reserve; } + ECAL_API int GetMemfileAckTimeoutMs () { return GetConfiguration().transport_layer.shm_options.memfile_ack_timeout; } + ECAL_API bool IsMemfileZerocopyEnabled () { return GetConfiguration().transport_layer.shm_options.memfile_zero_copy; } + ECAL_API size_t GetMemfileBufferCount () { return GetConfiguration().transport_layer.shm_options.memfile_buffer_count; } - ECAL_API bool IsTopicTypeSharingEnabled () { return (eCALPAR(PUB, SHARE_TTYPE) != 0); } - ECAL_API bool IsTopicDescriptionSharingEnabled () { return (eCALPAR(PUB, SHARE_TDESC) != 0); } + ECAL_API bool IsTopicTypeSharingEnabled () { return GetConfiguration().registration.share_ttype; } + ECAL_API bool IsTopicDescriptionSharingEnabled () { return GetConfiguration().registration.share_tdesc; } ///////////////////////////////////// // service ///////////////////////////////////// - ECAL_API bool IsServiceProtocolV0Enabled () { return (eCALPAR(SERVICE, PROTOCOL_V0) != 0); } - ECAL_API bool IsServiceProtocolV1Enabled () { return (eCALPAR(SERVICE, PROTOCOL_V1) != 0); } + ECAL_API bool IsServiceProtocolV0Enabled () { return GetConfiguration().service.protocol_v0; } + ECAL_API bool IsServiceProtocolV1Enabled () { return GetConfiguration().service.protocol_v1; } ///////////////////////////////////// // experimemtal @@ -189,11 +181,11 @@ namespace eCAL namespace Experimental { - ECAL_API bool IsShmMonitoringEnabled () { return eCALPAR(EXP, SHM_MONITORING_ENABLED); } - ECAL_API bool IsNetworkMonitoringDisabled () { return eCALPAR(EXP, NETWORK_MONITORING_DISABLED); } - ECAL_API size_t GetShmMonitoringQueueSize () { return static_cast(eCALPAR(EXP, SHM_MONITORING_QUEUE_SIZE)); } - ECAL_API std::string GetShmMonitoringDomain () { return eCALPAR(EXP, SHM_MONITORING_DOMAIN);} - ECAL_API bool GetDropOutOfOrderMessages () { return eCALPAR(EXP, DROP_OUT_OF_ORDER_MESSAGES); } + ECAL_API bool IsShmMonitoringEnabled () { return (GetConfiguration().monitoring.monitoring_mode & Monitoring::Types::Mode::shm_monitoring) != 0; } + ECAL_API bool IsNetworkMonitoringDisabled () { return !GetConfiguration().monitoring.network_monitoring; } + ECAL_API size_t GetShmMonitoringQueueSize () { return GetConfiguration().monitoring.shm_options.shm_monitoring_queue_size; } + ECAL_API std::string GetShmMonitoringDomain () { return GetConfiguration().monitoring.shm_options.shm_monitoring_domain;} + ECAL_API bool GetDropOutOfOrderMessages () { return GetConfiguration().transport_layer.drop_out_of_order_messages; } } } } diff --git a/ecal/core/src/config/ecal_config_initializer.cpp b/ecal/core/src/config/ecal_config_initializer.cpp new file mode 100644 index 0000000000..2441eccd40 --- /dev/null +++ b/ecal/core/src/config/ecal_config_initializer.cpp @@ -0,0 +1,271 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Function definitions for setting default config values +**/ + +#include "ecal/ecal_config.h" + +#include "ecal_global_accessors.h" +#include "ecal_def.h" +#include "config/ecal_config_reader.h" + +#include "ecal/ecal_process.h" +#include "config/ecal_cmd_parser.h" + +#include + +constexpr const char* COMMON = "common"; +constexpr const char* MONITORING = "monitoring"; +constexpr const char* NETWORK = "network"; +constexpr const char* EXPERIMENTAL = "experimental"; +constexpr const char* PUBLISHER = "publisher"; +constexpr const char* SYS = "sys"; +constexpr const char* TIME = "time"; +constexpr const char* SERVICE = "service"; +constexpr const char* PROCESS = "process"; + +namespace { + void tokenize(const std::string& str, std::vector& tokens, + const std::string& delimiters = " ", bool trimEmpty = false) + { + std::string::size_type pos = 0; + std::string::size_type lastPos = 0; + + for (;;) + { + pos = str.find_first_of(delimiters, lastPos); + if (pos == std::string::npos) + { + pos = str.length(); + if (pos != lastPos || !trimEmpty) + { + tokens.emplace_back(str.data() + lastPos, pos - lastPos); + } + break; + } + else + { + if (pos != lastPos || !trimEmpty) + { + tokens.emplace_back(str.data() + lastPos, pos - lastPos); + } + } + lastPos = pos + 1; + } + } + + eCAL_Logging_Filter ParseLogLevel(const std::string& filter_) + { + // tokenize it + std::vector token_filter_; + tokenize(filter_, token_filter_, " ,;"); + // create excluding filter list + char filter_mask = log_level_none; + for (auto& it : token_filter_) + { + if (it == "all") filter_mask |= log_level_all; + if (it == "info") filter_mask |= log_level_info; + if (it == "warning") filter_mask |= log_level_warning; + if (it == "error") filter_mask |= log_level_error; + if (it == "fatal") filter_mask |= log_level_fatal; + if (it == "debug1") filter_mask |= log_level_debug1; + if (it == "debug2") filter_mask |= log_level_debug2; + if (it == "debug3") filter_mask |= log_level_debug3; + if (it == "debug4") filter_mask |= log_level_debug4; + } + return(filter_mask); + }; +} + +namespace eCAL +{ + void Configuration::InitConfig(std::string ini_path_ /*= std::string("")*/) + { + CConfig iniConfig; + if (!command_line_arguments.config_keys.empty()) + iniConfig.OverwriteKeys(command_line_arguments.config_keys); + + if (!ini_path_.empty()) + { + iniConfig.AddFile(ini_path_); + ecal_ini_file_path = ini_path_; + } + + // transport layer options + auto& transportLayerOptions = transport_layer; + transportLayerOptions.network_enabled = iniConfig.get(NETWORK, "network_enabled", NET_ENABLED); + transportLayerOptions.drop_out_of_order_messages = iniConfig.get(EXPERIMENTAL, "drop_out_of_order_messages", EXP_DROP_OUT_OF_ORDER_MESSAGES); + + auto& multicastOptions = transportLayerOptions.mc_options; + + const std::string udp_config_version_string = iniConfig.get(NETWORK, "multicast_config_version", "v1"); + if (udp_config_version_string == "v1") + multicastOptions.config_version = Types::UdpConfigVersion::V1; + if (udp_config_version_string == "v2") + multicastOptions.config_version = Types::UdpConfigVersion::V2; + + multicastOptions.group = iniConfig.get(NETWORK, "multicast_group", NET_UDP_MULTICAST_GROUP); + multicastOptions.mask = iniConfig.get(NETWORK, "multicast_mask", NET_UDP_MULTICAST_MASK); + multicastOptions.port = iniConfig.get(NETWORK, "multicast_port", NET_UDP_MULTICAST_PORT); + multicastOptions.ttl = iniConfig.get(NETWORK, "multicast_ttl", NET_UDP_MULTICAST_TTL); + multicastOptions.recbuf = iniConfig.get(NETWORK, "multicast_rcvbuf", NET_UDP_MULTICAST_RCVBUF); + multicastOptions.sndbuf = iniConfig.get(NETWORK, "multicast_sndbuf", NET_UDP_MULTICAST_SNDBUF); + multicastOptions.join_all_interfaces = iniConfig.get(NETWORK, "multicast_join_all_if", NET_UDP_MULTICAST_JOIN_ALL_IF_ENABLED); + multicastOptions.npcap_enabled = iniConfig.get(NETWORK, "npcap_enabled", NET_NPCAP_ENABLED); + + auto& tcpPubSubOptions = transportLayerOptions.tcp_options; + tcpPubSubOptions.num_executor_reader = iniConfig.get(NETWORK, "tcp_pubsup_num_executor_reader", NET_TCP_PUBSUB_NUM_EXECUTOR_READER); + tcpPubSubOptions.num_executor_writer = iniConfig.get(NETWORK, "tcp_pubsup_num_executor_writer", NET_TCP_PUBSUB_NUM_EXECUTOR_WRITER); + tcpPubSubOptions.max_reconnections = iniConfig.get(NETWORK, "tcp_pubsup_max_reconnections", NET_TCP_PUBSUB_MAX_RECONNECTIONS); + + auto& shmOptions = transportLayerOptions.shm_options; + shmOptions.host_group_name = iniConfig.get(NETWORK, "host_group_name", NET_HOST_GROUP_NAME); + shmOptions.memfile_minsize = iniConfig.get(PUBLISHER, "memfile_minsize", PUB_MEMFILE_MINSIZE); + shmOptions.memfile_reserve = iniConfig.get(PUBLISHER, "memfile_reserve", PUB_MEMFILE_RESERVE); + shmOptions.memfile_ack_timeout = iniConfig.get(PUBLISHER, "memfile_ack_timeout", PUB_MEMFILE_ACK_TO); + shmOptions.memfile_buffer_count = iniConfig.get(PUBLISHER, "memfile_buffer_count", PUB_MEMFILE_BUF_COUNT); + shmOptions.drop_out_of_order_messages = iniConfig.get(EXPERIMENTAL, "drop_out_of_order_messages", EXP_DROP_OUT_OF_ORDER_MESSAGES); + shmOptions.memfile_zero_copy = iniConfig.get(PUBLISHER, "memfile_zero_copy", PUB_MEMFILE_ZERO_COPY); + + // registration options + auto registrationTimeout = iniConfig.get(COMMON, "registration_timeout", CMN_REGISTRATION_TO); + auto registrationRefresh = iniConfig.get(COMMON, "registration_refresh", CMN_REGISTRATION_REFRESH); + registration = Registration::Configuration(registrationTimeout, registrationRefresh); + auto& registrationOptions = registration; + registrationOptions.share_tdesc = iniConfig.get(PUBLISHER, "share_tdesc", PUB_SHARE_TDESC); + registrationOptions.share_ttype = iniConfig.get(PUBLISHER, "share_ttype", PUB_SHARE_TTYPE); + + // monitoring options + auto& monitoringOptions = monitoring; + auto monitoringMode = iniConfig.get(EXPERIMENTAL, "shm_monitoring_enabled", false) ? Monitoring::Types::Mode::shm_monitoring : Monitoring::Types::Mode::none; + monitoringOptions.monitoring_mode = static_cast(monitoringMode); + monitoringOptions.monitoring_timeout = iniConfig.get(MONITORING, "timeout", MON_TIMEOUT);; + monitoringOptions.network_monitoring = iniConfig.get(EXPERIMENTAL, "network_monitoring", EXP_NETWORK_MONITORING_ENABLED); + monitoringOptions.filter_excl = iniConfig.get(MONITORING, "filter_excl", MON_FILTER_EXCL); + monitoringOptions.filter_incl = iniConfig.get(MONITORING, "filter_incl", MON_FILTER_INCL); + + // auto& udpMonitoringOptions = monitoringOptions.udp_options; + // TODO: Nothing here yet + + auto& shmMonitoringOptions = monitoringOptions.shm_options; + shmMonitoringOptions.shm_monitoring_domain = iniConfig.get(EXPERIMENTAL, "shm_monitoring_domain", EXP_SHM_MONITORING_DOMAIN); + shmMonitoringOptions.shm_monitoring_queue_size = iniConfig.get(EXPERIMENTAL, "shm_monitoring_queue_size", EXP_SHM_MONITORING_QUEUE_SIZE); + + // subscriber options + auto& subscriberOptions = subscriber; + subscriberOptions.shm.enable = iniConfig.get(NETWORK, "shm_rec_enabled", NET_SHM_REC_ENABLED) != 0; + subscriberOptions.tcp.enable = iniConfig.get(NETWORK, "tcp_rec_enabled", NET_TCP_REC_ENABLED) != 0; + subscriberOptions.udp.enable = iniConfig.get(NETWORK, "udp_mc_rec_enabled", NET_UDP_MC_REC_ENABLED) != 0; + + // publisher options + auto& publisherOptions = publisher; + publisherOptions.shm.enable = iniConfig.get(PUBLISHER, "use_shm", static_cast(PUB_USE_SHM)) != 0; + publisherOptions.shm.zero_copy_mode = iniConfig.get(PUBLISHER, "memfile_zero_copy", PUB_MEMFILE_ZERO_COPY); + publisherOptions.shm.acknowledge_timeout_ms = iniConfig.get(PUBLISHER, "memfile_ack_timeout", PUB_MEMFILE_ACK_TO); + publisherOptions.shm.memfile_min_size_bytes = iniConfig.get(PUBLISHER, "memfile_minsize", PUB_MEMFILE_MINSIZE); + publisherOptions.shm.memfile_reserve_percent = iniConfig.get(PUBLISHER, "memfile_reserve", PUB_MEMFILE_RESERVE); + publisherOptions.shm.memfile_buffer_count = iniConfig.get(PUBLISHER, "memfile_buffer_count", PUB_MEMFILE_BUF_COUNT); + + publisherOptions.udp.enable = iniConfig.get(PUBLISHER, "use_udp_mc", static_cast(PUB_USE_UDP_MC)) != 0; + // TODO PG: Add here when its available in config file + publisherOptions.udp.loopback = false; + publisherOptions.udp.sndbuf_size_bytes = iniConfig.get(NETWORK, "multicast_sndbuf", NET_UDP_MULTICAST_SNDBUF); + + publisherOptions.share_topic_description = iniConfig.get(PUBLISHER, "share_tdesc", PUB_SHARE_TDESC); + publisherOptions.share_topic_type = iniConfig.get(PUBLISHER, "share_ttype", PUB_SHARE_TTYPE); + + publisherOptions.tcp.enable = iniConfig.get(PUBLISHER, "use_tcp", static_cast(PUB_USE_TCP)) != 0; + + // timesync options + auto& timesyncOptions = timesync; + timesyncOptions.timesync_module_rt = iniConfig.get(TIME, "timesync_module_rt", TIME_SYNC_MODULE); + timesyncOptions.timesync_module_replay = iniConfig.get(TIME, "timesync_module_replay", TIME_SYNC_MOD_REPLAY); + + // service options + auto& serviceOptions = service; + serviceOptions.protocol_v0 = iniConfig.get(SERVICE, "protocol_v0", SERVICE_PROTOCOL_V0); + serviceOptions.protocol_v1 = iniConfig.get(SERVICE, "protocol_v1", SERVICE_PROTOCOL_V1); + + // sys options + auto& sysConfig = application.sys; + sysConfig.filter_excl = iniConfig.get(SYS, "filter_excl", SYS_FILTER_EXCL); + + // process options + auto& startupConfig = application.startup; + startupConfig.terminal_emulator = iniConfig.get(PROCESS, "terminal_emulator", PROCESS_TERMINAL_EMULATOR); + + auto& loggingOptions = logging; + // needs to be adapted when switching from simpleini + loggingOptions.filter_log_con = ParseLogLevel(iniConfig.get(MONITORING, "filter_log_con", "info,warning,error,fatal")); + loggingOptions.filter_log_file = ParseLogLevel(iniConfig.get(MONITORING, "filter_log_file", "")); + loggingOptions.filter_log_udp = ParseLogLevel(iniConfig.get(MONITORING, "filter_log_udp", "info,warning,error,fatal")); + }; + + Configuration::Configuration(int argc_ , char **argv_) + { + std::vector arguments; + if (argc_ > 0 && argv_ != nullptr) + { + for (size_t i = 0; i < static_cast(argc_); ++i) + if (argv_[i] != nullptr) + arguments.emplace_back(argv_[i]); + } + Init(arguments); + } + + Configuration::Configuration(std::vector& args_) + { + Init(args_); + } + + void Configuration::Init(std::vector& arguments_) + { + Config::CmdParser parser(arguments_); + + command_line_arguments.config_keys = parser.getConfigKeys(); + command_line_arguments.specified_config = parser.getUserIni(); + command_line_arguments.dump_config = parser.getDumpConfig(); + command_line_arguments.config_keys_map = parser.getConfigKeysMap(); + + InitConfig(command_line_arguments.specified_config); + } + + void Configuration::InitConfigWithDefaultIni() + { + InitConfig(g_default_ini_file); + } + + Configuration::Configuration() + : Configuration(0, nullptr) + { + InitConfig(); + } + + std::string Configuration::GetIniFilePath() + { + return ecal_ini_file_path; + } + + Configuration& GetConfiguration() + { + return g_ecal_configuration; + }; +} \ No newline at end of file diff --git a/ecal/core/src/config/ecal_config_reader.cpp b/ecal/core/src/config/ecal_config_reader.cpp index cefe229658..7b4be4de19 100644 --- a/ecal/core/src/config/ecal_config_reader.cpp +++ b/ecal/core/src/config/ecal_config_reader.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -292,9 +292,33 @@ namespace eCAL void OverwriteKeys(const std::vector& key_vec_) { m_overwrite_keys = key_vec_; + OverwriteKeysNow(); } - void AddFile(std::string& file_name_) + void OverwriteKeysNow() + { + // update command line keys + for (const auto& full_key : m_overwrite_keys) + { + auto sec_pos = full_key.find_last_of('/'); + if (sec_pos == std::string::npos) continue; + const std::string section = full_key.substr(0, sec_pos); + std::string key = full_key.substr(sec_pos+1); + + auto val_pos = key.find_first_of(':'); + if (val_pos == std::string::npos) continue; + const std::string value = key.substr(val_pos+1); + key = key.substr(0, val_pos); + + const SI_Error err = SetValue(section.c_str(), key.c_str(), value.c_str()); + if (err == SI_FAIL) + { + std::cout << "Error: Could not overwrite key " << key << " in section " << section << "."; + } + } + } + + bool AddFile(std::string& file_name_) { std::string cfg_fname = file_name_; if (!fileexists(cfg_fname)) @@ -321,25 +345,9 @@ namespace eCAL file_name_ = cfg_fname; } - // update command line keys - for (const auto& full_key : m_overwrite_keys) - { - auto sec_pos = full_key.find_last_of('/'); - if (sec_pos == std::string::npos) continue; - const std::string section = full_key.substr(0, sec_pos); - std::string key = full_key.substr(sec_pos+1); - - auto val_pos = key.find_first_of(':'); - if (val_pos == std::string::npos) continue; - const std::string value = key.substr(val_pos+1); - key = key.substr(0, val_pos); + OverwriteKeysNow(); - const SI_Error err = SetValue(section.c_str(), key.c_str(), value.c_str()); - if (err == SI_FAIL) - { - std::cout << "Error: Could not overwrite key " << key << " in section " << section << "."; - } - } + return loaded; } protected: std::vector m_overwrite_keys; @@ -379,9 +387,9 @@ namespace eCAL m_impl->OverwriteKeys(key_vec_); } - void CConfig::AddFile(std::string& ini_file_) + bool CConfig::AddFile(std::string& ini_file_) { - m_impl->AddFile(ini_file_); + return m_impl->AddFile(ini_file_); } bool CConfig::Validate() @@ -444,24 +452,4 @@ namespace eCAL { return m_impl->GetValue(section_.c_str(), key_.c_str(), default_); } - - bool CfgGetBool(const std::string& section_, const std::string& key_, bool default_ /*= false*/) - { - return g_config()->get(section_, key_, default_); - } - - int CfgGetInt(const std::string& section_, const std::string& key_, int default_ /*= 0*/) - { - return g_config()->get(section_, key_, default_); - } - - double CfgGetDouble(const std::string& section_, const std::string& key_, double default_ /*= 0.0*/) - { - return g_config()->get(section_, key_, default_); - } - - std::string CfgGetString(const std::string& section_, const std::string& key_, const char* default_ /*= ""*/) - { - return g_config()->get(section_, key_, default_); - } } diff --git a/ecal/core/src/config/ecal_config_reader.h b/ecal/core/src/config/ecal_config_reader.h index d1bbca0a45..a08fbea310 100644 --- a/ecal/core/src/config/ecal_config_reader.h +++ b/ecal/core/src/config/ecal_config_reader.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ namespace eCAL virtual ~CConfig(); void OverwriteKeys(const std::vector& key_vec_); - void AddFile(std::string& ini_file_); + bool AddFile(std::string& ini_file_); bool Validate(); @@ -54,9 +54,4 @@ namespace eCAL private: std::unique_ptr m_impl; }; - - ECAL_API bool CfgGetBool (const std::string& section_, const std::string& key_, bool default_ = false); - ECAL_API int CfgGetInt (const std::string& section_, const std::string& key_, int default_ = 0); - ECAL_API double CfgGetDouble(const std::string& section_, const std::string& key_, double default_ = 0.0); - ECAL_API std::string CfgGetString(const std::string& section_, const std::string& key_, const char* default_ = ""); } diff --git a/ecal/core/src/ecal.cpp b/ecal/core/src/ecal.cpp index 7fa088e7d7..03c2e1a434 100644 --- a/ecal/core/src/ecal.cpp +++ b/ecal/core/src/ecal.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include "ecal_def.h" #include "ecal_event.h" #include "ecal_globals.h" +#include "config/ecal_cmd_parser.h" #include #include @@ -99,116 +100,71 @@ namespace eCAL **/ int Initialize(int argc_ , char **argv_, const char *unit_name_, unsigned int components_) { - bool dump_config(false); - std::vector config_keys; - -#if ECAL_CORE_COMMAND_LINE - if ((argc_ > 0) && (argv_ != nullptr)) - { - // define command line object - TCLAP::CmdLine cmd("", ' ', ECAL_VERSION); - - // define command line arguments - TCLAP::SwitchArg dump_config_arg ("", "ecal-dump-config", "Dump current configuration.", false); - TCLAP::ValueArg default_ini_file_arg("", "ecal-ini-file", "Load default configuration from that file.", false, ECAL_DEFAULT_CFG, "string"); - TCLAP::MultiArg set_config_key_arg ("", "ecal-set-config-key", "Overwrite a specific configuration key (ecal-set-config-key \"section/key:value\".", false, "string"); - - TCLAP::UnlabeledMultiArg dummy_arg("__dummy__", "Dummy", false, ""); // Dummy arg to eat all unrecognized arguments + eCAL::Configuration config(argc_, argv_); + + // Default behaviour: If not specified, try to use the default ini file + if (config.GetIniFilePath().empty()) + config.InitConfigWithDefaultIni(); - cmd.add(dump_config_arg); - cmd.add(default_ini_file_arg); - cmd.add(set_config_key_arg); - cmd.add(dummy_arg); + return Initialize(config, unit_name_, components_); + } - CustomTclap::AdvancedTclapOutput advanced_tclap_output(&std::cout, 75); - advanced_tclap_output.setArgumentHidden(&dummy_arg, true); - cmd.setOutput(&advanced_tclap_output); + /** + * @brief Initialize eCAL API. + * + * @param args_ Vector of config arguments to overwrite (["arg1", "value1", "arg2", "arg3", "value3" ..]). + * @param unit_name_ Defines the name of the eCAL unit. + * @param components_ Defines which component to initialize. + * + * @return Zero if succeeded, 1 if already initialized, -1 if failed. + **/ + int Initialize(std::vector args_, const char *unit_name_, unsigned int components_) //-V826 + { + eCAL::Configuration config(args_); + + // Default behaviour: If not specified, try to use the default ini file + if (config.GetIniFilePath().empty()) + config.InitConfigWithDefaultIni(); - // parse command line - cmd.parse(argc_, argv_); + return Initialize(config, unit_name_, components_); + } - // set globals - if (dump_config_arg.isSet()) - { - dump_config = true; - } - if (default_ini_file_arg.isSet()) - { - g_default_ini_file = default_ini_file_arg.getValue(); - } - if (set_config_key_arg.isSet()) - { - config_keys = set_config_key_arg.getValue(); - } + /** + * @brief Initialize eCAL API. + * + * @param config_ User defined configuration object. + * @param unit_name_ Defines the name of the eCAL unit. + * @param components_ Defines which component to initialize. + * + * @return Zero if succeeded, 1 if already initialized, -1 if failed. + **/ + int Initialize(eCAL::Configuration& config_, const char *unit_name_ /*= nullptr*/, unsigned int components_ /*= Init::Default*/) + { + if (g_globals() == nullptr) + { + InitGlobals(); } -#endif + + g_ecal_configuration = config_; - // first call - if (g_globals_ctx == nullptr) + if (unit_name_ != nullptr) { - g_globals_ctx = new CGlobals; - - if(unit_name_ != nullptr) g_unit_name = unit_name_; - if (g_unit_name.empty()) - { - g_unit_name = Process::GetProcessName(); -#ifdef ECAL_OS_WINDOWS - size_t p = g_unit_name.rfind('\\'); - if (p != std::string::npos) - { - g_unit_name = g_unit_name.substr(p+1); - } - p = g_unit_name.rfind('.'); - if (p != std::string::npos) - { - g_unit_name = g_unit_name.substr(0, p); - } -#endif -#ifdef ECAL_OS_LINUX - size_t p = g_unit_name.rfind('/'); - if (p != std::string::npos) - { - g_unit_name = g_unit_name.substr(p + 1); - } -#endif - } - - if (argv_ != nullptr) - { - for (size_t i = 0; i < static_cast(argc_); ++i) if (argv_[i] != nullptr) g_task_parameter.emplace_back(argv_[i]); - } + SetGlobalUnitName(unit_name_); } + g_globals_ctx_ref_cnt++; - // (post)initialize single components - const int success = g_globals()->Initialize(components_, &config_keys); + // (post)initialize single components + const int success = g_globals()->Initialize(components_, &GetConfiguration().command_line_arguments.config_keys); - // print out configuration - if (dump_config) + if (config_.command_line_arguments.dump_config) { Process::DumpConfig(); } - + return success; } - /** - * @brief Initialize eCAL API. - * - * @param args_ Vector of config arguments to overwrite (["arg1", "value1", "arg2", "arg3", "value3" ..]). - * @param unit_name_ Defines the name of the eCAL unit. - * @param components_ Defines which component to initialize. - * - * @return Zero if succeeded, 1 if already initialized, -1 if failed. - **/ - int Initialize(std::vector args_, const char *unit_name_, unsigned int components_) //-V826 - { - args_.emplace(args_.begin(), eCAL::Process::GetProcessName()); - std::vector argv(args_.size()); - std::transform(args_.begin(), args_.end(), argv.begin(), [](std::string& s) {return s.c_str();}); - return Initialize(static_cast(argv.size()), const_cast(argv.data()), unit_name_, components_); - } - /** * @brief Check eCAL initialize state. * diff --git a/ecal/core/src/ecal_def.h b/ecal/core/src/ecal_def.h index ada5beb82e..a9c6789d0a 100644 --- a/ecal/core/src/ecal_def.h +++ b/ecal/core/src/ecal_def.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,9 @@ #pragma once +#include +#include +#include #include /**********************************************************************************************/ @@ -48,9 +51,9 @@ constexpr const char* MON_FILTER_EXCL = "^__.*$"; constexpr const char* MON_FILTER_INCL = ""; /* logging filter settings */ -constexpr const char* MON_LOG_FILTER_CON = "info,warning,error,fatal"; -constexpr const char* MON_LOG_FILTER_FILE = ""; -constexpr const char* MON_LOG_FILTER_UDP = "info,warning,error,fatal"; +constexpr eCAL_Logging_Filter MON_LOG_FILTER_CON = (log_level_info | log_level_warning | log_level_error | log_level_fatal); +constexpr eCAL_Logging_Filter MON_LOG_FILTER_FILE = log_level_none; +constexpr eCAL_Logging_Filter MON_LOG_FILTER_UDP = (log_level_info | log_level_warning | log_level_error | log_level_fatal); /**********************************************************************************************/ @@ -66,17 +69,17 @@ constexpr const char* SYS_FILTER_EXCL = "^eCALSysClient$|^eCALSysGUI$|^eCALS constexpr bool NET_ENABLED = false; /* eCAL udp multicast defines */ -constexpr const char* NET_UDP_MULTICAST_CONFIG_VERSION = "v1"; -constexpr const char* NET_UDP_MULTICAST_GROUP = "239.0.0.1"; -constexpr const char* NET_UDP_MULTICAST_MASK = "0.0.0.15"; -constexpr unsigned int NET_UDP_MULTICAST_PORT = 14000U; -constexpr unsigned int NET_UDP_MULTICAST_TTL = 3U; -constexpr unsigned int NET_UDP_MULTICAST_PORT_REG_OFF = 0U; -constexpr unsigned int NET_UDP_MULTICAST_PORT_LOG_OFF = 1U; -constexpr unsigned int NET_UDP_MULTICAST_PORT_SAMPLE_OFF = 2U; -constexpr unsigned int NET_UDP_MULTICAST_SNDBUF = (5U*1024U*1024U); /* 5 MByte */ -constexpr unsigned int NET_UDP_MULTICAST_RCVBUF = (5U*1024U*1024U); /* 5 MByte */ -constexpr bool NET_UDP_MULTICAST_JOIN_ALL_IF_ENABLED = false; +constexpr eCAL::Types::UdpConfigVersion NET_UDP_MULTICAST_CONFIG_VERSION = eCAL::Types::UdpConfigVersion::V1; +constexpr const char* NET_UDP_MULTICAST_GROUP = "239.0.0.1"; +constexpr const char* NET_UDP_MULTICAST_MASK = "0.0.0.15"; +constexpr unsigned int NET_UDP_MULTICAST_PORT = 14000U; +constexpr unsigned int NET_UDP_MULTICAST_TTL = 3U; +constexpr unsigned int NET_UDP_MULTICAST_PORT_REG_OFF = 0U; +constexpr unsigned int NET_UDP_MULTICAST_PORT_LOG_OFF = 1U; +constexpr unsigned int NET_UDP_MULTICAST_PORT_SAMPLE_OFF = 2U; +constexpr unsigned int NET_UDP_MULTICAST_SNDBUF = (5U*1024U*1024U); /* 5 MByte */ +constexpr unsigned int NET_UDP_MULTICAST_RCVBUF = (5U*1024U*1024U); /* 5 MByte */ +constexpr bool NET_UDP_MULTICAST_JOIN_ALL_IF_ENABLED = false; constexpr unsigned int NET_UDP_RECBUFFER_TIMEOUT = 1000U; /* ms */ constexpr unsigned int NET_UDP_RECBUFFER_CLEANUP = 10U; /* ms */ @@ -102,16 +105,16 @@ constexpr const char* NET_HOST_GROUP_NAME = ""; /* publisher settings */ /**********************************************************************************************/ /* use shared memory transport layer [auto = 2, on = 1, off = 0] */ -constexpr unsigned int PUB_USE_SHM = 2U; +constexpr eCAL::TLayer::eSendMode PUB_USE_SHM = eCAL::TLayer::eSendMode::smode_auto; /* use tcp transport layer [auto = 2, on = 1, off = 0] */ -constexpr unsigned int PUB_USE_TCP = 0U; +constexpr eCAL::TLayer::eSendMode PUB_USE_TCP = eCAL::TLayer::eSendMode::smode_off; /* use udp multicast transport layer [auto = 2, on = 1, off = 0] */ -constexpr unsigned int PUB_USE_UDP_MC = 2U; +constexpr eCAL::TLayer::eSendMode PUB_USE_UDP_MC = eCAL::TLayer::eSendMode::smode_auto; /* share topic type [ on = 1, off = 0] */ -constexpr unsigned int PUB_SHARE_TTYPE = 1U; +constexpr bool PUB_SHARE_TTYPE = true; /* share topic description [ on = 1, off = 0] */ -constexpr unsigned int PUB_SHARE_TDESC = 1U; +constexpr bool PUB_SHARE_TDESC = true; /* minimum size for created shared memory files */ constexpr unsigned int PUB_MEMFILE_MINSIZE = (4U*1024U); @@ -137,22 +140,23 @@ constexpr unsigned int PUB_MEMFILE_BUF_COUNT = 1U; this memory file is blocked for other readers wihle processed by the user callback function this option is fully IPC compatible to all eCAL 5.x versions */ -constexpr unsigned int PUB_MEMFILE_ZERO_COPY = 0U; +constexpr bool PUB_MEMFILE_ZERO_COPY = false; /**********************************************************************************************/ /* service settings */ /**********************************************************************************************/ /* support service protocol v0, eCAL 5.11 and older (0 = off, 1 = on) */ -constexpr unsigned int SERVICE_PROTOCOL_V0 = 1U; +constexpr bool SERVICE_PROTOCOL_V0 = true; /* support service protocol v1, eCAL 5.12 and newer (0 = off, 1 = on) */ -constexpr unsigned int SERVICE_PROTOCOL_V1 = 1U; +constexpr bool SERVICE_PROTOCOL_V1 = true; /**********************************************************************************************/ /* time settings */ /**********************************************************************************************/ constexpr const char* TIME_SYNC_MOD_RT = ""; constexpr const char* TIME_SYNC_MOD_REPLAY = ""; +constexpr const char* TIME_SYNC_MODULE = "ecaltime-localtime"; /**********************************************************************************************/ /* process settings */ @@ -185,8 +189,8 @@ constexpr const char* EVENT_SHUTDOWN_PROC = "ecal_shutdown_pro /**********************************************************************************************/ /* enable distribution of monitoring/registration information via shared memory */ constexpr bool EXP_SHM_MONITORING_ENABLED = false; -/* disable distribution of monitoring/registration information via network (default) */ -constexpr bool EXP_NETWORK_MONITORING_DISABLED = false; +/* enable distribution of monitoring/registration information via network (default) */ +constexpr bool EXP_NETWORK_MONITORING_ENABLED = true; /* queue size of monitoring/registration events */ constexpr unsigned int EXP_SHM_MONITORING_QUEUE_SIZE = 1024U; /* domain name for shared memory based monitoring/registration */ @@ -196,3 +200,5 @@ constexpr unsigned int EXP_MEMFILE_ACCESS_TIMEOUT = 100U; /* enable dropping of payload messages that arrive out of order */ constexpr bool EXP_DROP_OUT_OF_ORDER_MESSAGES = false; + +constexpr eCAL::Monitoring::Types::Mode EXP_MONITORING_MODE = eCAL::Monitoring::Types::Mode::none; diff --git a/ecal/core/src/ecal_global_accessors.cpp b/ecal/core/src/ecal_global_accessors.cpp index 2f402cb920..eea548714e 100644 --- a/ecal/core/src/ecal_global_accessors.cpp +++ b/ecal/core/src/ecal_global_accessors.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ #include "ecal_global_accessors.h" #include "ecal_def.h" #include "ecal_globals.h" +#include "ecal/config/configuration.h" #include #include @@ -33,6 +34,7 @@ namespace eCAL std::atomic g_globals_ctx_ref_cnt; std::string g_default_ini_file(ECAL_DEFAULT_CFG); + Configuration g_ecal_configuration{}; std::string g_host_name; std::string g_unit_name; @@ -47,15 +49,45 @@ namespace eCAL eCAL_Process_eSeverity g_process_severity(eCAL_Process_eSeverity::proc_sev_unknown); eCAL_Process_eSeverity_Level g_process_severity_level(eCAL_Process_eSeverity_Level::proc_sev_level1); - CGlobals* g_globals() + void InitGlobals() { - return g_globals_ctx; + g_globals_ctx = new CGlobals; } - CConfig* g_config() + void SetGlobalUnitName(const char *unit_name_) { - if (g_globals() == nullptr) return(nullptr); - return(g_globals()->config().get()); + // There is a function already "SetUnitName" which sets the g_unit_name just as string. + // Used in global API. It does not have the following logic -> should that be added/removed/combined? + // For previous consistency this function is added here for the time being. + if(unit_name_ != nullptr) g_unit_name = unit_name_; + if (g_unit_name.empty()) + { + g_unit_name = Process::GetProcessName(); +#ifdef ECAL_OS_WINDOWS + size_t p = g_unit_name.rfind('\\'); + if (p != std::string::npos) + { + g_unit_name = g_unit_name.substr(p+1); + } + p = g_unit_name.rfind('.'); + if (p != std::string::npos) + { + g_unit_name = g_unit_name.substr(0, p); + } +#endif +#ifdef ECAL_OS_LINUX + const size_t p = g_unit_name.rfind('/'); + if (p != std::string::npos) + { + g_unit_name = g_unit_name.substr(p + 1); + } +#endif + } + }; + + CGlobals* g_globals() + { + return g_globals_ctx; } CLog* g_log() @@ -64,6 +96,11 @@ namespace eCAL return(g_globals()->log().get()); } + Configuration& g_ecal_config() + { + return(g_ecal_configuration); + } + #if ECAL_CORE_MONITORING CMonitoring* g_monitoring() { diff --git a/ecal/core/src/ecal_global_accessors.h b/ecal/core/src/ecal_global_accessors.h index 3ae00eda6d..a0d3516e1c 100644 --- a/ecal/core/src/ecal_global_accessors.h +++ b/ecal/core/src/ecal_global_accessors.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,9 +31,10 @@ // Forward declaration of global accessible classes namespace eCAL { - class CGlobals; - class CConfig; - class CLog; + class CGlobals; + class CLog; + struct Configuration; + #if ECAL_CORE_MONITORING class CMonitoring; #endif @@ -60,9 +61,11 @@ namespace eCAL class CMemFileMap; #endif + void SetGlobalUnitName(const char *unit_name_); + void InitGlobals(); + // Declaration of getter functions for globally accessible variable instances CGlobals* g_globals(); - CConfig* g_config(); CLog* g_log(); #if ECAL_CORE_MONITORING CMonitoring* g_monitoring(); @@ -88,6 +91,7 @@ namespace eCAL #if defined(ECAL_CORE_REGISTRATION_SHM) || defined(ECAL_CORE_TRANSPORT_SHM) CMemFileThreadPool* g_memfile_pool(); CMemFileMap* g_memfile_map(); + #endif // declaration of globally accessible variables @@ -95,6 +99,7 @@ namespace eCAL extern std::atomic g_globals_ctx_ref_cnt; extern std::string g_default_ini_file; + extern Configuration g_ecal_configuration; extern std::string g_host_name; extern std::string g_unit_name; diff --git a/ecal/core/src/ecal_globals.cpp b/ecal/core/src/ecal_globals.cpp index 778005b86d..088bfc60ec 100644 --- a/ecal/core/src/ecal_globals.cpp +++ b/ecal/core/src/ecal_globals.cpp @@ -50,36 +50,6 @@ namespace eCAL // will be set if any new module was initialized bool new_initialization(false); - ///////////////////// - // CONFIG - ///////////////////// - if (config_instance == nullptr) - { - config_instance = std::make_unique(); - if (config_keys_ != nullptr) - { - config_instance->OverwriteKeys(*config_keys_); - } - config_instance->AddFile(g_default_ini_file); - - if (!config_instance->Validate()) - { - const std::string emsg("Core initialization failed cause by a configuration error."); - - std::cerr << '\n'; - std::cerr << "----------------------------------------------------------" << '\n'; - std::cerr << "eCAL CORE PANIC :-(" << '\n'; - std::cerr << '\n'; - std::cerr << emsg << '\n'; - std::cerr << "----------------------------------------------------------" << '\n'; - std::cerr << '\n'; - - throw std::runtime_error(emsg.c_str()); - } - - new_initialization = true; - } - #if ECAL_CORE_REGISTRATION ///////////////////// // REGISTRATION PROVIDER @@ -377,8 +347,6 @@ namespace eCAL memfile_map_instance = nullptr; #endif log_instance = nullptr; - config_instance = nullptr; - initialized = false; return(0); diff --git a/ecal/core/src/ecal_globals.h b/ecal/core/src/ecal_globals.h index 6feda75a84..dc5eaed714 100644 --- a/ecal/core/src/ecal_globals.h +++ b/ecal/core/src/ecal_globals.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,13 +63,13 @@ namespace eCAL int Initialize ( unsigned int components_, std::vector* config_keys_ = nullptr); bool IsInitialized ( unsigned int component_ ); - + unsigned int GetComponents() const { return(components); }; int Finalize(); - const std::unique_ptr& config() { return config_instance; }; const std::unique_ptr& log() { return log_instance; }; + #if ECAL_CORE_MONITORING const std::unique_ptr& monitoring() { return monitoring_instance; }; #endif @@ -93,13 +93,13 @@ namespace eCAL #if defined(ECAL_CORE_REGISTRATION_SHM) || defined(ECAL_CORE_TRANSPORT_SHM) const std::unique_ptr& memfile_pool() { return memfile_pool_instance; }; const std::unique_ptr& memfile_map() { return memfile_map_instance; }; + #endif const std::unique_ptr& descgate() { return descgate_instance; }; private: bool initialized; unsigned int components; - std::unique_ptr config_instance; std::unique_ptr log_instance; #if ECAL_CORE_MONITORING std::unique_ptr monitoring_instance; @@ -124,6 +124,7 @@ namespace eCAL #if defined(ECAL_CORE_REGISTRATION_SHM) || defined(ECAL_CORE_TRANSPORT_SHM) std::unique_ptr memfile_pool_instance; std::unique_ptr memfile_map_instance; + #endif std::unique_ptr descgate_instance; }; diff --git a/ecal/core/src/ecal_process.cpp b/ecal/core/src/ecal_process.cpp index fab2a446bd..20c26b45e5 100644 --- a/ecal/core/src/ecal_process.cpp +++ b/ecal/core/src/ecal_process.cpp @@ -193,7 +193,7 @@ namespace eCAL #if ECAL_CORE_TIMEPLUGIN sstream << "------------------------- TIME -----------------------------------" << '\n'; sstream << "Synchronization realtime : " << Config::GetTimesyncModuleName() << '\n'; - sstream << "Synchronization replay : " << eCALPAR(TIME, SYNC_MOD_REPLAY) << '\n'; + sstream << "Synchronization replay : " << Config::GetTimesyncModuleReplay() << '\n'; sstream << "State : "; if (g_timegate()->IsSynchronized()) sstream << " synchronized " << '\n'; else sstream << " not synchronized " << '\n'; diff --git a/ecal/core/src/io/udp/ecal_udp_configurations.cpp b/ecal/core/src/io/udp/ecal_udp_configurations.cpp index 589da3874b..d3e81cf46a 100644 --- a/ecal/core/src/io/udp/ecal_udp_configurations.cpp +++ b/ecal/core/src/io/udp/ecal_udp_configurations.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -140,7 +140,7 @@ namespace eCAL } // determine the UDP multicast configuration version - if (Config::GetUdpMulticastConfigVersion() == Config::UdpConfigVersion::V1) + if (Config::GetUdpMulticastConfigVersion() == Types::UdpConfigVersion::V1) { // retrieve the corresponding multicast address based on the topic name using v1 implementation return UDP::V1::topic2mcast(topic_name, Config::GetUdpMulticastGroup(), Config::GetUdpMulticastMask()); diff --git a/ecal/core/src/pubsub/ecal_publisher_config.cpp b/ecal/core/src/pubsub/ecal_publisher_config.cpp index 949980e690..ede5ddddd9 100644 --- a/ecal/core/src/pubsub/ecal_publisher_config.cpp +++ b/ecal/core/src/pubsub/ecal_publisher_config.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,32 +22,15 @@ **/ #include -#include +#include namespace eCAL { namespace Publisher { - Configuration::Configuration() : - share_topic_type(eCAL::Config::IsTopicTypeSharingEnabled()), - share_topic_description(eCAL::Config::IsTopicDescriptionSharingEnabled()) + Configuration::Configuration() { - // shm config - shm.enable = eCAL::Config::GetPublisherShmMode() != TLayer::eSendMode::smode_off; - shm.zero_copy_mode = eCAL::Config::IsMemfileZerocopyEnabled(); - shm.acknowledge_timeout_ms = eCAL::Config::GetMemfileAckTimeoutMs(); - - shm.memfile_min_size_bytes = eCAL::Config::GetMemfileMinsizeBytes(); - shm.memfile_reserve_percent = eCAL::Config::GetMemfileOverprovisioningPercentage(); - shm.memfile_buffer_count = eCAL::Config::GetMemfileBufferCount(); - - // udp config - udp.enable = eCAL::Config::GetPublisherUdpMulticastMode() != TLayer::eSendMode::smode_off; - udp.loopback = false; // TODO: make this configurable - udp.sndbuf_size_bytes = eCAL::Config::GetUdpMulticastSndBufSizeBytes(); - - // tcp config - tcp.enable = eCAL::Config::GetPublisherTcpMode() != TLayer::eSendMode::smode_off; + *this = GetConfiguration().publisher; } } } diff --git a/ecal/core/src/pubsub/ecal_subscriber_config.cpp b/ecal/core/src/pubsub/ecal_subscriber_config.cpp index 45a7becd78..1ecdea261f 100644 --- a/ecal/core/src/pubsub/ecal_subscriber_config.cpp +++ b/ecal/core/src/pubsub/ecal_subscriber_config.cpp @@ -22,7 +22,7 @@ **/ #include -#include +#include namespace eCAL { @@ -30,14 +30,7 @@ namespace eCAL { Configuration::Configuration() { - // shm config - shm.enable = eCAL::Config::IsShmRecEnabled(); - - // udp config - udp.enable = eCAL::Config::IsUdpMulticastRecEnabled(); - - // tcp config - tcp.enable = eCAL::Config::IsTcpRecEnabled(); + *this = GetConfiguration().subscriber; } } } diff --git a/ecal/core/src/readwrite/ecal_writer.h b/ecal/core/src/readwrite/ecal_writer.h index 019c06fd26..bc6919c08f 100644 --- a/ecal/core/src/readwrite/ecal_writer.h +++ b/ecal/core/src/readwrite/ecal_writer.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,8 @@ #include #include -#include +#include +#include #include #include "util/ecal_expmap.h" diff --git a/ecal/core/src/readwrite/shm/ecal_writer_shm.h b/ecal/core/src/readwrite/shm/ecal_writer_shm.h index 01517db79a..fd6dff0d93 100644 --- a/ecal/core/src/readwrite/shm/ecal_writer_shm.h +++ b/ecal/core/src/readwrite/shm/ecal_writer_shm.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ #pragma once -#include +#include #include "readwrite/ecal_writer_base.h" #include "io/shm/ecal_memfile_sync.h" diff --git a/ecal/core/src/readwrite/tcp/ecal_writer_tcp.h b/ecal/core/src/readwrite/tcp/ecal_writer_tcp.h index 6258ae280c..94a3e96fe7 100644 --- a/ecal/core/src/readwrite/tcp/ecal_writer_tcp.h +++ b/ecal/core/src/readwrite/tcp/ecal_writer_tcp.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ #pragma once -#include +#include #include "readwrite/ecal_writer_base.h" diff --git a/ecal/core/src/readwrite/udp/ecal_writer_udp.h b/ecal/core/src/readwrite/udp/ecal_writer_udp.h index a9b2d4eabc..32a7ef78b1 100644 --- a/ecal/core/src/readwrite/udp/ecal_writer_udp.h +++ b/ecal/core/src/readwrite/udp/ecal_writer_udp.h @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ #pragma once -#include +#include #include "io/udp/ecal_udp_sample_sender.h" #include "readwrite/ecal_writer_base.h" diff --git a/ecal/core/src/time/ecal_timegate.cpp b/ecal/core/src/time/ecal_timegate.cpp index 1d1495ed1d..bfca24c0d1 100644 --- a/ecal/core/src/time/ecal_timegate.cpp +++ b/ecal/core/src/time/ecal_timegate.cpp @@ -89,7 +89,7 @@ namespace eCAL m_successfully_loaded_rt = LoadModule(m_time_sync_modname, m_time_sync_rt); break; case eTimeSyncMode::replay: - m_time_sync_modname = eCALPAR(TIME, SYNC_MOD_REPLAY); + m_time_sync_modname = Config::GetTimesyncModuleReplay(); m_successfully_loaded_replay = LoadModule(m_time_sync_modname, m_time_sync_replay); break; } diff --git a/ecal/core/src/types/ecal_custom_data_types.cpp b/ecal/core/src/types/ecal_custom_data_types.cpp new file mode 100644 index 0000000000..5fbf5615cd --- /dev/null +++ b/ecal/core/src/types/ecal_custom_data_types.cpp @@ -0,0 +1,88 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Definition of custom data types. +**/ + +#include "ecal/types/ecal_custom_data_types.h" +#include +#include +#include +#include +#include + +namespace{ + const std::array INVALID_IPV4_ADDRESSES = { + std::regex("((255|[fF][fF])\\.){3}(255|[fF][fF])"), // 255.255.255.255 + std::regex("((127|7[fF]).((0|00|000)\\.){2}(1|01|001))"), // 127.0.0.1 + std::regex("((0|00|000)\\.){3}(0|00|000)") // 0.0.0.0 + }; + const std::regex IPV4_DEC_REGEX = std::regex("(([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"); + const std::regex IPV4_HEX_REGEX = std::regex("(([0-9a-fA-F]|[0-9a-fA-F][0-9a-fA-F])\\.){3}([0-9a-fA-F]|[0-9a-fA-F][0-9a-fA-F])"); +} + +namespace eCAL +{ + namespace Types + { + + // IpAddressV4 definitions + IpAddressV4::IpAddressV4() : IpAddressV4(NET_UDP_MULTICAST_GROUP) {}; + + IpAddressV4::IpAddressV4(const std::string& ip_address_) + { + validateIpString(ip_address_); + } + + void IpAddressV4::validateIpString(const std::string& ip_address_) + { + if ( std::regex_match(ip_address_, IPV4_DEC_REGEX) + || std::regex_match(ip_address_, IPV4_HEX_REGEX) + ) + { + for (const auto& inv_ip_regex : INVALID_IPV4_ADDRESSES) + { + if (std::regex_match(ip_address_, inv_ip_regex)) + { + throwException(ip_address_); + return; + } + } + + m_ip_address = ip_address_; + } + else + { + throwException(ip_address_); + } + } + + void IpAddressV4::throwException(const std::string& ip_address_ /*std::string("")*/) + { + throw std::invalid_argument("[IpAddressV4] No valid IP address: " + ip_address_); + } + + std::string IpAddressV4::Get() const { return m_ip_address; }; + IpAddressV4& IpAddressV4::operator=(const std::string& ip_string) { this->validateIpString(ip_string); return *this; }; + IpAddressV4::operator std::string() { return m_ip_address; }; + + std::ostream& operator<<(std::ostream& os, const IpAddressV4& ipv4) { os << ipv4.Get(); return os; }; + } +} diff --git a/ecal/core/src/types/ecal_registration_options.cpp b/ecal/core/src/types/ecal_registration_options.cpp new file mode 100644 index 0000000000..2454ca1d69 --- /dev/null +++ b/ecal/core/src/types/ecal_registration_options.cpp @@ -0,0 +1,56 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Definition of custom data types. +**/ + +#include +#include "ecal_def.h" + +namespace eCAL +{ + namespace Registration + { + Configuration::Configuration() + : share_ttype(PUB_SHARE_TTYPE) + , share_tdesc(PUB_SHARE_TDESC) + , m_registration_timeout(CMN_REGISTRATION_TO) + , m_registration_refresh(CMN_REGISTRATION_REFRESH) + {} + + Configuration::Configuration(unsigned int reg_timeout_, unsigned int reg_refresh_) + : share_ttype(PUB_SHARE_TTYPE) + , share_tdesc(PUB_SHARE_TDESC) + { + if (reg_refresh_ < reg_timeout_) + { + m_registration_timeout = reg_timeout_; + m_registration_refresh = reg_refresh_; + } + else + { + throw std::invalid_argument("[RegistrationOptions] Refresh(" + std::to_string(reg_refresh_) + ") >= registration timeout (" + std::to_string(reg_timeout_) + ")."); + } + } + + unsigned int Configuration::getTimeoutMS() const { return m_registration_timeout; } + unsigned int Configuration::getRefreshMS() const { return m_registration_refresh; } + } +} \ No newline at end of file diff --git a/ecal/samples/CMakeLists.txt b/ecal/samples/CMakeLists.txt index 14f3fed75d..ccb0f0a67c 100644 --- a/ecal/samples/CMakeLists.txt +++ b/ecal/samples/CMakeLists.txt @@ -71,6 +71,7 @@ endif() # misc add_subdirectory(cpp/misc/process) add_subdirectory(cpp/misc/time) +add_subdirectory(cpp/misc/config) if(ECAL_CORE_PUBLISHER) add_subdirectory(cpp/misc/timer) endif() diff --git a/ecal/samples/cpp/benchmarks/counter_rec/src/counter_rec.cpp b/ecal/samples/cpp/benchmarks/counter_rec/src/counter_rec.cpp index 3a323f100a..986371abfc 100644 --- a/ecal/samples/cpp/benchmarks/counter_rec/src/counter_rec.cpp +++ b/ecal/samples/cpp/benchmarks/counter_rec/src/counter_rec.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,9 @@ int main(int argc, char **argv) eCAL::Initialize(argc, argv, "counter_rec_cb"); // create subscriber for topic "Counter" - eCAL::CSubscriber sub("Counter", { "", "long long", "" }); + eCAL::SDataTypeInformation datatype_information; + datatype_information.encoding = "long long"; + eCAL::CSubscriber sub("Counter", datatype_information); // counter long long g_clock(0); diff --git a/ecal/samples/cpp/misc/config/CMakeLists.txt b/ecal/samples/cpp/misc/config/CMakeLists.txt new file mode 100644 index 0000000000..2aa52c6391 --- /dev/null +++ b/ecal/samples/cpp/misc/config/CMakeLists.txt @@ -0,0 +1,44 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2024 Continental 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. +# +# ========================= eCAL LICENSE ================================= + +cmake_minimum_required(VERSION 3.10) + +set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) + +project(config_sample) + +find_package(eCAL REQUIRED) + +set(config_src + src/config_sample.cpp +) + +ecal_add_sample(${PROJECT_NAME} ${config_src}) + +target_include_directories(${PROJECT_NAME} PRIVATE .) + +target_link_libraries (${PROJECT_NAME} + eCAL::core +) + +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) + +ecal_install_sample(${PROJECT_NAME}) + +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/misc) + diff --git a/ecal/samples/cpp/misc/config/src/config_sample.cpp b/ecal/samples/cpp/misc/config/src/config_sample.cpp new file mode 100644 index 0000000000..42ad2f27f0 --- /dev/null +++ b/ecal/samples/cpp/misc/config/src/config_sample.cpp @@ -0,0 +1,54 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +#include +#include + +#include + +int main(int argc, char **argv) +{ + // creating config object + eCAL::Configuration my_config(argc, argv); + + // setting configuration + my_config.monitoring.network_monitoring = true; + + // initialize eCAL API + eCAL::Initialize(my_config, "config sample"); + + unsigned int counter = 0; + // enter main loop + while(eCAL::Ok()) + { + // sleep 500 ms + eCAL::Process::SleepMS(500); + if (counter >= 10) + { + break; + } + + std::cout << "Finished loop " << ++counter << "\n"; + } + + // finalize eCAL API + eCAL::Finalize(); + + return(0); +} \ No newline at end of file diff --git a/ecal/tests/CMakeLists.txt b/ecal/tests/CMakeLists.txt index 1fd288da16..5e2fc66b9f 100644 --- a/ecal/tests/CMakeLists.txt +++ b/ecal/tests/CMakeLists.txt @@ -30,6 +30,8 @@ add_subdirectory(cpp/core_test) add_subdirectory(cpp/descgate_test) +add_subdirectory(cpp/config_test) + if(ECAL_CORE_REGISTRATION) add_subdirectory(cpp/util_test) endif() diff --git a/ecal/tests/cpp/config_test/CMakeLists.txt b/ecal/tests/cpp/config_test/CMakeLists.txt new file mode 100644 index 0000000000..70947dab68 --- /dev/null +++ b/ecal/tests/cpp/config_test/CMakeLists.txt @@ -0,0 +1,62 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2024 Continental 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. +# +# ========================= eCAL LICENSE ================================= + +project(test_config) + +find_package(Threads REQUIRED) +find_package(GTest REQUIRED) +find_package(tclap REQUIRED) + +set(cmd_parser_src + ${CMAKE_SOURCE_DIR}/ecal/core/src/config/ecal_cmd_parser.cpp + ${CMAKE_SOURCE_DIR}/lib/ecal_utils/src/filesystem.cpp + ${CMAKE_SOURCE_DIR}/lib/ecal_utils/src/str_convert.cpp +) + +set(config_test_src + src/config_test.cpp + ${cmd_parser_src} +) + +ecal_add_gtest(${PROJECT_NAME} ${config_test_src}) + +target_include_directories(${PROJECT_NAME} PRIVATE + $ + ${CMAKE_CURRENT_LIST_DIR}/src + ${CMAKE_SOURCE_DIR}/ecal/core/src/config +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + eCAL::core + Threads::Threads + tclap::tclap + CustomTclap +) + +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) + +target_compile_definitions(${PROJECT_NAME} PRIVATE ECAL_CORE_COMMAND_LINE) + +ecal_install_gtest(${PROJECT_NAME}) + +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER tests/cpp/config) + +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES + ${${PROJECT_NAME}_src} +) diff --git a/ecal/tests/cpp/config_test/src/config_test.cpp b/ecal/tests/cpp/config_test/src/config_test.cpp new file mode 100644 index 0000000000..89d861dfda --- /dev/null +++ b/ecal/tests/cpp/config_test/src/config_test.cpp @@ -0,0 +1,299 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental 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. + * + * ========================= eCAL LICENSE ================================= +*/ + +#include +#include +#include "ini_file.h" + +#include + +#include +#include +#include +#include + +#include "ecal_cmd_parser.h" + +template +void SetValue(MEMBER& member, VALUE value) +{ + member = value; +} + +TEST(core_cpp_config, user_config_passing) +{ + eCAL::Configuration custom_config(0, nullptr); + + // Test value assignments from each category + // How the user would utilize it + + // Transport layer options + const bool network_enabled = true; + std::string ip_address = "238.200.100.2"; + const int upd_snd_buff = (5242880 + 1024); + + // Monitoring options + const unsigned int mon_timeout = 6000U; + const std::string mon_filter_excl = "_A.*"; + const eCAL_Logging_Filter mon_log_filter_con = log_level_warning; + const eCAL::Monitoring::Types::Mode monitoring_mode = eCAL::Monitoring::Types::Mode::udp_monitoring; + + // Publisher options + const bool pub_use_shm = true; + + // Registration options + const unsigned int registration_timeout = 80000U; + const unsigned int registration_refresh = 2000U; + const eCAL::Registration::Configuration registration = eCAL::Registration::Configuration(registration_timeout, registration_refresh); + + try{ + custom_config.transport_layer.network_enabled = network_enabled; + custom_config.transport_layer.mc_options.group = ip_address; + custom_config.transport_layer.mc_options.sndbuf = upd_snd_buff; + + custom_config.monitoring.monitoring_timeout = mon_timeout; + custom_config.monitoring.filter_excl = mon_filter_excl; + custom_config.monitoring.monitoring_mode = monitoring_mode; + custom_config.logging.filter_log_con = mon_log_filter_con; + + custom_config.publisher.shm.enable = pub_use_shm; + + custom_config.registration = registration; + } + catch (std::invalid_argument& e) + { + throw std::runtime_error("Error while configuring Configuration: " + std::string(e.what())); + } + + // Initialize ecal api with custom config + EXPECT_EQ(0, eCAL::Initialize(custom_config, "User Config Passing Test", eCAL::Init::Default)); + + // Test boolean assignment, default is false + EXPECT_EQ(network_enabled, eCAL::GetConfiguration().transport_layer.network_enabled); + + // Test IP address assignment, default is 239.0.0.1 + EXPECT_EQ(ip_address, static_cast(eCAL::GetConfiguration().transport_layer.mc_options.group)); + + // Test UDP send buffer assignment, default is 5242880 + EXPECT_EQ(upd_snd_buff, static_cast(eCAL::GetConfiguration().transport_layer.mc_options.sndbuf)); + + // Test monitoring timeout assignment, default is 5000U + EXPECT_EQ(mon_timeout, eCAL::GetConfiguration().monitoring.monitoring_timeout); + + // Test monitoring filter exclude assignment, default is "_.*" + EXPECT_EQ(mon_filter_excl, eCAL::GetConfiguration().monitoring.filter_excl); + + // Test monitoring console log assignment, default is (log_level_info | log_level_warning | log_level_error | log_level_fatal) + EXPECT_EQ(mon_log_filter_con, eCAL::GetConfiguration().logging.filter_log_con); + + // Test monitoring mode assignment, default is eCAL::Types::MonitoringMode::none + EXPECT_EQ(monitoring_mode, eCAL::GetConfiguration().monitoring.monitoring_mode); + + // Test publisher sendmode assignment, default is eCAL::TLayer::eSendMode::smode_auto + EXPECT_EQ(pub_use_shm, eCAL::GetConfiguration().publisher.shm.enable); + + // Test registration option assignment, default timeout is 60000U and default refresh is 1000U + EXPECT_EQ(registration_timeout, eCAL::GetConfiguration().registration.getTimeoutMS()); + EXPECT_EQ(registration_refresh, eCAL::GetConfiguration().registration.getRefreshMS()); + + // Finalize eCAL API + EXPECT_EQ(0, eCAL::Finalize()); +} + +TEST(ConfigDeathTest, user_config_death_test) +{ + eCAL::Configuration custom_config(0, nullptr); + + // Test the IpAddressV4 class with wrong values + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("42")), + std::invalid_argument); + + // Test the IpAddressV4 class with invalid addresses + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("256.0.0.0")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("127.0.0.1")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("255.255.255.255")), + std::invalid_argument); + + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("FFF.FF.FF.FF")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("FF.FF.FF.FF")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("Ff.fF.ff.Ff")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("7f.0.0.1")), + std::invalid_argument); + + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("0.0.0.0")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("00.00.00.00")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("000.000.000.000")), + std::invalid_argument); + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.group, std::string("0.00.000.0")), + std::invalid_argument); + + // Test the ConstrainedInteger class with wrong values. Default are MIN = 5242880, STEP = 1024 + // Value below MIN + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.sndbuf, 42), + std::invalid_argument); + + // Wrong step. Default STEP = 1024 + ASSERT_THROW( + SetValue(custom_config.transport_layer.mc_options.sndbuf, (5242880 + 512)), + std::invalid_argument); + + // Value exceeds MAX. Default MAX = 100 + ASSERT_THROW( + SetValue(custom_config.transport_layer.shm_options.memfile_reserve, 150), + std::invalid_argument); + + // Test the registration option limits + // Refresh timeout > registration timeout + ASSERT_THROW( + eCAL::Registration::Configuration(2000U, 3000U), std::invalid_argument); + + // Refresh timeout = registration timeout + ASSERT_THROW( + eCAL::Registration::Configuration(2000U, 2000U), std::invalid_argument); +} + +TEST(core_cpp_config, config_custom_datatypes_tests) +{ + // test custom datatype assignment operators + eCAL::Types::IpAddressV4 ip1; + eCAL::Types::IpAddressV4 ip2; + EXPECT_EQ(static_cast(ip1), static_cast(ip2)); + + ip1 = "192.168.0.2"; + ip2 = ip1; + EXPECT_EQ(static_cast(ip1), static_cast(ip2)); + + eCAL::Types::ConstrainedInteger<0,1,10> s1; + eCAL::Types::ConstrainedInteger<0,1,10> s2; + EXPECT_EQ(static_cast(s1), static_cast(s2)); + + s1 = 5; + s2 = s1; + EXPECT_EQ(static_cast(s1), static_cast(s2)); + + // test copy method for config structure + eCAL::Configuration config1(0, nullptr); + eCAL::Configuration config2(0, nullptr); + std::string testValue = std::string("234.0.3.2"); + config2.transport_layer.mc_options.group = testValue; + auto& config2ref = config2; + config1 = config2ref; + + EXPECT_EQ(static_cast(config1.transport_layer.mc_options.group), testValue); +} + +TEST(core_cpp_config, config_cmd_parser) +{ + // create a custom ini file + std::string ini_file_name = "customIni.ini"; + std::ofstream custom_ini_file(ini_file_name); + + if (custom_ini_file.is_open()) + { + custom_ini_file << ini_file_as_string; + custom_ini_file.close(); + } + else + { + std::cerr << "Error opening file for ini writing" << "\n"; + return; + } + + eCAL::Config::CmdParser parser; + + std::vector arguments; + + const std::string set_config_key = "--ecal-set-config-key "; + const std::string sep_slash = "/"; + const std::string sep_col = ":"; + + const std::string network = "network"; + const std::string host_group_name = "host_group_name"; + const std::string config_test_machine = "ConfigTestMachine"; + const std::string network_enabled = "network_enabled"; + const std::string is_network_enabled = "true"; + + const std::string common = "common"; + const std::string registration_timeout = "registration_timeout"; + const std::string registration_refresh = "registration_refresh"; + const std::string reg_to_value = "6000"; + const std::string reg_rf_value = "1000"; + + arguments.push_back("test_config_cmd_parser"); + arguments.push_back("--ecal-ini-file customIni.ini"); + arguments.push_back(set_config_key + network + sep_slash + host_group_name + sep_col + config_test_machine); + arguments.push_back(set_config_key + network + sep_slash + network_enabled + sep_col + is_network_enabled); + arguments.push_back(set_config_key + common + sep_slash + registration_timeout + sep_col + reg_to_value); + arguments.push_back(set_config_key + common + sep_slash + registration_refresh + sep_col + reg_rf_value); + + try + { + parser.parseArguments(arguments); + } + catch(const std::runtime_error& e) + { + std::cerr << e.what() << '\n'; + } + + // Expect a valid ini file + EXPECT_NE(parser.getUserIni(), std::string("")); + + // Expect a proper key-value map in the config key map + EXPECT_EQ(parser.getConfigKeysMap()[network][host_group_name], config_test_machine); + EXPECT_EQ(parser.getConfigKeysMap()[network][network_enabled], is_network_enabled); + EXPECT_EQ(parser.getConfigKeysMap()[common][registration_timeout], reg_to_value); + EXPECT_EQ(parser.getConfigKeysMap()[common][registration_refresh], reg_rf_value); + + remove(ini_file_name.data()); +} + +TEST(CmdParserDeathTest, config_cmd_parser_death_test) +{ + eCAL::Config::CmdParser parser; + + std::vector arguments; + + arguments.push_back("test_config_cmd_parser_death_test"); + arguments.push_back("--ecal-ini-file someNotValidFileName.ini"); + + ASSERT_THROW( + parser.parseArguments(arguments), + std::runtime_error + ); +} \ No newline at end of file diff --git a/ecal/tests/cpp/config_test/src/ini_file.h b/ecal/tests/cpp/config_test/src/ini_file.h new file mode 100644 index 0000000000..fafd498d88 --- /dev/null +++ b/ecal/tests/cpp/config_test/src/ini_file.h @@ -0,0 +1,194 @@ +#include + +static const std::string ini_file_as_string = +"; --------------------------------------------------\n" +"; NETWORK SETTINGS\n" +"; --------------------------------------------------\n" +"; network_enabled = true / false true = all eCAL components communicate over network boundaries\n" +"; false = local host only communication\n" +";\n" +"; multicast_config_version = v1 / v2 UDP configuration version (Since eCAL 5.12.)\n" +"; v1: default behavior\n" +"; v2: new behavior, comes with a bit more intuitive handling regarding masking of the groups\n" +"; multicast_group = 239.0.0.1 UDP multicast group base\n" +"; All registration and logging is sent on this address\n" +"; multicast_mask = 0.0.0.1-0.0.0.255 v1: Mask maximum number of dynamic multicast group\n" +"; 255.0.0.0-255.255.255.255 v2: masks are now considered like routes masking\n" +";\n" +"; multicast_port = 14000 + x UDP multicast port number (eCAL will use at least the 2 following port\n" +"; numbers too, so please modify in steps of 10 (e.g. 1010, 1020 ...)\n" +";\n" +"; multicast_ttl = 0 + x UDP ttl value, also known as hop limit, is used in determining \n" +"; the intermediate routers being traversed towards the destination\n" +";\n" +"; multicast_sndbuf = 1024 * x UDP send buffer in bytes\n" +"; \n" +"; multicast_rcvbuf = 1024 * x UDP receive buffer in bytes\n" +";\n" +"; multicast_join_all_if = false Linux specific setting to enable joining multicast groups on all network interfacs\n" +"; independent of their link state. Enabling this makes sure that eCAL processes\n" +"; receive data if they are started before network devices are up and running.\n" +"; \n" +"; shm_rec_enabled = true Enable to receive on eCAL shared memory layer\n" +"; tcp_rec_enabled = true Enable to receive on eCAL tcp layer\n" +"; udp_mc_rec_enabled = true Enable to receive on eCAL udp multicast layer\n" +";\n" +"; npcap_enabled = false Enable to receive UDP traffic with the Npcap based receiver\n" +";\n" +"; tcp_pubsub_num_executor_reader = 4 Tcp_pubsub reader amount of threads that shall execute workload\n" +"; tcp_pubsub_num_executor_writer = 4 Tcp_pubsub writer amount of threads that shall execute workload\n" +"; tcp_pubsub_max_reconnections = 5 Tcp_pubsub reconnection attemps the session will try to reconnect in \n" +"; case of an issue (a negative value means infinite reconnection attemps)\n" +";\n" +"; host_group_name = Common host group name that enables interprocess mechanisms across \n" +"; (virtual) host borders (e.g, Docker); by default equivalent to local host name\n" +"; --------------------------------------------------\n" +"\n" +"[network]\n" +"network_enabled = false\n" +"multicast_config_version = v1\n" +"multicast_group = 239.0.0.1\n" +"multicast_mask = 0.0.0.15\n" +"multicast_port = 14000\n" +"multicast_ttl = 2\n" +"multicast_sndbuf = 5242880\n" +"multicast_rcvbuf = 5242880\n" +"\n" +"multicast_join_all_if = false\n" +"\n" +"shm_rec_enabled = true\n" +"tcp_rec_enabled = true\n" +"udp_mc_rec_enabled = true\n" +"\n" +"npcap_enabled = false\n" +"\n" +"tcp_pubsub_num_executor_reader = 4\n" +"tcp_pubsub_num_executor_writer = 4\n" +"tcp_pubsub_max_reconnections = 5\n" +"\n" +"host_group_name =\n" +"\n" +"; --------------------------------------------------\n" +"; COMMON SETTINGS\n" +"; --------------------------------------------------\n" +"; registration_timeout = 60000 Timeout for topic registration in ms (internal)\n" +"; registration_refresh = 1000 Topic registration refresh cylce (has to be smaller then registration timeout !)\n" +"\n" +"; --------------------------------------------------\n" +"[common]\n" +"registration_timeout = 60000\n" +"registration_refresh = 1000\n" +"\n" +"; --------------------------------------------------\n" +"; TIME SETTINGS\n" +"; --------------------------------------------------\n" +"; timesync_module_rt = ecaltime-localtime Time synchronisation interface name (dynamic library)\n" +"; The name will be extended with platform suffix (32|64), debug suffix (d) and platform extension (.dll|.so)\n" +";\n" +"; Available modules are:\n" +"; - ecaltime-localtime local system time without synchronization \n" +"; - ecaltime-linuxptp For PTP / gPTP synchronization over ethernet on Linux\n" +"; (device configuration in ecaltime.ini)\n" +"; --------------------------------------------------\n" +"[time]\n" +"timesync_module_rt = ecaltime-localtime\n" +"\n" +"; ---------------------------------------------\n" +"; PROCESS SETTINGS\n" +"; ---------------------------------------------\n" +";\n" +"; terminal_emulator = /usr/bin/x-terminal-emulator -e command for starting applications with an external terminal emulator. If empty, the command will be ignored. Ignored on Windows.\n" +"; e.g. /usr/bin/x-terminal-emulator -e\n" +"; /usr/bin/gnome-terminal -x\n" +"; /usr/bin/xterm -e\n" +";\n" +"; ---------------------------------------------\n" +"[process]\n" +"terminal_emulator = \n" +"\n" +"; --------------------------------------------------\n" +"; PUBLISHER SETTINGS\n" +"; --------------------------------------------------\n" +"; use_shm = 0, 1, 2 Use shared memory transport layer (0 = off, 1 = on, 2 = auto, default = 2)\n" +"; use_tcp = 0, 1, 2 Use tcp transport layer (0 = off, 1 = on, 2 = auto, default = 0)\n" +"; use_udp_mc = 0, 1, 2 Use udp multicast transport layer (0 = off, 1 = on, 2 = auto, default = 2)\n" +";\n" +"; memfile_minsize = x * 4096 kB Default memory file size for new publisher\n" +";\n" +"; memfile_reserve = 50 .. x % Dynamic file size reserve before recreating memory file if topic size changes\n" +";\n" +"; memfile_ack_timeout = 0 .. x ms Publisher timeout for ack event from subscriber that memory file content is processed\n" +";\n" +"; memfile_buffer_count = 1 .. x Number of parallel used memory file buffers for 1:n publish/subscribe ipc connections (default = 1)\n" +"; memfile_zero_copy = 0, 1 Allow matching subscriber to access memory file without copying its content in advance (blocking mode)\n" +";\n" +"; share_ttype = 0, 1 Share topic type via registration layer\n" +"; share_tdesc = 0, 1 Share topic description via registration layer (switch off to disable reflection)\n" +"; --------------------------------------------------\n" +"[publisher]\n" +"use_shm = 2\n" +"use_tcp = 0\n" +"use_udp_mc = 2\n" +"\n" +"memfile_minsize = 4096\n" +"memfile_reserve = 50\n" +"memfile_ack_timeout = 0\n" +"memfile_buffer_count = 1\n" +"memfile_zero_copy = 0\n" +"\n" +"share_ttype = 1\n" +"share_tdesc = 1\n" +"\n" +"; --------------------------------------------------\n" +"; SERVICE SETTINGS\n" +"; --------------------------------------------------\n" +"; protocol_v0 = 0, 1 Support service protocol v0, eCAL 5.11 and older (0 = off, 1 = on)\n" +"; protocol_v1 = 0, 1 Support service protocol v1, eCAL 5.12 and newer (0 = off, 1 = on)\n" +"; --------------------------------------------------\n" +"[service]\n" +"protocol_v0 = 1\n" +"protocol_v1 = 1\n" +"\n" +"; --------------------------------------------------\n" +"; MONITORING SETTINGS\n" +"; --------------------------------------------------\n" +"; timeout = 1000 + (x * 1000) Timeout for topic monitoring in ms\n" +"; filter_excl = __.* Topics blacklist as regular expression (will not be monitored)\n" +"; filter_incl = Topics whitelist as regular expression (will be monitored only)\n" +"; filter_log_con = info, warning, error, fatal Log messages logged to console (all, info, warning, error, fatal, debug1, debug2, debug3, debug4)\n" +"; filter_log_file = Log messages to logged into file system\n" +"; filter_log_udp = info, warning, error, fatal Log messages logged via udp network\n" +"; --------------------------------------------------\n" +"[monitoring]\n" +"timeout = 5000\n" +"filter_excl = __.*\n" +"filter_incl =\n" +"filter_log_con = info, warning, error, fatal\n" +"filter_log_file =\n" +"filter_log_udp = info, warning, error, fatal\n" +"\n" +"; --------------------------------------------------\n" +"; SYS SETTINGS\n" +"; --------------------------------------------------\n" +"; filter_excl = App1,App2 Apps blacklist to be excluded when importing tasks from cloud\n" +"; --------------------------------------------------\n" +"[sys]\n" +"filter_excl = ^eCALSysClient$|^eCALSysGUI$|^eCALSys$\n" +"\n" +"; --------------------------------------------------\n" +"; EXPERIMENTAL SETTINGS\n" +"; --------------------------------------------------\n" +"; shm_monitoring_enabled = false Enable distribution of monitoring/registration information via shared memory\n" +"; shm_monitoring_domain = ecal_monitoring Domain name for shared memory based monitoring/registration\n" +"; shm_monitoring_queue_size = 1024 Queue size of monitoring/registration events\n" +"; network_monitoring_enabled = true Enable distribution of monitoring/registration information via network\n" +";\n" +"; drop_out_of_order_messages = false Enable dropping of payload messages that arrive out of order\n" +"; --------------------------------------------------\n" +"[experimental]\n" +"shm_monitoring_enabled = false\n" +"shm_monitoring_domain = ecal_mon\n" +"shm_monitoring_queue_size = 1024\n" +"network_monitoring_enabled = true\n" +"drop_out_of_order_messages = false\n" +; \ No newline at end of file diff --git a/ecal/tests/cpp/pubsub_test/src/pubsub_acknowledge.cpp b/ecal/tests/cpp/pubsub_test/src/pubsub_acknowledge.cpp index 903854a18c..1530f66e6d 100644 --- a/ecal/tests/cpp/pubsub_test/src/pubsub_acknowledge.cpp +++ b/ecal/tests/cpp/pubsub_test/src/pubsub_acknowledge.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.