// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include #include #include #include #include "../include/application_impl.hpp" #ifdef ANDROID # include "../../../configuration/include/internal_android.hpp" #else # include "../../../configuration/include/internal.hpp" #endif #include "../../message/include/message_impl.hpp" #include "../../message/include/payload_impl.hpp" namespace vsomeip { application_impl::application_impl(const std::string &_name) { impl_ = vsomeip_v3::runtime::get()->create_application(_name); } application_impl::~application_impl() { vsomeip::runtime::get()->remove_application(impl_->get_name()); } const std::string & application_impl::get_name() const { return impl_->get_name(); } client_t application_impl::get_client() const { return impl_->get_client(); } void application_impl::set_configuration(const std::shared_ptr _configuration) { (void)_configuration; // Not implemented } bool application_impl::init() { return impl_->init(); } void application_impl::start() { impl_->start(); } void application_impl::stop() { impl_->stop(); } void application_impl::offer_service(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { impl_->offer_service(_service, _instance, _major, _minor); } void application_impl::stop_offer_service(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { impl_->stop_offer_service(_service, _instance, _major, _minor); } void application_impl::offer_event(service_t _service, instance_t _instance, event_t _event, const std::set &_eventgroups, bool _is_field) { // Set event type vsomeip_v3::event_type_e its_type(vsomeip_v3::event_type_e::ET_EVENT); if (_is_field) its_type = vsomeip_v3::event_type_e::ET_FIELD; else { // Find out whether the event is selective. Requires a preceding // call to "register_subscription_handler". // Note: The check can be done on the eventgroup(s) as selective // events own an exclusive eventgroup. const bool is_selective = is_selective_event(_service, _instance, _eventgroups); if (is_selective) its_type = vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT; } impl_->offer_event(_service, _instance, _event, _eventgroups, its_type); } void application_impl::stop_offer_event(service_t _service, instance_t _instance, event_t _event) { impl_->stop_offer_event(_service, _instance, _event); } void application_impl::request_service(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, bool _use_exclusive_proxy) { (void)_use_exclusive_proxy; impl_->request_service(_service, _instance, _major, _minor); } void application_impl::release_service(service_t _service, instance_t _instance) { impl_->release_service(_service, _instance); } void application_impl::request_event(service_t _service, instance_t _instance, event_t _event, const std::set &_eventgroups, bool _is_field) { const vsomeip_v3::event_type_e its_type = (_is_field) ? vsomeip_v3::event_type_e::ET_FIELD : vsomeip_v3::event_type_e::ET_EVENT; impl_->request_event(_service, _instance, _event, _eventgroups, its_type); } void application_impl::release_event(service_t _service, instance_t _instance, event_t _event) { impl_->release_event(_service, _instance, _event); } void application_impl::subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, subscription_type_e _subscription_type, event_t _event) { (void)_subscription_type; // unused in v3 impl_->subscribe(_service, _instance, _eventgroup, _major, _event); } void application_impl::unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup) { impl_->unsubscribe(_service, _instance, _eventgroup); } bool application_impl::is_available(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) const { return impl_->is_available(_service, _instance, _major, _minor); } void application_impl::send(std::shared_ptr _message, bool _flush = true) { (void)_flush; // unused in v3 if (_message) { auto its_message = std::dynamic_pointer_cast(_message); impl_->send(its_message->get_impl()); } } void application_impl::notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload) const { if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify(_service, _instance, _event, its_payload->get_impl()); } else { impl_->notify(_service, _instance, _event, nullptr); } } void application_impl::notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, client_t _client) const { if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify_one(_service, _instance, _event, its_payload->get_impl(), _client); } else { impl_->notify_one(_service, _instance, _event, nullptr, _client); } } void application_impl::register_state_handler(state_handler_t _handler) { impl_->register_state_handler( [_handler](vsomeip_v3::state_type_e _state) { _handler(static_cast(_state)); } ); } void application_impl::unregister_state_handler() { impl_->unregister_state_handler(); } void application_impl::register_message_handler( service_t _service, instance_t _instance, method_t _method, message_handler_t _handler) { impl_->register_message_handler(_service, _instance, _method, [_handler](const std::shared_ptr &_message) { auto its_message = std::make_shared(_message); _handler(its_message); } ); } void application_impl::unregister_message_handler( service_t _service, instance_t _instance, method_t _method) { impl_->unregister_message_handler(_service, _instance, _method); } void application_impl::register_availability_handler( service_t _service, instance_t _instance, availability_handler_t _handler, major_version_t _major, minor_version_t _minor) { impl_->register_availability_handler(_service, _instance, _handler, _major, _minor); } void application_impl::unregister_availability_handler( service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) { impl_->unregister_availability_handler(_service, _instance, _major, _minor); } void application_impl::register_subscription_handler( service_t _service, instance_t _instance, eventgroup_t _eventgroup, subscription_handler_t _handler) { { std::lock_guard its_lock(eventgroups_mutex_); eventgroups_[_service][_instance].insert(_eventgroup); } impl_->register_subscription_handler(_service, _instance, _eventgroup, [_handler](client_t _client, vsomeip::uid_t _uid, vsomeip::gid_t _gid, bool _accepted){ (void)_uid; (void)_gid; return _handler(_client, _accepted); } ); } void application_impl::unregister_subscription_handler( service_t _service, instance_t _instance, eventgroup_t _eventgroup) { impl_->unregister_subscription_handler(_service, _instance, _eventgroup); } // subscription_error_handlers were exclusively used for selective events. // As selective events use an exclusive eventgroup, the event identifier // itself is not needed and we can use a dummy. #define ERROR_HANDLER_DUMMY_EVENT 0xFFFE void application_impl::register_subscription_error_handler( service_t _service, instance_t _instance, eventgroup_t _eventgroup, error_handler_t _handler) { impl_->register_subscription_status_handler( _service, _instance, _eventgroup, ERROR_HANDLER_DUMMY_EVENT, [_handler](service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, uint16_t _error) { (void)_service; (void)_instance; (void)_eventgroup; (void)_event; _handler(_error); }, true ); } void application_impl::unregister_subscription_error_handler( service_t _service, instance_t _instance, eventgroup_t _eventgroup) { impl_->unregister_subscription_status_handler(_service, _instance, _eventgroup, ERROR_HANDLER_DUMMY_EVENT); } void application_impl::clear_all_handler() { impl_->clear_all_handler(); } bool application_impl::is_routing() const { return impl_->is_routing(); } void application_impl::offer_event( service_t _service, instance_t _instance, event_t _event, const std::set &_eventgroups, bool _is_field, std::chrono::milliseconds _cycle, bool _change_resets_cycle, const epsilon_change_func_t &_epsilon_change_func) { // Set event type vsomeip_v3::event_type_e its_type(vsomeip_v3::event_type_e::ET_EVENT); if (_is_field) its_type = vsomeip_v3::event_type_e::ET_FIELD; else { // Find out whether the event is selective. Requires a preceding // call to "register_subscription_handler". // Note: The check can be done on the eventgroup(s) as selective // events own an exclusive eventgroup. const bool is_selective = is_selective_event(_service, _instance, _eventgroups); if (is_selective) its_type = vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT; } impl_->offer_event(_service, _instance, _event, _eventgroups, its_type, _cycle, _change_resets_cycle, true, [_epsilon_change_func]( const std::shared_ptr &_lhs, const std::shared_ptr &_rhs) { auto its_lhs = std::make_shared(_lhs); auto its_rhs = std::make_shared(_rhs); return _epsilon_change_func(its_lhs, its_rhs); } ); } void application_impl::notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, bool _force) const { if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify(_service, _instance, _event, its_payload->get_impl(), _force); } else { impl_->notify(_service, _instance, _event, nullptr, _force); } } void application_impl::notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, client_t _client, bool _force) const { if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify_one(_service, _instance, _event, its_payload->get_impl(), _client, _force); } else { impl_->notify_one(_service, _instance, _event, nullptr, _client, _force); } } bool application_impl::are_available(available_t &_available, service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor) const { return impl_->are_available(_available, _service, _instance, _major, _minor); } void application_impl::notify(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, bool _force, bool _flush) const { (void)_flush; // unused in v3 if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify(_service, _instance, _event, its_payload->get_impl(), _force); } else { impl_->notify(_service, _instance, _event, nullptr, _force); } } void application_impl::notify_one(service_t _service, instance_t _instance, event_t _event, std::shared_ptr _payload, client_t _client, bool _force, bool _flush) const { (void)_flush; // unused in v3 if (_payload) { auto its_payload = std::dynamic_pointer_cast(_payload); impl_->notify_one(_service, _instance, _event, its_payload->get_impl(), _client, _force); } else { impl_->notify_one(_service, _instance, _event, nullptr, _client, _force); } } void application_impl::set_routing_state(routing_state_e _routing_state) { impl_->set_routing_state( static_cast(_routing_state)); } void application_impl::unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) { impl_->unsubscribe(_service, _instance, _eventgroup, _event); } void application_impl::register_subscription_status_handler(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, subscription_status_handler_t _handler) { register_subscription_status_handler(_service, _instance, _eventgroup, _event, _handler, false); } void application_impl::register_subscription_status_handler(service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event, subscription_status_handler_t _handler, bool _is_selective) { if (_is_selective) { std::set its_eventgroups; its_eventgroups.insert(_eventgroup); // An application may call "register_event" before // "register_subscription_status_handler". While the call to // "register_subscription_status_handler" contains the information // whether an event is selective, the call to "register_event" does // not. Therefore, we re-register the event with correct event type // here. impl_->request_event(_service, _instance, _event, its_eventgroups, vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT); } impl_->register_subscription_status_handler(_service, _instance, _eventgroup, _event, [_handler](const vsomeip_v3::service_t _service, const vsomeip_v3::instance_t _instance, const vsomeip_v3::eventgroup_t _eventgroup, const vsomeip_v3::event_t _event, const uint16_t _error) { if (_handler) _handler(_service, _instance, _eventgroup, _event, _error); }, _is_selective); } void application_impl::get_offered_services_async( offer_type_e _offer_type, offered_services_handler_t _handler) { impl_->get_offered_services_async( static_cast(_offer_type), _handler); } void application_impl::set_watchdog_handler( watchdog_handler_t _handler, std::chrono::seconds _interval) { impl_->set_watchdog_handler(_handler, _interval); } void application_impl::register_async_subscription_handler( service_t _service, instance_t _instance, eventgroup_t _eventgroup, async_subscription_handler_t _handler) { { std::lock_guard its_lock(eventgroups_mutex_); eventgroups_[_service][_instance].insert(_eventgroup); } impl_->register_async_subscription_handler(_service, _instance, _eventgroup, [_handler](client_t _client, vsomeip::uid_t _uid, vsomeip::gid_t _gid, bool _accepted, std::function _handler2) { (void)_uid; (void)_gid; _handler(_client, _accepted, _handler2); }); } //////////////////////////////////////////////////////////////////////////////// // The following methods are not implemented as they should only be used by // plugin implementations that are not intended to run in compatibility mode //////////////////////////////////////////////////////////////////////////////// void application_impl::set_offer_acceptance_required( ip_address_t _address, const std::string _path, bool _enable) { (void)_address; (void)_path; (void)_enable; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } vsomeip::application::offer_acceptance_map_type_t application_impl::get_offer_acceptance_required() { VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; return vsomeip::application::offer_acceptance_map_type_t(); } void application_impl::register_offer_acceptance_handler( offer_acceptance_handler_t _handler) { (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } void application_impl::register_reboot_notification_handler( reboot_notification_handler_t _handler) { (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } void application_impl::register_routing_ready_handler( routing_ready_handler_t _handler) { (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } void application_impl::register_routing_state_handler( routing_state_handler_t _handler) { (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } bool application_impl::update_service_configuration( service_t _service, instance_t _instance, std::uint16_t _port, bool _reliable, bool _magic_cookies_enabled, bool _offer) { (void)_service; (void)_instance; (void)_port; (void)_reliable; (void)_magic_cookies_enabled; (void)_offer; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; return false; } void application_impl::update_security_policy_configuration( uint32_t _uid, uint32_t _gid, std::shared_ptr _policy, std::shared_ptr _payload, security_update_handler_t _handler) { (void)_uid; (void)_gid; (void)_policy; (void)_payload; (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } void application_impl::remove_security_policy_configuration( uint32_t _uid, uint32_t _gid, security_update_handler_t _handler) { (void)_uid; (void)_gid; (void)_handler; VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer."; } //////////////////////////////////////////////////////////////////////////////// // Private helper //////////////////////////////////////////////////////////////////////////////// bool application_impl::is_selective_event( vsomeip::service_t _service, vsomeip::instance_t _instance, const std::set &_eventgroups) { bool is_selective(false); std::lock_guard its_events_lock(eventgroups_mutex_); const auto its_service = eventgroups_.find(_service); if (its_service != eventgroups_.end()) { const auto its_instance = its_service->second.find(_instance); if (its_instance != its_service->second.end()) { for (const auto& eg : _eventgroups) { const auto its_egrp = its_instance->second.find(eg); if (its_egrp != its_instance->second.end()) { is_selective = true; break; } } } } return is_selective; } } // namespace vsomeip