diff --git a/app/rec/rec_server_core/src/rec_server_impl.cpp b/app/rec/rec_server_core/src/rec_server_impl.cpp index 90824dd5af..bf9cf2e596 100644 --- a/app/rec/rec_server_core/src/rec_server_impl.cpp +++ b/app/rec/rec_server_core/src/rec_server_impl.cpp @@ -60,7 +60,7 @@ namespace eCAL settings_.ClearHostFilter(); // There is no global host filter // Initialize eCAL - eCAL::Initialize("", eCAL::Init::Default | eCAL::Init::Monitoring); + eCAL::Initialize("eCALRec-Server", eCAL::Init::Default | eCAL::Init::Monitoring); // Start FTP Server ftp_server_->start(5); diff --git a/ecal/core/CMakeLists.txt b/ecal/core/CMakeLists.txt index 9fc282564b..d16a316b7e 100644 --- a/ecal/core/CMakeLists.txt +++ b/ecal/core/CMakeLists.txt @@ -181,8 +181,8 @@ endif() ###################################### set(ecal_logging_src src/logging/ecal_log.cpp - src/logging/ecal_log_impl.cpp - src/logging/ecal_log_impl.h + src/logging/ecal_log_provider.cpp + src/logging/ecal_log_receiver.cpp ) ###################################### @@ -335,6 +335,8 @@ set(ecal_serialization_src src/serialization/nanopb/pb_decode.h src/serialization/nanopb/pb_encode.c src/serialization/nanopb/pb_encode.h + src/serialization/nanopb/ecal/core/pb/datatype.npb.c + src/serialization/nanopb/ecal/core/pb/datatype.npb.h src/serialization/nanopb/ecal/core/pb/ecal.npb.c src/serialization/nanopb/ecal/core/pb/ecal.npb.h src/serialization/nanopb/ecal/core/pb/host.npb.c diff --git a/ecal/core/include/ecal/config/logging.h b/ecal/core/include/ecal/config/logging.h index 0ade27b36a..e50ddb95fd 100644 --- a/ecal/core/include/ecal/config/logging.h +++ b/ecal/core/include/ecal/config/logging.h @@ -39,50 +39,63 @@ namespace eCAL { namespace Logging { - namespace Sinks + namespace Provider { - namespace Console + struct Sink + { + bool enable; //!< Enable sink + eCAL_Logging_Filter filter_log; //!< Log messages logged (all, info, warning, error, fatal, debug1, debug2, debug3, debug4) + }; + + namespace File { struct Configuration { - bool enable { true }; //!< Enable console logging (Default: true) - eCAL_Logging_Filter filter_log_con { log_level_error | log_level_fatal }; /*!< Log messages logged to console (all, info, warning, error, fatal, debug1, debug2, debug3, debug4) - (Default: info, warning, error, fatal)*/ + std::string path { "" }; //!< Path to log file (Default: "") }; } - namespace File + namespace UDP { struct Configuration { - bool enable { false }; //!< Enable file logging (Default: false) - std::string path { "" }; //!< Path to log file (Default: "") - eCAL_Logging_Filter filter_log_file { log_level_none }; /*!< Log messages logged into file system (all, info, warning, error, fatal, debug1, debug2, debug3, debug4) - (Default: info, warning, error, fatal)*/ + unsigned int port { 14001 }; //!< UDP port number (Default: 14001) }; } + struct Configuration + { + Sink console { true, log_level_error | log_level_fatal}; //!< default: true, log_level_error + Sink file { false, log_level_none }; //!< default: false, log_level_none + Sink udp { true, log_filter_default }; //!< default: true, log_filter_default + + File::Configuration file_config; + UDP::Configuration udp_config; + + }; + } + + namespace Receiver + { namespace UDP { struct Configuration { - bool enable { true }; //!< Enable UDP logging (Default: false) - unsigned int port { 14001 }; //!< UDP port number (Default: 14001) - eCAL_Logging_Filter filter_log_udp { log_filter_default }; //!< Log messages logged via udp network (Default: info, warning, error, fatal) + unsigned int port { 14001 }; //!< UDP port number (Default: 14001) }; } struct Configuration { - Console::Configuration console; - File::Configuration file; - UDP::Configuration udp; + bool enable { false }; //!< Enable UDP receiver (Default: false) + UDP::Configuration udp_config; }; } struct Configuration { - Sinks::Configuration sinks; + Provider::Configuration provider; + Receiver::Configuration receiver; }; } } \ No newline at end of file diff --git a/ecal/core/include/ecal/types/ecal_custom_data_types.h b/ecal/core/include/ecal/types/ecal_custom_data_types.h index 6907519f1f..096c15e7ea 100644 --- a/ecal/core/include/ecal/types/ecal_custom_data_types.h +++ b/ecal/core/include/ecal/types/ecal_custom_data_types.h @@ -47,6 +47,7 @@ namespace eCAL { public: ECAL_API IpAddressV4(const std::string& ip_address_); + ECAL_API IpAddressV4(const char* ip_address_); ECAL_API std::string Get() const; @@ -61,7 +62,6 @@ namespace eCAL 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{}; }; diff --git a/ecal/core/include/ecal/types/monitoring.h b/ecal/core/include/ecal/types/monitoring.h index aff7793d15..ba7051c8a5 100644 --- a/ecal/core/include/ecal/types/monitoring.h +++ b/ecal/core/include/ecal/types/monitoring.h @@ -133,12 +133,17 @@ namespace eCAL struct SMethodMon //::encode(const eCAL::Logging::Sinks::UDP::Configuration& config_) + + Node convert::encode(const eCAL::Logging::Receiver::UDP::Configuration& config_) { Node node; - node["enable"] = config_.enable; node["port"] = config_.port; - node["level"] = LogLevelToVector(config_.filter_log_udp); return node; } - bool convert::decode(const Node& node_, eCAL::Logging::Sinks::UDP::Configuration& config_) + bool convert::decode(const Node& node_, eCAL::Logging::Receiver::UDP::Configuration& config_) { - AssignValue(config_.enable, node_, "enable"); AssignValue(config_.port, node_, "port"); + return true; + } - std::vector tmp; - AssignValue>(tmp, node_, "level"); - config_.filter_log_udp = ParseLogLevel(tmp); + Node convert::encode(const eCAL::Logging::Receiver::Configuration& config_) + { + Node node; + node["enable"] = config_.enable; + node["udp_config"] = config_.udp_config; + return node; + } + + bool convert::decode(const Node& node_, eCAL::Logging::Receiver::Configuration& config_) + { + AssignValue(config_.enable, node_, "enable"); + AssignValue(config_.udp_config, node_, "udp_config"); return true; } - Node convert::encode(const eCAL::Logging::Sinks::Console::Configuration& config_) + Node convert::encode(const eCAL::Logging::Provider::UDP::Configuration& config_) + { + Node node; + node["port"] = config_.port; + return node; + } + + bool convert::decode(const Node& node_, eCAL::Logging::Provider::UDP::Configuration& config_) + { + AssignValue(config_.port, node_, "port"); + return true; + } + + Node convert::encode(const eCAL::Logging::Provider::Sink& config_) { Node node; node["enable"] = config_.enable; - node["level"] = LogLevelToVector(config_.filter_log_con); + node["level"] = LogLevelToVector(config_.filter_log); return node; } - bool convert::decode(const Node& node_, eCAL::Logging::Sinks::Console::Configuration& config_) + bool convert::decode(const Node& node_, eCAL::Logging::Provider::Sink& config_) { AssignValue(config_.enable, node_, "enable"); std::vector tmp; AssignValue>(tmp, node_, "level"); - config_.filter_log_con = ParseLogLevel(tmp); + config_.filter_log = ParseLogLevel(tmp); return true; } - Node convert::encode(const eCAL::Logging::Sinks::File::Configuration& config_) + Node convert::encode(const eCAL::Logging::Provider::File::Configuration& config_) { Node node; - node["enable"] = config_.enable; node["path"] = config_.path; - node["level"] = LogLevelToVector(config_.filter_log_file); return node; } - bool convert::decode(const Node& node_, eCAL::Logging::Sinks::File::Configuration& config_) + bool convert::decode(const Node& node_, eCAL::Logging::Provider::File::Configuration& config_) { - AssignValue(config_.enable, node_, "enable"); AssignValue(config_.path, node_, "path"); - - std::vector tmp; - AssignValue>(tmp, node_, "level"); - config_.filter_log_file = ParseLogLevel(tmp); return true; } - Node convert::encode(const eCAL::Logging::Sinks::Configuration& config_) + Node convert::encode(const eCAL::Logging::Provider::Configuration& config_) { Node node; - node["console"] = config_.console; - node["file"] = config_.file; - node["udp"] = config_.udp; + node["console"] = config_.console; + node["file"] = config_.file; + node["udp"] = config_.udp; + node["file_config"] = config_.file_config; + node["udp_config"] = config_.udp_config; return node; } - bool convert::decode(const Node& node_, eCAL::Logging::Sinks::Configuration& config_) + bool convert::decode(const Node& node_, eCAL::Logging::Provider::Configuration& config_) { - AssignValue(config_.console, node_, "console"); - AssignValue(config_.file, node_, "file"); - AssignValue(config_.udp, node_, "udp"); + AssignValue(config_.console, node_, "console"); + AssignValue(config_.file, node_, "file"); + AssignValue(config_.udp, node_, "udp"); + AssignValue(config_.udp_config, node_, "udp_config"); + AssignValue(config_.file_config, node_, "file_config"); return true; } Node convert::encode(const eCAL::Logging::Configuration& config_) { Node node; - node["sinks"] = config_.sinks; + node["provider"] = config_.provider; + node["receiver"] = config_.receiver; return node; } bool convert::decode(const Node& node_, eCAL::Logging::Configuration& config_) { - AssignValue(config_.sinks, node_, "sinks"); + AssignValue(config_.provider, node_, "provider"); + AssignValue(config_.receiver, node_, "receiver"); return true; } diff --git a/ecal/core/src/config/configuration_to_yaml.h b/ecal/core/src/config/configuration_to_yaml.h index 16ae6eaf45..2772230778 100644 --- a/ecal/core/src/config/configuration_to_yaml.h +++ b/ecal/core/src/config/configuration_to_yaml.h @@ -283,35 +283,51 @@ namespace YAML /___//___/ /___/ */ template<> - struct convert + struct convert { - static Node encode(const eCAL::Logging::Sinks::UDP::Configuration& config_); + static Node encode(const eCAL::Logging::Receiver::UDP::Configuration& config_); - static bool decode(const Node& node_, eCAL::Logging::Sinks::UDP::Configuration& config_); + static bool decode(const Node& node_, eCAL::Logging::Receiver::UDP::Configuration& config_); }; template<> - struct convert + struct convert { - static Node encode(const eCAL::Logging::Sinks::Console::Configuration& config_); + static Node encode(const eCAL::Logging::Receiver::Configuration& config_); - static bool decode(const Node& node_, eCAL::Logging::Sinks::Console::Configuration& config_); + static bool decode(const Node& node_, eCAL::Logging::Receiver::Configuration& config_); }; template<> - struct convert + struct convert { - static Node encode(const eCAL::Logging::Sinks::File::Configuration& config_); + static Node encode(const eCAL::Logging::Provider::File::Configuration& config_); - static bool decode(const Node& node_, eCAL::Logging::Sinks::File::Configuration& config_); + static bool decode(const Node& node_, eCAL::Logging::Provider::File::Configuration& config_); }; template<> - struct convert + struct convert { - static Node encode(const eCAL::Logging::Sinks::Configuration& config_); + static Node encode(const eCAL::Logging::Provider::UDP::Configuration& config_); - static bool decode(const Node& node_, eCAL::Logging::Sinks::Configuration& config_); + static bool decode(const Node& node_, eCAL::Logging::Provider::UDP::Configuration& config_); + }; + + template<> + struct convert + { + static Node encode(const eCAL::Logging::Provider::Sink& config_); + + static bool decode(const Node& node_, eCAL::Logging::Provider::Sink& config_); + }; + + template<> + struct convert + { + static Node encode(const eCAL::Logging::Provider::Configuration& config_); + + static bool decode(const Node& node_, eCAL::Logging::Provider::Configuration& config_); }; template<> diff --git a/ecal/core/src/config/default_configuration.cpp b/ecal/core/src/config/default_configuration.cpp index 0f3f617694..cecd68a747 100644 --- a/ecal/core/src/config/default_configuration.cpp +++ b/ecal/core/src/config/default_configuration.cpp @@ -307,29 +307,42 @@ namespace eCAL ss << R"()" << "\n"; ss << R"(# Logging configuration)" << "\n"; ss << R"(logging:)" << "\n"; - ss << R"( sinks:)" << "\n"; - ss << R"( # Console logging configuration)" << "\n"; + ss << R"( # Configuration for file, udp and console log provider)" << "\n"; + ss << R"( provider:)" << "\n"; + ss << R"( # Console logging configuration)" << "\n"; ss << R"( console:)" << "\n"; ss << R"( # Enable console logging)" << "\n"; - ss << R"( enable: )" << config_.logging.sinks.console.enable << "\n"; + ss << R"( enable: )" << config_.logging.provider.console.enable << "\n"; ss << R"( # Log level for console output)" << "\n"; - ss << R"( level: )" << logToArray(config_.logging.sinks.console.filter_log_con) << "\n"; + ss << R"( level: )" << logToArray(config_.logging.provider.console.filter_log) << "\n"; ss << R"( # File logging configuration)" << "\n"; ss << R"( file:)" << "\n"; ss << R"( # Enable file logging)" << "\n"; - ss << R"( enable: )" << config_.logging.sinks.file.enable << "\n"; + ss << R"( enable: )" << config_.logging.provider.file.enable << "\n"; ss << R"( # Log level for file output)" << "\n"; - ss << R"( level: )" << logToArray(config_.logging.sinks.file.filter_log_file) << "\n"; - ss << R"( # Log file path)" << "\n"; - ss << R"( path: )" << quoteString(config_.logging.sinks.file.path) << "\n"; + ss << R"( level: )" << logToArray(config_.logging.provider.file.filter_log) << "\n"; ss << R"( # UDP logging configuration)" << "\n"; ss << R"( udp:)" << "\n"; ss << R"( # Enable UDP logging)" << "\n"; - ss << R"( enable: )" << config_.logging.sinks.udp.enable << "\n"; + ss << R"( enable: )" << config_.logging.provider.udp.enable << "\n"; ss << R"( # Log level for UDP output)" << "\n"; - ss << R"( level: )" << logToArray(config_.logging.sinks.udp.filter_log_udp) << "\n"; - ss << R"( # UDP)" << "\n"; - ss << R"( port: )" << config_.logging.sinks.udp.port << "\n"; + ss << R"( level: )" << logToArray(config_.logging.provider.udp.filter_log) << "\n"; + ss << R"( # File specific configuration)" << "\n"; + ss << R"( file_config: )" << "\n"; + ss << R"( # Log file path)" << "\n"; + ss << R"( path: )" << quoteString(config_.logging.provider.file_config.path) << "\n"; + ss << R"( # UDP specific configuration)" << "\n"; + ss << R"( udp_config:)" << "\n"; + ss << R"( # UDP Port for sending logging data)" << "\n"; + ss << R"( port: )" << config_.logging.provider.udp_config.port << "\n"; + ss << R"( # Configuration for udp log receiver)" << "\n"; + ss << R"( receiver:)" << "\n"; + ss << R"( # Enable log receiving (UDP only))" << "\n"; + ss << R"( enable: )" << config_.logging.receiver.enable << "\n"; + ss << R"( # UDP specific configuration)" << "\n"; + ss << R"( udp_config:)" << "\n"; + ss << R"( # UDP Port for sending logging data)" << "\n"; + ss << R"( port: )" << config_.logging.receiver.udp_config.port << "\n"; ss << R"()" << "\n"; return ss; diff --git a/ecal/core/src/config/ecal_config.cpp b/ecal/core/src/config/ecal_config.cpp index f74930c9ad..1617197ed7 100644 --- a/ecal/core/src/config/ecal_config.cpp +++ b/ecal/core/src/config/ecal_config.cpp @@ -83,9 +83,9 @@ namespace eCAL std::string GetMonitoringFilterExcludeList () { return GetConfiguration().monitoring.filter_excl; } std::string GetMonitoringFilterIncludeList () { return GetConfiguration().monitoring.filter_incl; } - eCAL_Logging_Filter GetConsoleLogFilter () { return GetConfiguration().logging.sinks.console.filter_log_con; } - eCAL_Logging_Filter GetFileLogFilter () { return GetConfiguration().logging.sinks.file.filter_log_file; } - eCAL_Logging_Filter GetUdpLogFilter () { return GetConfiguration().logging.sinks.udp.filter_log_udp; } + eCAL_Logging_Filter GetConsoleLogFilter () { return GetConfiguration().logging.provider.console.filter_log; } + eCAL_Logging_Filter GetFileLogFilter () { return GetConfiguration().logging.provider.file.filter_log; } + eCAL_Logging_Filter GetUdpLogFilter () { return GetConfiguration().logging.provider.udp.filter_log; } ///////////////////////////////////// // sys diff --git a/ecal/core/src/ecal_global_accessors.cpp b/ecal/core/src/ecal_global_accessors.cpp index 85024b1eef..8f5b281d8a 100644 --- a/ecal/core/src/ecal_global_accessors.cpp +++ b/ecal/core/src/ecal_global_accessors.cpp @@ -93,10 +93,16 @@ namespace eCAL return g_globals_ctx; } - CLog* g_log() + Logging::CLogReceiver* g_log_udp_receiver() { if (g_globals() == nullptr) return(nullptr); - return(g_globals()->log().get()); + return(g_globals()->log_udp_receiver().get()); + } + + Logging::CLogProvider* g_log_provider() + { + if (g_globals() == nullptr) return(nullptr); + return(g_globals()->log_provider().get()); } Configuration& g_ecal_config() diff --git a/ecal/core/src/ecal_global_accessors.h b/ecal/core/src/ecal_global_accessors.h index a0d3516e1c..a44d88c877 100644 --- a/ecal/core/src/ecal_global_accessors.h +++ b/ecal/core/src/ecal_global_accessors.h @@ -32,9 +32,14 @@ namespace eCAL { class CGlobals; - class CLog; struct Configuration; + namespace Logging + { + class CLogProvider; + class CLogReceiver; + } + #if ECAL_CORE_MONITORING class CMonitoring; #endif @@ -66,7 +71,8 @@ namespace eCAL // Declaration of getter functions for globally accessible variable instances CGlobals* g_globals(); - CLog* g_log(); + Logging::CLogReceiver* g_log_udp_receiver(); + Logging::CLogProvider* g_log_provider(); #if ECAL_CORE_MONITORING CMonitoring* g_monitoring(); #endif diff --git a/ecal/core/src/ecal_globals.cpp b/ecal/core/src/ecal_globals.cpp index 40d7aca23a..1cb6063db5 100644 --- a/ecal/core/src/ecal_globals.cpp +++ b/ecal/core/src/ecal_globals.cpp @@ -190,9 +190,15 @@ namespace eCAL ///////////////////// if ((components_ & Init::Logging) != 0u) { - if (log_instance == nullptr) + if (log_provider_instance == nullptr) { - log_instance = std::make_unique(eCAL::Logging::BuildLoggingAttributes(GetLoggingConfiguration(), GetRegistrationConfiguration(), GetTransportLayerConfiguration())); + log_provider_instance = std::make_unique(eCAL::Logging::BuildLoggingProviderAttributes(GetLoggingConfiguration(), GetRegistrationConfiguration(), GetTransportLayerConfiguration())); + new_initialization = true; + } + + if (log_udp_receiver_instance == nullptr) + { + log_udp_receiver_instance = std::make_unique(eCAL::Logging::BuildLoggingReceiverAttributes(GetLoggingConfiguration(), GetRegistrationConfiguration(), GetTransportLayerConfiguration())); new_initialization = true; } } @@ -200,11 +206,14 @@ namespace eCAL ///////////////////// // START ALL ///////////////////// - //if (config_instance) config_instance->Create(); - if (log_instance && ((components_ & Init::Logging) != 0u)) log_instance->Start(); + if (log_provider_instance && ((components_ & Init::Logging) != 0u)) + { + log_provider_instance->Start(); + log_udp_receiver_instance->Start(); + } #if ECAL_CORE_REGISTRATION - if (registration_provider_instance) registration_provider_instance->Start(); - if (registration_receiver_instance) registration_receiver_instance->Start(); + if (registration_provider_instance) registration_provider_instance->Start(); + if (registration_receiver_instance) registration_receiver_instance->Start(); #endif if (descgate_instance) { @@ -214,23 +223,23 @@ namespace eCAL #endif } #if defined(ECAL_CORE_REGISTRATION_SHM) || defined(ECAL_CORE_TRANSPORT_SHM) - if (memfile_pool_instance) memfile_pool_instance->Start(); + if (memfile_pool_instance) memfile_pool_instance->Start(); #endif #if ECAL_CORE_SUBSCRIBER - if (subgate_instance && ((components_ & Init::Subscriber) != 0u)) subgate_instance->Start(); + if (subgate_instance && ((components_ & Init::Subscriber) != 0u)) subgate_instance->Start(); #endif #if ECAL_CORE_PUBLISHER - if (pubgate_instance && ((components_ & Init::Publisher) != 0u)) pubgate_instance->Start(); + if (pubgate_instance && ((components_ & Init::Publisher) != 0u)) pubgate_instance->Start(); #endif #if ECAL_CORE_SERVICE - if (servicegate_instance && ((components_ & Init::Service) != 0u)) servicegate_instance->Start(); - if (clientgate_instance && ((components_ & Init::Service) != 0u)) clientgate_instance->Start(); + if (servicegate_instance && ((components_ & Init::Service) != 0u)) servicegate_instance->Start(); + if (clientgate_instance && ((components_ & Init::Service) != 0u)) clientgate_instance->Start(); #endif #if ECAL_CORE_TIMEPLUGIN - if (timegate_instance && ((components_ & Init::TimeSync) != 0u)) timegate_instance->Start(CTimeGate::eTimeSyncMode::realtime); + if (timegate_instance && ((components_ & Init::TimeSync) != 0u)) timegate_instance->Start(CTimeGate::eTimeSyncMode::realtime); #endif #if ECAL_CORE_MONITORING - if (monitoring_instance && ((components_ & Init::Monitoring) != 0u)) monitoring_instance->Start(); + if (monitoring_instance && ((components_ & Init::Monitoring) != 0u)) monitoring_instance->Start(); #endif initialized = true; components |= components_; @@ -266,7 +275,7 @@ namespace eCAL return(monitoring_instance != nullptr); #endif case Init::Logging: - return(log_instance != nullptr); + return(log_provider_instance != nullptr); #if ECAL_CORE_TIMEPLUGIN case Init::TimeSync: return(timegate_instance != nullptr); @@ -318,8 +327,8 @@ namespace eCAL if (memfile_pool_instance) memfile_pool_instance->Stop(); if (memfile_map_instance) memfile_map_instance->Stop(); #endif - if (log_instance) log_instance->Stop(); - //if (config_instance) config_instance->Destroy(); + if (log_udp_receiver_instance) log_udp_receiver_instance->Stop(); + if (log_provider_instance) log_provider_instance->Stop(); #if ECAL_CORE_MONITORING monitoring_instance = nullptr; @@ -346,7 +355,9 @@ namespace eCAL memfile_pool_instance = nullptr; memfile_map_instance = nullptr; #endif - log_instance = nullptr; + log_provider_instance = nullptr; + log_udp_receiver_instance = nullptr; + initialized = false; // reset configuration to default values diff --git a/ecal/core/src/ecal_globals.h b/ecal/core/src/ecal_globals.h index 72dd12e60e..b6ba23db00 100644 --- a/ecal/core/src/ecal_globals.h +++ b/ecal/core/src/ecal_globals.h @@ -31,7 +31,8 @@ #include "registration/ecal_registration_receiver.h" #endif #include "time/ecal_timegate.h" -#include "logging/ecal_log_impl.h" +#include "logging/ecal_log_provider.h" +#include "logging/ecal_log_receiver.h" #if ECAL_CORE_MONITORING #include "monitoring/ecal_monitoring_def.h" #endif @@ -69,7 +70,8 @@ namespace eCAL int Finalize(); - const std::unique_ptr& log() { return log_instance; }; + const std::unique_ptr& log_provider() { return log_provider_instance; }; + const std::unique_ptr& log_udp_receiver() { return log_udp_receiver_instance; }; #if ECAL_CORE_MONITORING const std::unique_ptr& monitoring() { return monitoring_instance; }; @@ -101,7 +103,8 @@ namespace eCAL private: bool initialized; unsigned int components; - std::unique_ptr log_instance; + std::unique_ptr log_provider_instance; + std::unique_ptr log_udp_receiver_instance; #if ECAL_CORE_MONITORING std::unique_ptr monitoring_instance; #endif diff --git a/ecal/core/src/logging/config/attributes/logging_attributes.h b/ecal/core/src/logging/config/attributes/ecal_log_provider_attributes.h similarity index 52% rename from ecal/core/src/logging/config/attributes/logging_attributes.h rename to ecal/core/src/logging/config/attributes/ecal_log_provider_attributes.h index 9105bc77c8..18ae15651d 100644 --- a/ecal/core/src/logging/config/attributes/logging_attributes.h +++ b/ecal/core/src/logging/config/attributes/ecal_log_provider_attributes.h @@ -27,56 +27,37 @@ namespace eCAL { namespace Logging { - struct SUDP + struct SProviderAttributes { - bool enabled; - unsigned int port; - eCAL_Logging_Filter filter_log; - }; - - struct SFile - { - bool enabled; - std::string path; - eCAL_Logging_Filter filter_log; - }; - - struct SConsole - { - bool enabled; - eCAL_Logging_Filter filter_log; - }; + struct SSink + { + bool enabled; + eCAL_Logging_Filter filter_log; + }; - struct SUDPSender - { - std::string address; - int port; - int ttl; - bool broadcast; - bool loopback; - int sndbuf; - }; + struct SUDP + { + std::string address; + int port; + int ttl; + bool broadcast; + bool loopback; + int sndbuf; + }; - struct SUDPReceiver - { - std::string address; - int port; - bool broadcast; - bool loopback; - int rcvbuf; - }; + struct SFile + { + std::string path; + }; - struct SAttributes - { - SUDP udp; - SFile file; - SConsole console; + SSink udp_sink; + SSink file_sink; + SSink console_sink; - SUDPSender udp_sender; - SUDPReceiver udp_receiver; + SUDP udp_config; + SFile file_config; int process_id; - bool network_enabled; std::string host_name; std::string process_name; std::string unit_name; diff --git a/ecal/core/src/logging/config/attributes/ecal_log_receiver_attributes.h b/ecal/core/src/logging/config/attributes/ecal_log_receiver_attributes.h new file mode 100644 index 0000000000..582fedc8b1 --- /dev/null +++ b/ecal/core/src/logging/config/attributes/ecal_log_receiver_attributes.h @@ -0,0 +1,48 @@ +/* ========================= 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 ================================= +*/ + +#pragma once + +#include + +#include + +namespace eCAL +{ + namespace Logging + { + struct SReceiverAttributes + { + struct SUDPReceiver + { + std::string address; + int port; + bool broadcast; + bool loopback; + int rcvbuf; + }; + + SUDPReceiver udp_receiver; + + bool network_enabled; + bool receive_enabled; + std::string host_name; + }; + } +} \ No newline at end of file diff --git a/ecal/core/src/logging/config/builder/udp_attribute_builder.cpp b/ecal/core/src/logging/config/builder/udp_attribute_builder.cpp index ff193f8765..f4b9b9d524 100644 --- a/ecal/core/src/logging/config/builder/udp_attribute_builder.cpp +++ b/ecal/core/src/logging/config/builder/udp_attribute_builder.cpp @@ -25,7 +25,7 @@ namespace eCAL { namespace UDP { - eCAL::UDP::SSenderAttr ConvertToIOUDPSenderAttributes(const Logging::SUDPSender& sender_attr_) + eCAL::UDP::SSenderAttr ConvertToIOUDPSenderAttributes(const Logging::SProviderAttributes::SUDP& sender_attr_) { eCAL::UDP::SSenderAttr attr; attr.broadcast = sender_attr_.broadcast; @@ -37,7 +37,7 @@ namespace eCAL return attr; } - eCAL::UDP::SReceiverAttr ConvertToIOUDPReceiverAttributes(const Logging::SUDPReceiver& receiver_attr_) + eCAL::UDP::SReceiverAttr ConvertToIOUDPReceiverAttributes(const Logging::SReceiverAttributes::SUDPReceiver& receiver_attr_) { eCAL::UDP::SReceiverAttr attr; attr.broadcast = receiver_attr_.broadcast; diff --git a/ecal/core/src/logging/config/builder/udp_attribute_builder.h b/ecal/core/src/logging/config/builder/udp_attribute_builder.h index bead7d647e..8e9ce6d6fa 100644 --- a/ecal/core/src/logging/config/builder/udp_attribute_builder.h +++ b/ecal/core/src/logging/config/builder/udp_attribute_builder.h @@ -23,7 +23,8 @@ #include "io/udp/ecal_udp_receiver_attr.h" #include "io/udp/ecal_udp_sender_attr.h" -#include "logging/config/attributes/logging_attributes.h" +#include "logging/config/attributes/ecal_log_provider_attributes.h" +#include "logging/config/attributes/ecal_log_receiver_attributes.h" namespace eCAL { @@ -31,8 +32,8 @@ namespace eCAL { namespace UDP { - eCAL::UDP::SSenderAttr ConvertToIOUDPSenderAttributes (const Logging::SUDPSender& sender_attr_); - eCAL::UDP::SReceiverAttr ConvertToIOUDPReceiverAttributes (const Logging::SUDPReceiver& receiver_attr_); + eCAL::UDP::SSenderAttr ConvertToIOUDPSenderAttributes (const Logging::SProviderAttributes::SUDP& sender_attr_); + eCAL::UDP::SReceiverAttr ConvertToIOUDPReceiverAttributes (const Logging::SReceiverAttributes::SUDPReceiver& receiver_attr_); } } } \ No newline at end of file diff --git a/ecal/core/src/logging/ecal_log.cpp b/ecal/core/src/logging/ecal_log.cpp index b3e49bb44d..08bae6bc24 100644 --- a/ecal/core/src/logging/ecal_log.cpp +++ b/ecal/core/src/logging/ecal_log.cpp @@ -24,7 +24,9 @@ #include #include -#include "ecal_log_impl.h" +#include "ecal_log_provider.h" +#include "ecal_log_receiver.h" +#include "ecal_global_accessors.h" namespace eCAL { @@ -37,7 +39,7 @@ namespace eCAL **/ void SetLogLevel(const eCAL_Logging_eLogLevel level_) { - if(g_log() != nullptr) g_log()->SetLogLevel(level_); + if(g_log_provider() != nullptr) g_log_provider()->SetLogLevel(level_); } /** @@ -47,7 +49,7 @@ namespace eCAL */ void SetFileLogFilter(eCAL_Logging_Filter filter_) { - if(g_log() != nullptr) g_log()->SetFileLogFilter(filter_); + if(g_log_provider() != nullptr) g_log_provider()->SetFileLogFilter(filter_); } /** @@ -57,7 +59,7 @@ namespace eCAL */ void SetUDPLogFilter(eCAL_Logging_Filter filter_) { - if(g_log() != nullptr) g_log()->SetUDPLogFilter(filter_); + if(g_log_provider() != nullptr) g_log_provider()->SetUDPLogFilter(filter_); } /** @@ -67,7 +69,7 @@ namespace eCAL */ void SetConsoleLogFilter(eCAL_Logging_Filter filter_) { - if(g_log() != nullptr) g_log()->SetConsoleLogFilter(filter_); + if(g_log_provider() != nullptr) g_log_provider()->SetConsoleLogFilter(filter_); } /** @@ -77,7 +79,7 @@ namespace eCAL **/ eCAL_Logging_eLogLevel GetLogLevel() { - if(g_log() != nullptr) return(g_log()->GetLogLevel()); + if(g_log_provider() != nullptr) return(g_log_provider()->GetLogLevel()); else return(log_level_none); } @@ -88,7 +90,7 @@ namespace eCAL **/ void Log(const std::string& msg_) { - if(g_log() != nullptr) g_log()->Log(msg_); + if(g_log_provider() != nullptr) g_log_provider()->Log(msg_); } /** @@ -100,7 +102,7 @@ namespace eCAL **/ int GetLogging(std::string& log_) { - if (g_log() != nullptr) g_log()->GetLogging(log_); + if (g_log_udp_receiver() != nullptr) g_log_udp_receiver()->GetLogging(log_); return static_cast(log_.size()); } @@ -113,7 +115,7 @@ namespace eCAL **/ int GetLogging(Logging::SLogging& log_) { - if (g_log() != nullptr) g_log()->GetLogging(log_); + if (g_log_udp_receiver() != nullptr) g_log_udp_receiver()->GetLogging(log_); return static_cast(log_.log_messages.size()); } } diff --git a/ecal/core/src/logging/ecal_log_impl.cpp b/ecal/core/src/logging/ecal_log_impl.cpp deleted file mode 100644 index 76f1d5b1e7..0000000000 --- a/ecal/core/src/logging/ecal_log_impl.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* ========================= 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 eCAL logging class -**/ - -#include -#include -#include - -#include "ecal_log_impl.h" -#include "serialization/ecal_serialize_logging.h" -#include "config/builder/udp_attribute_builder.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ECAL_OS_WINDOWS -#include "ecal_win_main.h" -#include - -namespace -{ - bool isDirectory(const std::string& path_) - { - if (path_.empty()) return false; - - return EcalUtils::Filesystem::IsDir(path_, EcalUtils::Filesystem::Current); - } - - std::string get_time_str() - { - auto t = std::time(nullptr); - auto tm = *std::localtime(&t); - std::stringstream tstream; - tstream << std::put_time(&tm, "%Y-%m-%d-%H-%M-%S"); - return(tstream.str()); - } -} -#endif - -#ifdef ECAL_OS_LINUX -#include -#include - -static bool isDirectory(const std::string& path_) -{ - if (path_.empty()) return false; - - struct stat st; - if (stat(path_.c_str(), &st) == 0) - return S_ISDIR(st.st_mode); - - return false; -} - -static std::string get_time_str() -{ - char fmt[64]; - struct timeval tv; - struct tm *tm; - gettimeofday(&tv, NULL); - if ((tm = localtime(&tv.tv_sec)) != NULL) - { - strftime(fmt, sizeof fmt, "%Y-%m-%d-%H-%M-%S", tm); - } - return(std::string(fmt)); -} -#endif - -namespace -{ - void logWarningToConsole(const std::string& msg_) - { - std::cout << "[eCAL][Logging][Warning] " << msg_ << "\n"; - } - - void createLogHeader(std::stringstream& msg_stream, const eCAL_Logging_eLogLevel level_, const eCAL::Logging::SAttributes& attr_, const eCAL::Time::ecal_clock::time_point& log_time_) - { - msg_stream << std::chrono::duration_cast(log_time_.time_since_epoch()).count(); - msg_stream << " ms"; - msg_stream << " | "; - msg_stream << attr_.host_name; - msg_stream << " | "; - msg_stream << attr_.unit_name; - msg_stream << " | "; - msg_stream << attr_.process_id; - msg_stream << " | "; - switch(level_) - { - case log_level_none: - case log_level_all: - break; - case log_level_info: - msg_stream << "info"; - break; - case log_level_warning: - msg_stream << "warning"; - break; - case log_level_error: - msg_stream << "error"; - break; - case log_level_fatal: - msg_stream << "fatal"; - break; - case log_level_debug1: - msg_stream << "debug1"; - break; - case log_level_debug2: - msg_stream << "debug2"; - break; - case log_level_debug3: - msg_stream << "debug3"; - break; - case log_level_debug4: - msg_stream << "debug4"; - break; - } - msg_stream << " | "; - } -} - -namespace eCAL -{ - CLog::CLog(const Logging::SAttributes& attr_) : - m_created(false), - m_attributes(attr_), - m_logfile(nullptr) - { - } - - CLog::~CLog() - { - Stop(); - } - - void CLog::Start() - { - // create log file if file logging is enabled - if(m_attributes.file.enabled) - { - if (isDirectory(m_attributes.file.path)) - { - const std::string tstring = get_time_str(); - - m_logfile_name = m_attributes.file.path + tstring + "_" + m_attributes.unit_name + "_" + std::to_string(m_attributes.process_id) + ".log"; - m_logfile = fopen(m_logfile_name.c_str(), "w"); - } - else - { - logWarningToConsole("Logging for file enabled, but specified path to log is not valid: " + m_attributes.file.path); - } - - if (m_logfile == nullptr) - { - logWarningToConsole("Logging for file enabled, but file could not be created."); - } - - } - - if(m_attributes.udp.enabled) - { - // set logging send network attributes - const eCAL::UDP::SSenderAttr attr = Logging::UDP::ConvertToIOUDPSenderAttributes(m_attributes.udp_sender); - - // create udp logging sender - m_udp_logging_sender = std::make_unique(attr); - - if(m_udp_logging_sender == nullptr) - { - logWarningToConsole("Logging for UDP enabled, but sender could not be created."); - } - } - - // set logging receive network attributes - const eCAL::UDP::SReceiverAttr attr = Logging::UDP::ConvertToIOUDPReceiverAttributes(m_attributes.udp_receiver); - - // start logging receiver - m_log_receiver = std::make_shared(attr, std::bind(&CLog::HasSample, this, std::placeholders::_1), std::bind(&CLog::ApplySample, this, std::placeholders::_1, std::placeholders::_2)); - - if(m_log_receiver == nullptr) - { - logWarningToConsole("Logging receiver could not be created."); - } - - m_created = true; - } - - void CLog::Stop() - { - if(!m_created) return; - - const std::lock_guard lock(m_log_mtx); - - m_udp_logging_sender.reset(); - - if(m_logfile != nullptr) fclose(m_logfile); - m_logfile = nullptr; - - m_created = false; - } - - void CLog::SetLogLevel(const eCAL_Logging_eLogLevel level_) - { - const std::lock_guard lock(m_log_mtx); - m_attributes.level = level_; - } - - void CLog::SetFileLogFilter(eCAL_Logging_Filter filter_) - { - m_attributes.file.filter_log = filter_; - } - - void CLog::SetUDPLogFilter(eCAL_Logging_Filter filter_) - { - m_attributes.udp.filter_log = filter_; - } - - void CLog::SetConsoleLogFilter(eCAL_Logging_Filter filter_) - { - m_attributes.console.filter_log = filter_; - } - - eCAL_Logging_eLogLevel CLog::GetLogLevel() - { - const std::lock_guard lock(m_log_mtx); - return(m_attributes.level); - } - - void CLog::Log(const eCAL_Logging_eLogLevel level_, const std::string& msg_) - { - const std::lock_guard lock(m_log_mtx); - - if(!m_created) return; - if(msg_.empty()) return; - - const eCAL_Logging_Filter log_con = level_ & m_attributes.console.filter_log; - const eCAL_Logging_Filter log_file = level_ & m_attributes.file.filter_log; - const eCAL_Logging_Filter log_udp = level_ & m_attributes.udp.filter_log; - if((log_con | log_file | log_udp) == 0) return; - - auto log_time = eCAL::Time::ecal_clock::now(); - - const bool log_to_console = m_attributes.console.enabled && log_con != 0; - const bool log_to_file = m_attributes.file.enabled && log_file != 0; - - if (log_to_console || log_to_file) - { - std::stringstream string_stream; - createLogHeader(string_stream, level_, m_attributes, log_time); - string_stream << msg_; - - if(log_to_console) - { - std::cout << string_stream.str() << '\n'; - } - - if (log_to_file) - { - fprintf(m_logfile, "%s\n", string_stream.str().c_str()); - fflush(m_logfile); - } - } - - if(m_attributes.udp.enabled && log_udp != 0 && m_udp_logging_sender) - { - // set up log message - Logging::SLogMessage log_message; - log_message.time = std::chrono::duration_cast(log_time.time_since_epoch()).count(); - log_message.hname = m_attributes.host_name; - log_message.pid = m_attributes.process_id; - log_message.pname = m_attributes.process_name; - log_message.uname = m_attributes.unit_name; - log_message.level = level_; - log_message.content = msg_; - - // sent it - m_log_message_vec.clear(); - SerializeToBuffer(log_message, m_log_message_vec); - m_udp_logging_sender->Send("_log_message_", m_log_message_vec); - } - } - - void CLog::Log(const std::string& msg_) - { - Log(m_attributes.level, msg_); - } - - void CLog::GetLogging(std::string& log_msg_list_string_) - { - // clear target list string - log_msg_list_string_.clear(); - - // serialize message list - { - const std::lock_guard lock(m_log_mtx); - // serialize message list to target list string - SerializeToBuffer(m_log_msglist, log_msg_list_string_); - // clear message list - m_log_msglist.log_messages.clear(); - } - } - - void CLog::GetLogging(Logging::SLogging& log_) - { - // copy message list - { - const std::lock_guard lock(m_log_mtx); - log_ = m_log_msglist; - // clear message list - m_log_msglist.log_messages.clear(); - } - } - - bool CLog::HasSample(const std::string& sample_name_) - { - return (sample_name_ == "_log_message_"); - } - - bool CLog::ApplySample(const char* serialized_sample_data_, size_t serialized_sample_size_) - { - // TODO: Limit maximum size of collected log messages ! - Logging::SLogMessage log_message; - if (DeserializeFromBuffer(serialized_sample_data_, serialized_sample_size_, log_message)) - { - // in "network mode" we accept all log messages - // in "local mode" we accept log messages from this host only - if ((m_attributes.host_name == log_message.hname) || m_attributes.network_enabled) - { - const std::lock_guard lock(m_log_mtx); - m_log_msglist.log_messages.emplace_back(log_message); - } - return true; - } - return false; - } -} diff --git a/ecal/core/src/logging/ecal_log_impl.h b/ecal/core/src/logging/ecal_log_impl.h deleted file mode 100644 index 03aa0210ac..0000000000 --- a/ecal/core/src/logging/ecal_log_impl.h +++ /dev/null @@ -1,148 +0,0 @@ -/* ========================= 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 eCAL logging class -**/ - -#pragma once - -#include "io/udp/ecal_udp_sample_receiver.h" -#include "io/udp/ecal_udp_sample_sender.h" - -#include -#include -#include - -#include -#include - -#include "config/attributes/logging_attributes.h" -#include "ecal_global_accessors.h" - -#include -#include -#include -#include -#include -#include - -namespace eCAL -{ - class CLog - { - public: - /** - * @brief Constructor. - **/ - CLog(const Logging::SAttributes& attr_); - - /** - * @brief Destructor. - **/ - ~CLog(); - - /** - * @brief Start logging. - **/ - void Start(); - - /** - * @brief Stop logging. - **/ - void Stop(); - - /** - * @brief Sets the log level. - * - * @param level_ The level. - **/ - void SetLogLevel(eCAL_Logging_eLogLevel level_); - - /** - * @brief Sets the log filter for file. - * - * @param filter_ The filter. - */ - void SetFileLogFilter(eCAL_Logging_Filter filter_); - - /** - * @brief Sets the log filter for udp. - * - * @param filter_ The filter. - */ - void SetUDPLogFilter(eCAL_Logging_Filter filter_); - - /** - * @brief Sets the log filter for console. - * - * @param filter_ The filter. - */ - void SetConsoleLogFilter(eCAL_Logging_Filter filter_); - - /** - * @brief Set the current log level. - * - * @return The current log level. - **/ - eCAL_Logging_eLogLevel GetLogLevel(); - - /** - * @brief Log a message. - * - * @param level_ The level. - * @param msg_ The message. - **/ - void Log(eCAL_Logging_eLogLevel level_, const std::string& msg_); - - /** - * @brief Log a message (with the current log level). - * - * @param msg_ The message. - **/ - void Log(const std::string& msg_); - - void GetLogging(std::string& log_msg_list_string_); - void GetLogging(Logging::SLogging& log_); - - private: - bool HasSample(const std::string& sample_name_); - bool ApplySample(const char* serialized_sample_data_, size_t serialized_sample_size_); - - CLog(const CLog&); // prevent copy-construction - CLog& operator=(const CLog&); // prevent assignment - - std::mutex m_log_mtx; - - std::atomic m_created; - std::unique_ptr m_udp_logging_sender; - - // log message list and log message serialization buffer - Logging::SLogging m_log_msglist; - std::vector m_log_message_vec; - - // udp logging receiver - std::shared_ptr m_log_receiver; - - std::string m_logfile_name; - FILE* m_logfile; - - Logging::SAttributes m_attributes; - }; -} diff --git a/ecal/core/src/logging/ecal_log_provider.cpp b/ecal/core/src/logging/ecal_log_provider.cpp new file mode 100644 index 0000000000..d77ff160b0 --- /dev/null +++ b/ecal/core/src/logging/ecal_log_provider.cpp @@ -0,0 +1,306 @@ +/* ========================= 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 "ecal_log_provider.h" +#include "serialization/ecal_serialize_logging.h" +#include "config/builder/udp_attribute_builder.h" + +#include +#include + +#include +#include +#include + +#ifdef ECAL_OS_WINDOWS +#include "ecal_win_main.h" +#include + +namespace +{ + std::string get_time_str() + { + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + std::stringstream tstream; + tstream << std::put_time(&tm, "%Y-%m-%d-%H-%M-%S"); + return(tstream.str()); + } +} +#endif + +#ifdef ECAL_OS_LINUX +#include +#include +#include + +namespace{ + bool isDirectory(const std::string& path_) + { + if (path_.empty()) return false; + + struct stat st; + if (stat(path_.c_str(), &st) == 0) + return S_ISDIR(st.st_mode); + + return false; + } + + std::string get_time_str() + { + char fmt[64]; + struct timeval tv; + struct tm *tm = nullptr; + gettimeofday(&tv, nullptr); + tm = localtime(&tv.tv_sec); + if (tm != nullptr) + { + strftime(fmt, sizeof fmt, "%Y-%m-%d-%H-%M-%S", tm); + } + return(std::string(fmt)); + } +} +#endif + +namespace +{ + void logWarningToConsole(const std::string& msg_) + { + std::cout << "[eCAL][Logging-Provider][Warning] " << msg_ << "\n"; + } + + void createLogHeader(std::stringstream& msg_stream, const eCAL_Logging_eLogLevel level_, const eCAL::Logging::SProviderAttributes& attr_, const eCAL::Time::ecal_clock::time_point& log_time_) + { + msg_stream << std::chrono::duration_cast(log_time_.time_since_epoch()).count(); + msg_stream << " ms"; + msg_stream << " | "; + msg_stream << attr_.host_name; + msg_stream << " | "; + msg_stream << attr_.unit_name; + msg_stream << " | "; + msg_stream << attr_.process_id; + msg_stream << " | "; + switch(level_) + { + case log_level_none: + case log_level_all: + break; + case log_level_info: + msg_stream << "info"; + break; + case log_level_warning: + msg_stream << "warning"; + break; + case log_level_error: + msg_stream << "error"; + break; + case log_level_fatal: + msg_stream << "fatal"; + break; + case log_level_debug1: + msg_stream << "debug1"; + break; + case log_level_debug2: + msg_stream << "debug2"; + break; + case log_level_debug3: + msg_stream << "debug3"; + break; + case log_level_debug4: + msg_stream << "debug4"; + break; + } + msg_stream << " | "; + } + + bool isDirectoryOrCreate(const std::string& path_) + { + if (path_.empty()) return false; + + bool path_exists = EcalUtils::Filesystem::IsDir(path_, EcalUtils::Filesystem::Current); + if (!path_exists) + { + path_exists = EcalUtils::Filesystem::MkDir(path_, EcalUtils::Filesystem::Current); + } + + return path_exists; + } +} + +namespace eCAL +{ + namespace Logging + { + CLogProvider::CLogProvider(const SProviderAttributes& attr_) + : m_attributes(attr_) + , m_created(false) + , m_logfile(nullptr) + { + } + + CLogProvider::~CLogProvider() + { + Stop(); + } + + void CLogProvider::SetLogLevel(const eCAL_Logging_eLogLevel level_) + { + const std::lock_guard lock(m_log_mtx); + m_attributes.level = level_; + } + + void CLogProvider::SetFileLogFilter(eCAL_Logging_Filter filter_) + { + m_attributes.file_sink.filter_log = filter_; + } + + void CLogProvider::SetUDPLogFilter(eCAL_Logging_Filter filter_) + { + m_attributes.udp_sink.filter_log = filter_; + } + + void CLogProvider::SetConsoleLogFilter(eCAL_Logging_Filter filter_) + { + m_attributes.console_sink.filter_log = filter_; + } + + eCAL_Logging_eLogLevel CLogProvider::GetLogLevel() + { + const std::lock_guard lock(m_log_mtx); + return(m_attributes.level); + } + + void CLogProvider::Start() + { + // create log file if file logging is enabled + if (m_attributes.file_sink.enabled) + { + if (!StartFileLogging()) + { + logWarningToConsole("Logging for file enabled, but specified path to log is not valid or could not be created: " + m_attributes.file_config.path); + } + } + + // create udp logging sender if udp logging is enabled + if (m_attributes.udp_sink.enabled) + { + // create udp logging sender + if (!StartUDPLogging()) + { + logWarningToConsole("Logging for udp enabled, but could not create udp logging sender."); + } + } + + m_created = true; + } + + bool CLogProvider::StartFileLogging() + { + if (!isDirectoryOrCreate(m_attributes.file_config.path)) return false; + + const std::string tstring = get_time_str(); + + m_logfile_name = m_attributes.file_config.path + tstring + "_" + m_attributes.unit_name + "_" + std::to_string(m_attributes.process_id) + ".log"; + m_logfile = fopen(m_logfile_name.c_str(), "w"); + + return m_logfile != nullptr; + } + + bool CLogProvider::StartUDPLogging() + { + const eCAL::UDP::SSenderAttr attr = Logging::UDP::ConvertToIOUDPSenderAttributes(m_attributes.udp_config); + m_udp_logging_sender = std::make_unique(attr); + + return m_udp_logging_sender != nullptr; + } + + void CLogProvider::Log(const eCAL_Logging_eLogLevel level_, const std::string& msg_) + { + const std::lock_guard lock(m_log_mtx); + + if(!m_created) return; + if(msg_.empty()) return; + + const eCAL_Logging_Filter log_con = level_ & m_attributes.console_sink.filter_log; + const eCAL_Logging_Filter log_file = level_ & m_attributes.file_sink.filter_log; + const eCAL_Logging_Filter log_udp = level_ & m_attributes.udp_sink.filter_log; + if((log_con | log_file | log_udp) == 0) return; + + auto log_time = eCAL::Time::ecal_clock::now(); + + const bool log_to_console = m_attributes.console_sink.enabled && log_con != 0; + const bool log_to_file = m_attributes.file_sink.enabled && log_file != 0; + + if (log_to_console || log_to_file) + { + std::stringstream string_stream; + createLogHeader(string_stream, level_, m_attributes, log_time); + string_stream << msg_; + + if(log_to_console) + { + std::cout << string_stream.str() << '\n'; + } + + if (log_to_file) + { + fprintf(m_logfile, "%s\n", string_stream.str().c_str()); + fflush(m_logfile); + } + } + + if(m_attributes.udp_sink.enabled && log_udp != 0 && m_udp_logging_sender) + { + // set up log message + Logging::SLogMessage log_message; + log_message.time = std::chrono::duration_cast(log_time.time_since_epoch()).count(); + log_message.hname = m_attributes.host_name; + log_message.pid = m_attributes.process_id; + log_message.pname = m_attributes.process_name; + log_message.uname = m_attributes.unit_name; + log_message.level = level_; + log_message.content = msg_; + + // sent it + m_log_message_vec.clear(); + SerializeToBuffer(log_message, m_log_message_vec); + m_udp_logging_sender->Send("_log_message_", m_log_message_vec); + } + } + + void CLogProvider::Log(const std::string& msg_) + { + Log(m_attributes.level, msg_); + } + + void CLogProvider::Stop() + { + if(!m_created) return; + + const std::lock_guard lock(m_log_mtx); + + m_udp_logging_sender.reset(); + + if(m_logfile != nullptr) fclose(m_logfile); + m_logfile = nullptr; + + m_created = false; + } + } +} \ No newline at end of file diff --git a/ecal/core/src/logging/ecal_log_provider.h b/ecal/core/src/logging/ecal_log_provider.h new file mode 100644 index 0000000000..f9d84307d6 --- /dev/null +++ b/ecal/core/src/logging/ecal_log_provider.h @@ -0,0 +1,140 @@ +/* ========================= 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 eCAL logging provider class +**/ + +#pragma once + +#include "config/attributes/ecal_log_provider_attributes.h" +#include "io/udp/ecal_udp_sample_sender.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace eCAL +{ + namespace Logging + { + class CLogProvider + { + public: + /** + * @brief Constructor. + **/ + CLogProvider(const SProviderAttributes& attr_); + + /** + * @brief Destructor. + **/ + ~CLogProvider(); + + /** + * @brief Start logging. + **/ + void Start(); + + /** + * @brief Stop logging. + **/ + void Stop(); + + /** + * @brief Sets the log level. + * + * @param level_ The level. + **/ + void SetLogLevel(eCAL_Logging_eLogLevel level_); + + /** + * @brief Sets the log filter for file. + * + * @param filter_ The filter. + */ + void SetFileLogFilter(eCAL_Logging_Filter filter_); + + /** + * @brief Sets the log filter for udp. + * + * @param filter_ The filter. + */ + void SetUDPLogFilter(eCAL_Logging_Filter filter_); + + /** + * @brief Sets the log filter for console. + * + * @param filter_ The filter. + */ + void SetConsoleLogFilter(eCAL_Logging_Filter filter_); + + /** + * @brief Set the current log level. + * + * @return The current log level. + **/ + eCAL_Logging_eLogLevel GetLogLevel(); + + /** + * @brief Log a message. + * + * @param level_ The level. + * @param msg_ The message. + **/ + void Log(eCAL_Logging_eLogLevel level_, const std::string& msg_); + + /** + * @brief Log a message (with the current log level). + * + * @param msg_ The message. + **/ + void Log(const std::string& msg_); + + private: + + CLogProvider(const CLogProvider&); // prevent copy-construction + CLogProvider& operator=(const CLogProvider&); // prevent assignment + + bool StartFileLogging(); + bool StartUDPLogging(); + + std::mutex m_log_mtx; + + std::atomic m_created; + std::unique_ptr m_udp_logging_sender; + + // log message list and log message serialization buffer + Logging::SLogging m_log_msglist; + std::vector m_log_message_vec; + + std::string m_logfile_name; + FILE* m_logfile; + + SProviderAttributes m_attributes; + + }; + } +} \ No newline at end of file diff --git a/ecal/core/src/logging/ecal_log_receiver.cpp b/ecal/core/src/logging/ecal_log_receiver.cpp new file mode 100644 index 0000000000..7251bfec14 --- /dev/null +++ b/ecal/core/src/logging/ecal_log_receiver.cpp @@ -0,0 +1,127 @@ +/* ========================= 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 "ecal_log_receiver.h" + +#include "config/builder/udp_attribute_builder.h" +#include "serialization/ecal_serialize_logging.h" + +#include + +namespace +{ + void logWarningToConsole(const std::string& msg_) + { + std::cout << "[eCAL][Logging-Receiver][Warning] " << msg_ << "\n"; + } +} + +namespace eCAL +{ + namespace Logging + { + CLogReceiver::CLogReceiver(const SReceiverAttributes& attr_) + : m_attributes(attr_) + , m_created(false) + { + } + + CLogReceiver::~CLogReceiver() + { + Stop(); + } + + void CLogReceiver::Start() + { + if (m_attributes.receive_enabled) + { + // set logging receive network attributes + const eCAL::UDP::SReceiverAttr attr = Logging::UDP::ConvertToIOUDPReceiverAttributes(m_attributes.udp_receiver); + + // start logging receiver + m_log_receiver = std::make_shared(attr, std::bind(&CLogReceiver::HasSample, this, std::placeholders::_1), std::bind(&CLogReceiver::ApplySample, this, std::placeholders::_1, std::placeholders::_2)); + + if(m_log_receiver == nullptr) + { + logWarningToConsole("Logging receiver could not be created."); + } + } + + m_created = true; + } + + void CLogReceiver::Stop() + { + if(!m_created) return; + + m_log_receiver.reset(); + + m_created = false; + } + + void CLogReceiver::GetLogging(std::string& log_msg_list_string_) + { + // clear target list string + log_msg_list_string_.clear(); + + // serialize message list + { + const std::lock_guard lock(m_log_mtx); + // serialize message list to target list string + SerializeToBuffer(m_log_msglist, log_msg_list_string_); + // clear message list + m_log_msglist.log_messages.clear(); + } + } + + void CLogReceiver::GetLogging(Logging::SLogging& log_) + { + // copy message list + { + const std::lock_guard lock(m_log_mtx); + log_ = m_log_msglist; + // clear message list + m_log_msglist.log_messages.clear(); + } + } + + bool CLogReceiver::HasSample(const std::string& sample_name_) + { + return (sample_name_ == "_log_message_"); + } + + bool CLogReceiver::ApplySample(const char* serialized_sample_data_, size_t serialized_sample_size_) + { + // TODO: Limit maximum size of collected log messages ! + Logging::SLogMessage log_message; + if (DeserializeFromBuffer(serialized_sample_data_, serialized_sample_size_, log_message)) + { + // in "network mode" we accept all log messages + // in "local mode" we accept log messages from this host only + if ((m_attributes.host_name == log_message.hname) || m_attributes.network_enabled) + { + const std::lock_guard lock(m_log_mtx); + m_log_msglist.log_messages.emplace_back(log_message); + } + return true; + } + return false; + } + } +} \ No newline at end of file diff --git a/ecal/core/src/logging/ecal_log_receiver.h b/ecal/core/src/logging/ecal_log_receiver.h new file mode 100644 index 0000000000..a41bbd8a91 --- /dev/null +++ b/ecal/core/src/logging/ecal_log_receiver.h @@ -0,0 +1,95 @@ +/* ========================= 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 eCAL logging receiver class +**/ + +#pragma once + +#include "config/attributes/ecal_log_receiver_attributes.h" +#include "io/udp/ecal_udp_sample_receiver.h" + +#include + +#include +#include +#include +#include +#include + +namespace eCAL +{ + namespace Logging + { + class CLogReceiver + { + public: + /** + * @brief Constructor. + **/ + CLogReceiver(const SReceiverAttributes& attr_); + + /** + * @brief Destructor. + **/ + ~CLogReceiver(); + + /** + * @brief Start logging. + **/ + void Start(); + + /** + * @brief Stop logging. + **/ + void Stop(); + + /** + * @brief Get the log messages. + * + * @param log_msg_list_string_ The log messages. + **/ + void GetLogging(std::string& log_msg_list_string_); + + /** + * @brief Get the log messages. + * + * @param log_ The log messages. + **/ + void GetLogging(Logging::SLogging& log_); + + private: + bool HasSample(const std::string& sample_name_); + bool ApplySample(const char* serialized_sample_data_, size_t serialized_sample_size_); + + std::atomic m_created; + + std::mutex m_log_mtx; + + SReceiverAttributes m_attributes; + + // log message list and log message serialization buffer + Logging::SLogging m_log_msglist; + std::vector m_log_message_vec; + + std::shared_ptr m_log_receiver; + }; + } +} \ No newline at end of file diff --git a/ecal/core/src/pubsub/ecal_publisher.cpp b/ecal/core/src/pubsub/ecal_publisher.cpp index 68547633fc..28c4e2f805 100644 --- a/ecal/core/src/pubsub/ecal_publisher.cpp +++ b/ecal/core/src/pubsub/ecal_publisher.cpp @@ -113,7 +113,7 @@ namespace eCAL if(g_pubgate() != nullptr) g_pubgate()->Unregister(m_datawriter->GetTopicName(), m_datawriter); #ifndef NDEBUG // log it - if (g_log() != nullptr) g_log()->Log(log_level_debug1, std::string(m_datawriter->GetTopicName() + "::CPublisher::Destroy")); + eCAL::Logging::Log(log_level_debug1, std::string(m_datawriter->GetTopicName() + "::CPublisher::Destroy")); #endif // stop & destroy datawriter diff --git a/ecal/core/src/pubsub/ecal_subscriber.cpp b/ecal/core/src/pubsub/ecal_subscriber.cpp index f5ef6d50aa..4ba910956d 100644 --- a/ecal/core/src/pubsub/ecal_subscriber.cpp +++ b/ecal/core/src/pubsub/ecal_subscriber.cpp @@ -105,7 +105,7 @@ namespace eCAL #ifndef NDEBUG // log it - if (g_log() != nullptr) g_log()->Log(log_level_debug1, std::string(m_datareader->GetTopicName() + "::CSubscriber::Destroy")); + eCAL::Logging::Log(log_level_debug1, std::string(m_datareader->GetTopicName() + "::CSubscriber::Destroy")); #endif // stop & destroy datareader diff --git a/ecal/core/src/serialization/ecal_serialize_common.cpp b/ecal/core/src/serialization/ecal_serialize_common.cpp index 13d0649240..461e55880c 100644 --- a/ecal/core/src/serialization/ecal_serialize_common.cpp +++ b/ecal/core/src/serialization/ecal_serialize_common.cpp @@ -354,6 +354,17 @@ namespace eCAL encode_string(pb_method.resp_type, method.resp_type); encode_string(pb_method.req_desc, method.req_desc); encode_string(pb_method.resp_desc, method.resp_desc); + + pb_method.has_req_datatype = true; + encode_string(pb_method.req_datatype.name, method.req_datatype.name); + encode_string(pb_method.req_datatype.encoding, method.req_datatype.encoding); + encode_string(pb_method.req_datatype.desc, method.req_datatype.descriptor); + + pb_method.has_resp_datatype = true; + encode_string(pb_method.resp_datatype.name, method.resp_datatype.name); + encode_string(pb_method.resp_datatype.encoding, method.resp_datatype.encoding); + encode_string(pb_method.resp_datatype.desc, method.resp_datatype.descriptor); + pb_method.call_count = method.call_count; if (!pb_encode_submessage(stream, eCAL_pb_Method_fields, &pb_method)) @@ -387,6 +398,14 @@ namespace eCAL decode_string(pb_method.resp_type, method.resp_type); decode_string(pb_method.resp_desc, method.resp_desc); + decode_string(pb_method.req_datatype.name, method.req_datatype.name); + decode_string(pb_method.req_datatype.encoding, method.req_datatype.encoding); + decode_string(pb_method.req_datatype.desc, method.req_datatype.descriptor); + + decode_string(pb_method.resp_datatype.name, method.resp_datatype.name); + decode_string(pb_method.resp_datatype.encoding, method.resp_datatype.encoding); + decode_string(pb_method.resp_datatype.desc, method.resp_datatype.descriptor); + // decode it if (!pb_decode(stream, eCAL_pb_Method_fields, &pb_method)) { diff --git a/ecal/core/src/serialization/ecal_serialize_monitoring.cpp b/ecal/core/src/serialization/ecal_serialize_monitoring.cpp index 59fafbff19..877c081a37 100644 --- a/ecal/core/src/serialization/ecal_serialize_monitoring.cpp +++ b/ecal/core/src/serialization/ecal_serialize_monitoring.cpp @@ -265,9 +265,20 @@ namespace eCAL_pb_Method pb_method = eCAL_pb_Method_init_default; eCAL::nanopb::encode_string(pb_method.mname, method.mname); eCAL::nanopb::encode_string(pb_method.req_type, method.req_type); - eCAL::nanopb::encode_string(pb_method.resp_type, method.resp_type); eCAL::nanopb::encode_string(pb_method.req_desc, method.req_desc); + eCAL::nanopb::encode_string(pb_method.resp_type, method.resp_type); eCAL::nanopb::encode_string(pb_method.resp_desc, method.resp_desc); + + pb_method.has_req_datatype = true; + eCAL::nanopb::encode_string(pb_method.req_datatype.name, method.req_datatype.name); + eCAL::nanopb::encode_string(pb_method.req_datatype.encoding, method.req_datatype.encoding); + eCAL::nanopb::encode_string(pb_method.req_datatype.desc, method.req_datatype.descriptor); + + pb_method.has_resp_datatype = true; + eCAL::nanopb::encode_string(pb_method.resp_datatype.name, method.resp_datatype.name); + eCAL::nanopb::encode_string(pb_method.resp_datatype.encoding, method.resp_datatype.encoding); + eCAL::nanopb::encode_string(pb_method.resp_datatype.desc, method.resp_datatype.descriptor); + pb_method.call_count = method.call_count; if (!pb_encode_submessage(stream, eCAL_pb_Method_fields, &pb_method)) @@ -693,11 +704,20 @@ namespace // decode method parameter eCAL::nanopb::decode_string(pb_method.mname, method.mname); + eCAL::nanopb::decode_string(pb_method.req_type, method.req_type); eCAL::nanopb::decode_string(pb_method.req_desc, method.req_desc); eCAL::nanopb::decode_string(pb_method.resp_type, method.resp_type); eCAL::nanopb::decode_string(pb_method.resp_desc, method.resp_desc); + eCAL::nanopb::decode_string(pb_method.req_datatype.name, method.req_datatype.name); + eCAL::nanopb::decode_string(pb_method.req_datatype.encoding, method.req_datatype.encoding); + eCAL::nanopb::decode_string(pb_method.req_datatype.desc, method.req_datatype.descriptor); + + eCAL::nanopb::decode_string(pb_method.resp_datatype.name, method.resp_datatype.name); + eCAL::nanopb::decode_string(pb_method.resp_datatype.encoding, method.resp_datatype.encoding); + eCAL::nanopb::decode_string(pb_method.resp_datatype.desc, method.resp_datatype.descriptor); + // decode it if (!pb_decode(stream, eCAL_pb_Method_fields, &pb_method)) { diff --git a/ecal/core/src/serialization/ecal_struct_service.h b/ecal/core/src/serialization/ecal_struct_service.h index 9757207292..d28e095422 100644 --- a/ecal/core/src/serialization/ecal_struct_service.h +++ b/ecal/core/src/serialization/ecal_struct_service.h @@ -29,6 +29,7 @@ #include #include +#include #include namespace eCAL @@ -119,10 +120,15 @@ namespace eCAL struct Method { std::string mname; // Method name - std::string req_type; // Request type - std::string req_desc; // Request descriptor - std::string resp_type; // Response type - std::string resp_desc; // Response descriptor + + std::string req_type; // Request type (deprecated use req_datatype) + std::string req_desc; // Request descriptor (deprecated use req_datatype) + std::string resp_type; // Response type (deprecated use resp_datatype) + std::string resp_desc; // Response descriptor (deprecated use resp_datatype) + + SDataTypeInformation req_datatype; // Request datatype information (encoding & type & description) + SDataTypeInformation resp_datatype; // Response datatype information (encoding & type & description) + int64_t call_count = 0; // Call counter bool operator==(const Method& other) const { @@ -131,6 +137,8 @@ namespace eCAL req_desc == other.req_desc && resp_type == other.resp_type && resp_desc == other.resp_desc && + req_datatype == other.req_datatype && + resp_datatype == other.resp_datatype && call_count == other.call_count; } diff --git a/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.c b/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.c new file mode 100644 index 0000000000..2f35c2c038 --- /dev/null +++ b/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.9 */ + +#include "datatype.npb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(eCAL_pb_DataTypeInformation, eCAL_pb_DataTypeInformation, AUTO) + + + diff --git a/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.h b/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.h new file mode 100644 index 0000000000..fe8816b31a --- /dev/null +++ b/ecal/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.h @@ -0,0 +1,53 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.9 */ + +#ifndef PB_ECAL_PB_DATATYPE_NPB_H_INCLUDED +#define PB_ECAL_PB_DATATYPE_NPB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Struct definitions */ +typedef struct _eCAL_pb_DataTypeInformation { + pb_callback_t name; /* name of the datatype */ + pb_callback_t encoding; /* encoding of the datatype (e.g. protobuf, flatbuffers, capnproto) */ + pb_callback_t desc; /* descriptor information of the datatype (necessary for reflection) */ +} eCAL_pb_DataTypeInformation; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define eCAL_pb_DataTypeInformation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} +#define eCAL_pb_DataTypeInformation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} + +/* Field tags (for use in manual encoding/decoding) */ +#define eCAL_pb_DataTypeInformation_name_tag 1 +#define eCAL_pb_DataTypeInformation_encoding_tag 2 +#define eCAL_pb_DataTypeInformation_desc_tag 3 + +/* Struct field encoding specification for nanopb */ +#define eCAL_pb_DataTypeInformation_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, STRING, name, 1) \ +X(a, CALLBACK, SINGULAR, STRING, encoding, 2) \ +X(a, CALLBACK, SINGULAR, BYTES, desc, 3) +#define eCAL_pb_DataTypeInformation_CALLBACK pb_default_field_callback +#define eCAL_pb_DataTypeInformation_DEFAULT NULL + +extern const pb_msgdesc_t eCAL_pb_DataTypeInformation_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define eCAL_pb_DataTypeInformation_fields &eCAL_pb_DataTypeInformation_msg + +/* Maximum encoded size of messages (where known) */ +/* eCAL_pb_DataTypeInformation_size depends on runtime parameters */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/ecal/core/src/serialization/nanopb/ecal/core/pb/service.npb.h b/ecal/core/src/serialization/nanopb/ecal/core/pb/service.npb.h index f60c1b2ce6..27d8ade85b 100644 --- a/ecal/core/src/serialization/nanopb/ecal/core/pb/service.npb.h +++ b/ecal/core/src/serialization/nanopb/ecal/core/pb/service.npb.h @@ -4,6 +4,7 @@ #ifndef PB_ECAL_PB_SERVICE_NPB_H_INCLUDED #define PB_ECAL_PB_SERVICE_NPB_H_INCLUDED #include +#include "ecal/core/pb/datatype.npb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. @@ -42,11 +43,15 @@ typedef struct _eCAL_pb_Response { typedef struct _eCAL_pb_Method { pb_callback_t mname; /* method name */ - pb_callback_t req_type; /* request type */ - pb_callback_t resp_type; /* response type */ + pb_callback_t req_type; /* request type (deprecated use req_datatype) */ + pb_callback_t resp_type; /* response type (deprecated use resp_datatype) */ int64_t call_count; /* call counter */ - pb_callback_t req_desc; /* request descriptor */ - pb_callback_t resp_desc; /* response descriptor */ + pb_callback_t req_desc; /* request descriptor (deprecated use req_datatype) */ + pb_callback_t resp_desc; /* response descriptor (deprecated use resp_datatype) */ + bool has_req_datatype; + eCAL_pb_DataTypeInformation req_datatype; /* request datatype information (encoding & type & description) */ + bool has_resp_datatype; + eCAL_pb_DataTypeInformation resp_datatype; /* response datatype information (encoding & type & description) */ } eCAL_pb_Method; typedef struct _eCAL_pb_Service { @@ -56,7 +61,7 @@ typedef struct _eCAL_pb_Service { pb_callback_t uname; /* unit name */ int32_t pid; /* process id */ pb_callback_t sname; /* service name */ - uint32_t tcp_port_v0; /* the tcp port used for that service */ + uint32_t tcp_port_v0; /* the tcp port used for that service (deprecated) */ pb_callback_t methods; /* list of methods */ pb_callback_t sid; /* service id */ /* transport specific parameter (for internal use) */ @@ -99,13 +104,13 @@ extern "C" { #define eCAL_pb_ServiceHeader_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, _eCAL_pb_ServiceHeader_eCallState_MIN, {{NULL}, NULL}} #define eCAL_pb_Request_init_default {false, eCAL_pb_ServiceHeader_init_default, {{NULL}, NULL}} #define eCAL_pb_Response_init_default {false, eCAL_pb_ServiceHeader_init_default, {{NULL}, NULL}, 0} -#define eCAL_pb_Method_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}} +#define eCAL_pb_Method_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, false, eCAL_pb_DataTypeInformation_init_default, false, eCAL_pb_DataTypeInformation_init_default} #define eCAL_pb_Service_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0} #define eCAL_pb_Client_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}} #define eCAL_pb_ServiceHeader_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, _eCAL_pb_ServiceHeader_eCallState_MIN, {{NULL}, NULL}} #define eCAL_pb_Request_init_zero {false, eCAL_pb_ServiceHeader_init_zero, {{NULL}, NULL}} #define eCAL_pb_Response_init_zero {false, eCAL_pb_ServiceHeader_init_zero, {{NULL}, NULL}, 0} -#define eCAL_pb_Method_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}} +#define eCAL_pb_Method_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, false, eCAL_pb_DataTypeInformation_init_zero, false, eCAL_pb_DataTypeInformation_init_zero} #define eCAL_pb_Service_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0} #define eCAL_pb_Client_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, 0, {{NULL}, NULL}} @@ -128,6 +133,8 @@ extern "C" { #define eCAL_pb_Method_call_count_tag 4 #define eCAL_pb_Method_req_desc_tag 5 #define eCAL_pb_Method_resp_desc_tag 6 +#define eCAL_pb_Method_req_datatype_tag 7 +#define eCAL_pb_Method_resp_datatype_tag 8 #define eCAL_pb_Service_rclock_tag 1 #define eCAL_pb_Service_hname_tag 2 #define eCAL_pb_Service_pname_tag 3 @@ -182,9 +189,13 @@ X(a, CALLBACK, SINGULAR, STRING, req_type, 2) \ X(a, CALLBACK, SINGULAR, STRING, resp_type, 3) \ X(a, STATIC, SINGULAR, INT64, call_count, 4) \ X(a, CALLBACK, SINGULAR, BYTES, req_desc, 5) \ -X(a, CALLBACK, SINGULAR, BYTES, resp_desc, 6) +X(a, CALLBACK, SINGULAR, BYTES, resp_desc, 6) \ +X(a, STATIC, OPTIONAL, MESSAGE, req_datatype, 7) \ +X(a, STATIC, OPTIONAL, MESSAGE, resp_datatype, 8) #define eCAL_pb_Method_CALLBACK pb_default_field_callback #define eCAL_pb_Method_DEFAULT NULL +#define eCAL_pb_Method_req_datatype_MSGTYPE eCAL_pb_DataTypeInformation +#define eCAL_pb_Method_resp_datatype_MSGTYPE eCAL_pb_DataTypeInformation #define eCAL_pb_Service_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, rclock, 1) \ diff --git a/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.c b/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.c index 85f7d1970a..c192e6fafe 100644 --- a/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.c +++ b/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.c @@ -6,9 +6,6 @@ #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(eCAL_pb_DataTypeInformation, eCAL_pb_DataTypeInformation, AUTO) - - PB_BIND(eCAL_pb_Topic, eCAL_pb_Topic, 2) diff --git a/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.h b/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.h index 97993e98a4..56ba216513 100644 --- a/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.h +++ b/ecal/core/src/serialization/nanopb/ecal/core/pb/topic.npb.h @@ -5,18 +5,13 @@ #define PB_ECAL_PB_TOPIC_NPB_H_INCLUDED #include #include "ecal/core/pb/layer.npb.h" +#include "ecal/core/pb/datatype.npb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif /* Struct definitions */ -typedef struct _eCAL_pb_DataTypeInformation { - pb_callback_t name; /* name of the datatype */ - pb_callback_t encoding; /* encoding of the datatype (e.g. protobuf, flatbuffers, capnproto) */ - pb_callback_t desc; /* descriptor information of the datatype (necessary for reflection) */ -} eCAL_pb_DataTypeInformation; - typedef struct _eCAL_pb_Topic { /* Reserved fields in enums are not supported in protobuf 3.0 reserved 9, 10, 11, 14, 15, 22 to 26, 29; */ int32_t rclock; /* registration clock (heart beat) */ @@ -54,17 +49,12 @@ extern "C" { #endif /* Initializer values for message structs */ -#define eCAL_pb_DataTypeInformation_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} #define eCAL_pb_Topic_init_default {0, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, false, eCAL_pb_DataTypeInformation_init_default} #define eCAL_pb_Topic_AttrEntry_init_default {{{NULL}, NULL}, {{NULL}, NULL}} -#define eCAL_pb_DataTypeInformation_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} #define eCAL_pb_Topic_init_zero {0, {{NULL}, NULL}, 0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, 0, 0, 0, 0, {{NULL}, NULL}, {{NULL}, NULL}, false, eCAL_pb_DataTypeInformation_init_zero} #define eCAL_pb_Topic_AttrEntry_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} /* Field tags (for use in manual encoding/decoding) */ -#define eCAL_pb_DataTypeInformation_name_tag 1 -#define eCAL_pb_DataTypeInformation_encoding_tag 2 -#define eCAL_pb_DataTypeInformation_desc_tag 3 #define eCAL_pb_Topic_rclock_tag 1 #define eCAL_pb_Topic_hname_tag 2 #define eCAL_pb_Topic_pid_tag 3 @@ -88,13 +78,6 @@ extern "C" { #define eCAL_pb_Topic_AttrEntry_value_tag 2 /* Struct field encoding specification for nanopb */ -#define eCAL_pb_DataTypeInformation_FIELDLIST(X, a) \ -X(a, CALLBACK, SINGULAR, STRING, name, 1) \ -X(a, CALLBACK, SINGULAR, STRING, encoding, 2) \ -X(a, CALLBACK, SINGULAR, BYTES, desc, 3) -#define eCAL_pb_DataTypeInformation_CALLBACK pb_default_field_callback -#define eCAL_pb_DataTypeInformation_DEFAULT NULL - #define eCAL_pb_Topic_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, rclock, 1) \ X(a, CALLBACK, SINGULAR, STRING, hname, 2) \ @@ -127,17 +110,14 @@ X(a, CALLBACK, SINGULAR, STRING, value, 2) #define eCAL_pb_Topic_AttrEntry_CALLBACK pb_default_field_callback #define eCAL_pb_Topic_AttrEntry_DEFAULT NULL -extern const pb_msgdesc_t eCAL_pb_DataTypeInformation_msg; extern const pb_msgdesc_t eCAL_pb_Topic_msg; extern const pb_msgdesc_t eCAL_pb_Topic_AttrEntry_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define eCAL_pb_DataTypeInformation_fields &eCAL_pb_DataTypeInformation_msg #define eCAL_pb_Topic_fields &eCAL_pb_Topic_msg #define eCAL_pb_Topic_AttrEntry_fields &eCAL_pb_Topic_AttrEntry_msg /* Maximum encoded size of messages (where known) */ -/* eCAL_pb_DataTypeInformation_size depends on runtime parameters */ /* eCAL_pb_Topic_size depends on runtime parameters */ /* eCAL_pb_Topic_AttrEntry_size depends on runtime parameters */ diff --git a/ecal/core/src/types/ecal_custom_data_types.cpp b/ecal/core/src/types/ecal_custom_data_types.cpp index e6fe22c541..03fdcf1e87 100644 --- a/ecal/core/src/types/ecal_custom_data_types.cpp +++ b/ecal/core/src/types/ecal_custom_data_types.cpp @@ -30,13 +30,8 @@ #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])"); + const std::regex IPV4_DEC_REGEX = std::regex("^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$"); + const std::regex IPV4_HEX_REGEX = std::regex("^([0-9a-fA-F]{1,2}\\.){3}[0-9a-fA-F]{1,2}$"); } namespace eCAL @@ -48,34 +43,25 @@ namespace eCAL validateIpString(ip_address_); } + IpAddressV4::IpAddressV4(const char* 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_); + throw std::invalid_argument("[IpAddressV4] No valid IP address: " + 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& IpAddressV4::operator=(const char* ip_string_) { this->validateIpString(ip_string_); return *this; } diff --git a/ecal/core_pb/CMakeLists.txt b/ecal/core_pb/CMakeLists.txt index 7295221be0..6259f6a56a 100644 --- a/ecal/core_pb/CMakeLists.txt +++ b/ecal/core_pb/CMakeLists.txt @@ -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. @@ -21,6 +21,7 @@ project(core_pb) find_package(Protobuf REQUIRED) set(ProtoFiles + ${CMAKE_CURRENT_SOURCE_DIR}/src/ecal/core/pb/datatype.proto ${CMAKE_CURRENT_SOURCE_DIR}/src/ecal/core/pb/ecal.proto ${CMAKE_CURRENT_SOURCE_DIR}/src/ecal/core/pb/host.proto ${CMAKE_CURRENT_SOURCE_DIR}/src/ecal/core/pb/layer.proto diff --git a/ecal/core_pb/src/ecal/core/pb/datatype.proto b/ecal/core_pb/src/ecal/core/pb/datatype.proto new file mode 100644 index 0000000000..8eb0b9e881 --- /dev/null +++ b/ecal/core_pb/src/ecal/core/pb/datatype.proto @@ -0,0 +1,29 @@ +/* ========================= 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 ================================= +*/ + +syntax = "proto3"; + +package eCAL.pb; + +message DataTypeInformation +{ + string name = 1; // name of the datatype + string encoding = 2; // encoding of the datatype (e.g. protobuf, flatbuffers, capnproto) + bytes desc = 3; // descriptor information of the datatype (necessary for reflection) +} diff --git a/ecal/core_pb/src/ecal/core/pb/service.proto b/ecal/core_pb/src/ecal/core/pb/service.proto index addc84a5a2..8054bf314f 100644 --- a/ecal/core_pb/src/ecal/core/pb/service.proto +++ b/ecal/core_pb/src/ecal/core/pb/service.proto @@ -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. @@ -19,6 +19,8 @@ syntax = "proto3"; +import "ecal/core/pb/datatype.proto"; + package eCAL.pb; message ServiceHeader @@ -30,66 +32,71 @@ message ServiceHeader failed = 2; } - string hname = 1; // host name - string sname = 2; // service name - string sid = 7; // service id - string mname = 3; // method name - string error = 4; // error message - int32 id = 5; // session id - eCallState state = 6; // method call state + string hname = 1; // host name + string sname = 2; // service name + string sid = 7; // service id + string mname = 3; // method name + string error = 4; // error message + int32 id = 5; // session id + eCallState state = 6; // method call state } -message Request // client request +message Request // client request { - ServiceHeader header = 1; // common service header - bytes request = 2; // request payload + ServiceHeader header = 1; // common service header + bytes request = 2; // request payload } -message Response // server response +message Response // server response { - ServiceHeader header = 1; // common service header - bytes response = 2; // response payload - int64 ret_state = 3; // callback return state + ServiceHeader header = 1; // common service header + bytes response = 2; // response payload + int64 ret_state = 3; // callback return state } -message Method // method +message Method // method { - string mname = 1; // method name - string req_type = 2; // request type - bytes req_desc = 5; // request descriptor - string resp_type = 3; // response type - bytes resp_desc = 6; // response descriptor - int64 call_count = 4; // call counter + string mname = 1; // method name + + string req_type = 2; // request type (deprecated use req_datatype) + bytes req_desc = 5; // request descriptor (deprecated use req_datatype) + string resp_type = 3; // response type (deprecated use resp_datatype) + bytes resp_desc = 6; // response descriptor (deprecated use resp_datatype) + + DataTypeInformation req_datatype = 7; // request datatype information (encoding & type & description) + DataTypeInformation resp_datatype = 8; // response datatype information (encoding & type & description) + + int64 call_count = 4; // call counter } -message Service // service +message Service // service { - int32 rclock = 1; // registration clock - string hname = 2; // host name - string pname = 3; // process name - string uname = 4; // unit name - int32 pid = 5; // process id - string sname = 6; // service name - string sid = 9; // service id - repeated Method methods = 8; // list of methods + int32 rclock = 1; // registration clock + string hname = 2; // host name + string pname = 3; // process name + string uname = 4; // unit name + int32 pid = 5; // process id + string sname = 6; // service name + string sid = 9; // service id + repeated Method methods = 8; // list of methods // transport specific parameter (for internal use) - uint32 version = 10; // service protocol version - uint32 tcp_port_v0 = 7; // the tcp port used for that service - uint32 tcp_port_v1 = 11; // the tcp port used for that service + uint32 version = 10; // service protocol version + uint32 tcp_port_v0 = 7; // the tcp port used for that service (deprecated) + uint32 tcp_port_v1 = 11; // the tcp port used for that service } -message Client // client +message Client // client { - int32 rclock = 1; // registration clock - string hname = 2; // host name - string pname = 3; // process name - string uname = 4; // unit name - int32 pid = 5; // process id - string sname = 6; // service name - string sid = 7; // service id - repeated Method methods = 9; // list of methods + int32 rclock = 1; // registration clock + string hname = 2; // host name + string pname = 3; // process name + string uname = 4; // unit name + int32 pid = 5; // process id + string sname = 6; // service name + string sid = 7; // service id + repeated Method methods = 9; // list of methods // transport specific parameter (for internal use) - uint32 version = 8; // client protocol version + uint32 version = 8; // client protocol version } diff --git a/ecal/core_pb/src/ecal/core/pb/topic.proto b/ecal/core_pb/src/ecal/core/pb/topic.proto index 0da480cf68..155121287e 100644 --- a/ecal/core_pb/src/ecal/core/pb/topic.proto +++ b/ecal/core_pb/src/ecal/core/pb/topic.proto @@ -20,16 +20,10 @@ syntax = "proto3"; import "ecal/core/pb/layer.proto"; +import "ecal/core/pb/datatype.proto"; package eCAL.pb; -message DataTypeInformation -{ - string name = 1; // name of the datatype - string encoding = 2; // encoding of the datatype (e.g. protobuf, flatbuffers, capnproto) - bytes desc = 3; // descriptor information of the datatype (necessary for reflection) -} - message Topic // eCAL topic { // Reserved fields in enums are not supported in protobuf 3.0 diff --git a/ecal/tests/cpp/config_test/src/config_test.cpp b/ecal/tests/cpp/config_test/src/config_test.cpp index 2417811d48..7bada83722 100644 --- a/ecal/tests/cpp/config_test/src/config_test.cpp +++ b/ecal/tests/cpp/config_test/src/config_test.cpp @@ -68,7 +68,7 @@ TEST(core_cpp_config /*unused*/, user_config_passing /*unused*/) custom_config.transport_layer.udp.send_buffer = upd_snd_buff; custom_config.monitoring.filter_excl = mon_filter_excl; - custom_config.logging.sinks.console.filter_log_con = mon_log_filter_con; + custom_config.logging.provider.console.filter_log = mon_log_filter_con; custom_config.publisher.layer.shm.enable = pub_use_shm; @@ -97,7 +97,7 @@ TEST(core_cpp_config /*unused*/, user_config_passing /*unused*/) 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.sinks.console.filter_log_con); + EXPECT_EQ(mon_log_filter_con, eCAL::GetConfiguration().logging.provider.console.filter_log); // Test publisher sendmode assignment EXPECT_EQ(pub_use_shm, eCAL::GetConfiguration().publisher.layer.shm.enable); @@ -123,38 +123,10 @@ TEST(core_cpp_config /*unused*/, user_config_death_test /*unused*/) ASSERT_THROW( SetValue(custom_config.transport_layer.udp.network.group, "256.0.0.0"), std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "127.0.0.1"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "255.255.255.255"), - std::invalid_argument); - + ASSERT_THROW( SetValue(custom_config.transport_layer.udp.network.group, "FFF.FF.FF.FF"), std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "FF.FF.FF.FF"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "Ff.fF.ff.Ff"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "7f.0.0.1"), - std::invalid_argument); - - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "0.0.0.0"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "00.00.00.00"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "000.000.000.000"), - std::invalid_argument); - ASSERT_THROW( - SetValue(custom_config.transport_layer.udp.network.group, "0.00.000.0"), - std::invalid_argument); } TEST(core_cpp_config /*unused*/, config_custom_datatypes_tests /*unused*/) diff --git a/ecal/tests/cpp/logging_test/src/logging_test.cpp b/ecal/tests/cpp/logging_test/src/logging_test.cpp index 86a8e96913..020689f9e9 100644 --- a/ecal/tests/cpp/logging_test/src/logging_test.cpp +++ b/ecal/tests/cpp/logging_test/src/logging_test.cpp @@ -54,31 +54,32 @@ class CoutRedirect { eCAL::Configuration GetUDPConfiguration() { eCAL::Configuration config; - config.logging.sinks.file.enable = false; - config.logging.sinks.console.enable = false; - config.logging.sinks.udp.enable = true; - config.logging.sinks.udp.filter_log_udp = log_level_all; + config.logging.provider.file.enable = false; + config.logging.provider.console.enable = false; + config.logging.provider.udp.enable = true; + config.logging.receiver.enable = true; + config.logging.provider.udp.filter_log = log_level_all; return config; } eCAL::Configuration GetFileConfiguration(const std::string& path_) { eCAL::Configuration config; - config.logging.sinks.udp.enable = false; - config.logging.sinks.console.enable = false; - config.logging.sinks.file.enable = true; - config.logging.sinks.file.path = path_; - config.logging.sinks.file.filter_log_file = log_level_all; + config.logging.provider.udp.enable = false; + config.logging.provider.console.enable = false; + config.logging.provider.file.enable = true; + config.logging.provider.file_config.path = path_; + config.logging.provider.file.filter_log = log_level_all; return config; } eCAL::Configuration GetConsoleConfiguration() { eCAL::Configuration config; - config.logging.sinks.file.enable = false; - config.logging.sinks.udp.enable = false; - config.logging.sinks.console.enable = true; - config.logging.sinks.console.filter_log_con = log_level_all; + config.logging.provider.file.enable = false; + config.logging.provider.udp.enable = false; + config.logging.provider.console.enable = true; + config.logging.provider.console.filter_log = log_level_all; return config; } @@ -224,7 +225,7 @@ TEST(logging_levels /*unused*/, various /*unused*/) const std::string log_message = "Logging level various test for udp."; auto ecal_config = GetUDPConfiguration(); - ecal_config.logging.sinks.udp.filter_log_udp = log_level_warning; + ecal_config.logging.provider.udp.filter_log = log_level_warning; eCAL::Initialize(ecal_config, unit_name, eCAL::Init::Logging); @@ -261,7 +262,7 @@ TEST(logging_levels /*unused*/, none /*unused*/) const std::string log_message = "Logging level none test for udp."; auto ecal_config = GetUDPConfiguration(); - ecal_config.logging.sinks.udp.filter_log_udp = log_level_none; + ecal_config.logging.provider.udp.filter_log = log_level_none; eCAL::Initialize(ecal_config, unit_name, eCAL::Init::Logging); @@ -301,7 +302,7 @@ TEST(logging_disable /*unused*/, file /*unused*/) const std::string log_message = "Disabled logging test for file."; auto ecal_config = GetFileConfiguration(logging_path); - ecal_config.logging.sinks.file.enable = false; + ecal_config.logging.provider.file.enable = false; eCAL::Initialize(ecal_config, unit_name, eCAL::Init::Logging); eCAL::Logging::Log(log_level_info, log_message); @@ -325,11 +326,11 @@ TEST(logging_disable /*unused*/, file /*unused*/) TEST(logging_disable /*unused*/, udp /*unused*/) { - const std::string unit_name = "logging_dsiable_udp_test"; + const std::string unit_name = "logging_disable_udp_test"; const std::string log_message = "Disabled logging test for udp."; auto ecal_config = GetUDPConfiguration(); - ecal_config.logging.sinks.udp.enable = false; + ecal_config.logging.provider.udp.enable = false; eCAL::Initialize(ecal_config, unit_name, eCAL::Init::Logging); eCAL::Logging::Log(log_level_info, log_message); @@ -344,13 +345,57 @@ TEST(logging_disable /*unused*/, udp /*unused*/) eCAL::Finalize(); } +TEST(logging_disable /*unused*/, udp_receive /*unused*/) +{ + const std::string unit_name = "logging_disable_receive_udp_test"; + const std::string log_message = "Disabled receive logging test for udp."; + auto ecal_config = GetUDPConfiguration(); + + ecal_config.logging.receiver.enable = false; + eCAL::Initialize(ecal_config, unit_name.c_str(), eCAL::Init::Logging); + + eCAL::Logging::Log(log_level_info, log_message); + + std::this_thread::sleep_for(UDP_WAIT_TIME); + + eCAL::Logging::SLogging log; + eCAL::Logging::GetLogging(log); + + EXPECT_EQ(log.log_messages.size(), 0); + + eCAL::Finalize(); +} + +TEST(logging_disable /*unused*/, udp_different_receive_port /*unused*/) +{ + const std::string unit_name = "no_logging_different_udp_port"; + const std::string log_message = "No log receiving possible - different udp port."; + auto ecal_config = GetUDPConfiguration(); + + ecal_config.logging.receiver.enable = true; + ecal_config.logging.receiver.udp_config.port = 14009; + + eCAL::Initialize(ecal_config, unit_name.c_str(), eCAL::Init::Logging); + + eCAL::Logging::Log(log_level_info, log_message); + + std::this_thread::sleep_for(UDP_WAIT_TIME); + + eCAL::Logging::SLogging log; + eCAL::Logging::GetLogging(log); + + EXPECT_EQ(log.log_messages.size(), 0); + + eCAL::Finalize(); +} + TEST(logging_disable /*unused*/, console /*unused*/) { const std::string unit_name = "logging_disable_console_test"; const std::string log_message = "Disabled logging test for console."; auto ecal_config = GetConsoleConfiguration(); - ecal_config.logging.sinks.console.enable = false; + ecal_config.logging.provider.console.enable = false; eCAL::Initialize(ecal_config, unit_name, eCAL::Init::Logging); { diff --git a/ecal/tests/cpp/serialization_test/CMakeLists.txt b/ecal/tests/cpp/serialization_test/CMakeLists.txt index 20dc5ee454..26f440c74c 100644 --- a/ecal/tests/cpp/serialization_test/CMakeLists.txt +++ b/ecal/tests/cpp/serialization_test/CMakeLists.txt @@ -32,6 +32,8 @@ set(nanopb_lib_src ) set(nanopb_generated_src + ${ECAL_CORE_PROJECT_ROOT}/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.c + ${ECAL_CORE_PROJECT_ROOT}/core/src/serialization/nanopb/ecal/core/pb/datatype.npb.h ${ECAL_CORE_PROJECT_ROOT}/core/src/serialization/nanopb/ecal/core/pb/ecal.npb.c ${ECAL_CORE_PROJECT_ROOT}/core/src/serialization/nanopb/ecal/core/pb/ecal.npb.h ${ECAL_CORE_PROJECT_ROOT}/core/src/serialization/nanopb/ecal/core/pb/host.npb.c diff --git a/ecal/tests/cpp/serialization_test/src/logging_compare.h b/ecal/tests/cpp/serialization_test/src/logging_compare.h index 1e5c9dfa73..aaa154860d 100644 --- a/ecal/tests/cpp/serialization_test/src/logging_compare.h +++ b/ecal/tests/cpp/serialization_test/src/logging_compare.h @@ -18,6 +18,7 @@ */ #pragma once + #include namespace eCAL diff --git a/ecal/tests/cpp/serialization_test/src/logging_generate.h b/ecal/tests/cpp/serialization_test/src/logging_generate.h index daab8f208c..9f493e7136 100644 --- a/ecal/tests/cpp/serialization_test/src/logging_generate.h +++ b/ecal/tests/cpp/serialization_test/src/logging_generate.h @@ -18,6 +18,7 @@ */ #pragma once + #include namespace eCAL diff --git a/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp b/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp index a0f3a0c846..c744f447a1 100644 --- a/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp +++ b/ecal/tests/cpp/serialization_test/src/monitoring_compare.cpp @@ -74,9 +74,7 @@ namespace eCAL monitoring1.publisher[i].tid != monitoring2.publisher[i].tid || monitoring1.publisher[i].tname != monitoring2.publisher[i].tname || monitoring1.publisher[i].direction != monitoring2.publisher[i].direction || - monitoring1.publisher[i].tdatatype.name != monitoring2.publisher[i].tdatatype.name || - monitoring1.publisher[i].tdatatype.encoding != monitoring2.publisher[i].tdatatype.encoding || - monitoring1.publisher[i].tdatatype.descriptor != monitoring2.publisher[i].tdatatype.descriptor || + monitoring1.publisher[i].tdatatype != monitoring2.publisher[i].tdatatype || monitoring1.publisher[i].tlayer.size() != monitoring2.publisher[i].tlayer.size() || monitoring1.publisher[i].tsize != monitoring2.publisher[i].tsize || monitoring1.publisher[i].connections_loc != monitoring2.publisher[i].connections_loc || @@ -108,9 +106,7 @@ namespace eCAL monitoring1.subscriber[i].tid != monitoring2.subscriber[i].tid || monitoring1.subscriber[i].tname != monitoring2.subscriber[i].tname || monitoring1.subscriber[i].direction != monitoring2.subscriber[i].direction || - monitoring1.subscriber[i].tdatatype.name != monitoring2.subscriber[i].tdatatype.name || - monitoring1.subscriber[i].tdatatype.encoding != monitoring2.subscriber[i].tdatatype.encoding || - monitoring1.subscriber[i].tdatatype.descriptor != monitoring2.subscriber[i].tdatatype.descriptor || + monitoring1.subscriber[i].tdatatype != monitoring2.subscriber[i].tdatatype || monitoring1.subscriber[i].tlayer.size() != monitoring2.subscriber[i].tlayer.size() || monitoring1.subscriber[i].tsize != monitoring2.subscriber[i].tsize || monitoring1.subscriber[i].connections_loc != monitoring2.subscriber[i].connections_loc || @@ -155,6 +151,8 @@ namespace eCAL monitoring1.server[i].methods[j].req_desc != monitoring2.server[i].methods[j].req_desc || monitoring1.server[i].methods[j].resp_type != monitoring2.server[i].methods[j].resp_type || monitoring1.server[i].methods[j].resp_desc != monitoring2.server[i].methods[j].resp_desc || + monitoring1.server[i].methods[j].req_datatype != monitoring2.server[i].methods[j].req_datatype || + monitoring1.server[i].methods[j].resp_datatype != monitoring2.server[i].methods[j].resp_datatype || monitoring1.server[i].methods[j].call_count != monitoring2.server[i].methods[j].call_count) { return false; @@ -190,6 +188,8 @@ namespace eCAL monitoring1.clients[i].methods[j].req_desc != monitoring2.clients[i].methods[j].req_desc || monitoring1.clients[i].methods[j].resp_type != monitoring2.clients[i].methods[j].resp_type || monitoring1.clients[i].methods[j].resp_desc != monitoring2.clients[i].methods[j].resp_desc || + monitoring1.clients[i].methods[j].req_datatype != monitoring2.clients[i].methods[j].req_datatype || + monitoring1.clients[i].methods[j].resp_datatype != monitoring2.clients[i].methods[j].resp_datatype || monitoring1.clients[i].methods[j].call_count != monitoring2.clients[i].methods[j].call_count) { return false; diff --git a/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp b/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp index 34970abac0..0d50929924 100644 --- a/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp +++ b/ecal/tests/cpp/serialization_test/src/monitoring_generate.cpp @@ -18,6 +18,7 @@ */ #include "monitoring_generate.h" +#include "registration_generate.h" #include "common_generate.h" #include @@ -52,28 +53,26 @@ namespace eCAL // generate topic STopicMon GenerateTopic(const std::string& direction) { - STopicMon publisher; - publisher.rclock = rand() % 1000; - publisher.hname = GenerateString(10); - publisher.hgname = GenerateString(8); - publisher.pid = rand() % 1000; - publisher.pname = GenerateString(8); - publisher.uname = GenerateString(6); - publisher.tid = GenerateString(8); - publisher.tname = GenerateString(10); - publisher.direction = direction; - publisher.tdatatype.name = GenerateString(8); - publisher.tdatatype.encoding = GenerateString(8); - publisher.tdatatype.descriptor = GenerateString(10); - publisher.tlayer.push_back({ tl_ecal_shm, 1, true }); - publisher.tsize = rand() % 5000; - publisher.connections_loc = rand() % 10; - publisher.connections_ext = rand() % 10; - publisher.message_drops = rand() % 100; - publisher.did = rand() % 10000; - publisher.dclock = rand() % 10000; - publisher.dfreq = rand() % 100; - return publisher; + STopicMon topic; + topic.rclock = rand() % 1000; + topic.hname = GenerateString(10); + topic.hgname = GenerateString(8); + topic.pid = rand() % 1000; + topic.pname = GenerateString(8); + topic.uname = GenerateString(6); + topic.tid = GenerateString(8); + topic.tname = GenerateString(10); + topic.direction = direction; + topic.tdatatype = eCAL::Registration::GenerateDataTypeInformation(); + topic.tlayer.push_back({ tl_ecal_shm, 1, true }); + topic.tsize = rand() % 5000; + topic.connections_loc = rand() % 10; + topic.connections_ext = rand() % 10; + topic.message_drops = rand() % 100; + topic.did = rand() % 10000; + topic.dclock = rand() % 10000; + topic.dfreq = rand() % 100; + return topic; } // generate servicemethod @@ -81,10 +80,15 @@ namespace eCAL { SMethodMon method; method.mname = GenerateString(8); - method.req_type = GenerateString(8); - method.req_desc = GenerateString(10); - method.resp_type = GenerateString(8); - method.resp_desc = GenerateString(10); + + method.req_type = GenerateString(8); // deprecated + method.req_desc = GenerateString(10); // deprecated + method.resp_type = GenerateString(8); // deprecated + method.resp_desc = GenerateString(10); // deprecated + + method.req_datatype = eCAL::Registration::GenerateDataTypeInformation(); + method.resp_datatype = eCAL::Registration::GenerateDataTypeInformation(); + method.call_count = rand() % 10000; return method; } diff --git a/ecal/tests/cpp/serialization_test/src/payload_compare.h b/ecal/tests/cpp/serialization_test/src/payload_compare.h index a0c86a9f22..110967a098 100644 --- a/ecal/tests/cpp/serialization_test/src/payload_compare.h +++ b/ecal/tests/cpp/serialization_test/src/payload_compare.h @@ -17,6 +17,8 @@ * ========================= eCAL LICENSE ================================= */ +#pragma once + #include namespace eCAL diff --git a/ecal/tests/cpp/serialization_test/src/payload_generate.h b/ecal/tests/cpp/serialization_test/src/payload_generate.h index ce8286afe8..ba5248582f 100644 --- a/ecal/tests/cpp/serialization_test/src/payload_generate.h +++ b/ecal/tests/cpp/serialization_test/src/payload_generate.h @@ -17,6 +17,8 @@ * ========================= eCAL LICENSE ================================= */ +#pragma once + #include #include diff --git a/ecal/tests/cpp/serialization_test/src/registration_generate.cpp b/ecal/tests/cpp/serialization_test/src/registration_generate.cpp index 79a90c545e..9b7f5272fe 100644 --- a/ecal/tests/cpp/serialization_test/src/registration_generate.cpp +++ b/ecal/tests/cpp/serialization_test/src/registration_generate.cpp @@ -31,12 +31,17 @@ namespace eCAL Service::Method GenerateMethod() { Service::Method method; - method.mname = GenerateString(6); - method.req_type = GenerateString(8); - method.req_desc = GenerateString(10); - method.resp_type = GenerateString(8); - method.resp_desc = GenerateString(10); - method.call_count = rand() % 100; + method.mname = GenerateString(8); + + method.req_type = GenerateString(8); // deprecated + method.req_desc = GenerateString(10); // deprecated + method.resp_type = GenerateString(8); // deprecated + method.resp_desc = GenerateString(10); // deprecated + + method.req_datatype = GenerateDataTypeInformation(); + method.resp_datatype = GenerateDataTypeInformation(); + + method.call_count = rand() % 10000; return method; } diff --git a/ecal/tests/cpp/serialization_test/src/registration_generate.h b/ecal/tests/cpp/serialization_test/src/registration_generate.h index 64d1a765cf..df1df075f3 100644 --- a/ecal/tests/cpp/serialization_test/src/registration_generate.h +++ b/ecal/tests/cpp/serialization_test/src/registration_generate.h @@ -16,15 +16,19 @@ * * ========================= eCAL LICENSE ================================= */ + +#pragma once + #include "serialization/ecal_struct_sample_registration.h" namespace eCAL { namespace Registration { + SDataTypeInformation GenerateDataTypeInformation(); Sample GenerateProcessSample(); Sample GenerateTopicSample(); Sample GenerateServiceSample(); - Sample GenerateClientSample(); + Sample GenerateClientSample(); } } \ No newline at end of file diff --git a/ecal/tests/cpp/serialization_test/src/service_compare.h b/ecal/tests/cpp/serialization_test/src/service_compare.h index 46d9234e2e..3fc64e6a5d 100644 --- a/ecal/tests/cpp/serialization_test/src/service_compare.h +++ b/ecal/tests/cpp/serialization_test/src/service_compare.h @@ -16,6 +16,7 @@ * * ========================= eCAL LICENSE ================================= */ + #pragma once #include