diff options
author | Lutz Bichler <Lutz.Bichler@bmw.de> | 2014-08-05 14:16:27 +0200 |
---|---|---|
committer | Lutz Bichler <Lutz.Bichler@bmw.de> | 2014-08-05 14:16:27 +0200 |
commit | e339029b33ad8415469794691d70016cac6701b0 (patch) | |
tree | b12d6c67c58865e19bf7887c4ffafbeb3ba471af | |
parent | d3644b3edc8b15ace244724bc50e4fbfbf9601ec (diff) | |
download | vSomeIP-e339029b33ad8415469794691d70016cac6701b0.tar.gz |
Implemented get/set of fields. Only currently this works for remote
events/fields.
TODO: enable the mechanism for local events/fields. The simple approach
(sending locally) would require serialization/deserialization which I'd
like to avoid...
31 files changed, 2772 insertions, 2379 deletions
diff --git a/config/vsomeip-udp-service.json b/config/vsomeip-udp-service.json index 7f19ad3..c07302c 100644 --- a/config/vsomeip-udp-service.json +++ b/config/vsomeip-udp-service.json @@ -51,7 +51,7 @@ }, { "event" : "0x0778", - "is_field" : "false", + "is_field" : "true", "update-cycle" : 0 }, { diff --git a/documentation/readme.txt b/documentation/readme.txt index 4d1376a..5419b69 100644 --- a/documentation/readme.txt +++ b/documentation/readme.txt @@ -1,3 +1,7 @@ To use IP multicast, the route must be added. In Linux this can be done -by "route add -net 224.0.0.0/4 dev eth0". +by: + +# route add -net 224.0.0.0/4 dev eth0 + +Other OSes may have slightly different ways to do this. diff --git a/documentation/todo.txt b/documentation/todo.txt new file mode 100644 index 0000000..0e250bd --- /dev/null +++ b/documentation/todo.txt @@ -0,0 +1,7 @@ +TODO: + +- handle endpoints for multicasts correctly. Especially, delete them if they are no longer needed. + This should probably be done as part of the redesign of the endpoints. + + +
\ No newline at end of file diff --git a/examples/notify-sample.cpp b/examples/notify-sample.cpp index 7661e89..1b46453 100644 --- a/examples/notify-sample.cpp +++ b/examples/notify-sample.cpp @@ -16,153 +16,152 @@ #include "sample-ids.hpp" class service_sample { - public: - service_sample(bool _use_tcp, uint32_t _cycle) - : app_(vsomeip::runtime::get()->create_application()), - is_registered_(false), - use_tcp_(_use_tcp), - cycle_(_cycle), - offer_thread_(std::bind(&service_sample::run, this)), - notify_thread_(std::bind(&service_sample::notify, this)), - is_offered_(false) { - } - - void init() { - std::lock_guard < std::mutex > its_lock(mutex_); - - app_->init(); - app_->register_event_handler( - std::bind(&service_sample::on_event, this, std::placeholders::_1)); - - blocked_ = true; - condition_.notify_one(); - } - - void start() { - app_->start(); - } - - void offer() { - std::lock_guard < std::mutex > its_lock(notify_mutex_); - app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); - is_offered_ = true; - notify_condition_.notify_one(); - } - - void stop_offer() { - app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); - is_offered_ = false; - } - - void on_event(vsomeip::event_type_e _event) { - VSOMEIP_INFO << "Application " << app_->get_name() << " is " - << (_event == vsomeip::event_type_e::REGISTERED ? - "registered." : "deregistered."); - - if (_event == vsomeip::event_type_e::REGISTERED) { - if (!is_registered_) { - is_registered_ = true; - } - } else { - is_registered_ = false; - } - } - - void run() { - std::unique_lock < std::mutex > its_lock(mutex_); - while (!blocked_) - condition_.wait(its_lock); - - bool is_offer(true); - while (true) { - if (is_offer) - offer(); - else - stop_offer(); - std::this_thread::sleep_for(std::chrono::milliseconds(10000)); - is_offer = !is_offer; - } - } - - void notify() { - std::shared_ptr<vsomeip::payload> its_payload - = vsomeip::runtime::get()->create_payload(); - - vsomeip::byte_t its_data[256]; - uint32_t its_size = 1; - - while (true) { - VSOMEIP_INFO << "notify: started..."; - std::unique_lock < std::mutex > its_lock(notify_mutex_); - while (!is_offered_) - notify_condition_.wait(its_lock); - - VSOMEIP_INFO << "notify: unblocked ..."; - while (is_offered_) { - if (its_size == sizeof(its_data)) - its_size = 1; - - for (uint32_t i = 0; i < its_size; ++i) - its_data[i] = (i % 256); - - its_payload->set_data(its_data, its_size); - - VSOMEIP_INFO << "Setting event (Length=" << std::dec << its_size << ")."; - app_->set(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_payload); - - its_size++; - - std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); - } - } - } +public: + service_sample(bool _use_tcp, uint32_t _cycle) : + app_(vsomeip::runtime::get()->create_application()), is_registered_( + false), use_tcp_(_use_tcp), cycle_(_cycle), offer_thread_( + std::bind(&service_sample::run, this)), notify_thread_( + std::bind(&service_sample::notify, this)), is_offered_( + false) { + } + + void init() { + std::lock_guard<std::mutex> its_lock(mutex_); + + app_->init(); + app_->register_event_handler( + std::bind(&service_sample::on_event, this, + std::placeholders::_1)); + + blocked_ = true; + condition_.notify_one(); + } + + void start() { + app_->start(); + } + + void offer() { + std::lock_guard<std::mutex> its_lock(notify_mutex_); + app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); + is_offered_ = true; + notify_condition_.notify_one(); + } + + void stop_offer() { + app_->stop_offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID); + is_offered_ = false; + } + + void on_event(vsomeip::event_type_e _event) { + VSOMEIP_INFO<< "Application " << app_->get_name() << " is " + << (_event == vsomeip::event_type_e::REGISTERED ? + "registered." : "deregistered."); + + if (_event == vsomeip::event_type_e::REGISTERED) { + if (!is_registered_) { + is_registered_ = true; + } + } else { + is_registered_ = false; + } + } + + void run() { + std::unique_lock < std::mutex > its_lock(mutex_); + while (!blocked_) + condition_.wait(its_lock); + + bool is_offer(true); + while (true) { + if (is_offer) + offer(); + else + stop_offer(); + std::this_thread::sleep_for(std::chrono::milliseconds(10000)); + is_offer = !is_offer; + } + } + + void notify() { + std::shared_ptr<vsomeip::payload> its_payload + = vsomeip::runtime::get()->create_payload(); + + vsomeip::byte_t its_data[10]; + uint32_t its_size = 1; + + while (true) { + VSOMEIP_INFO << "notify: started..."; + std::unique_lock < std::mutex > its_lock(notify_mutex_); + while (!is_offered_) + notify_condition_.wait(its_lock); + + VSOMEIP_INFO << "notify: unblocked ..."; + while (is_offered_) { + if (its_size == sizeof(its_data)) + its_size = 1; + + for (uint32_t i = 0; i < its_size; ++i) + its_data[i] = static_cast<uint8_t>(i); + + its_payload->set_data(its_data, its_size); + + VSOMEIP_INFO << "Setting event (Length=" << std::dec << its_size << ")."; + app_->set(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_payload); + + its_size++; + + std::this_thread::sleep_for(std::chrono::milliseconds(cycle_)); + } + } + } private: - std::shared_ptr<vsomeip::application> app_; - bool is_registered_; - bool use_tcp_; - uint32_t cycle_; - - std::thread offer_thread_; - std::mutex mutex_; - std::condition_variable condition_; - bool blocked_; - - std::thread notify_thread_; - std::mutex notify_mutex_; - std::condition_variable notify_condition_; - bool is_offered_; + std::shared_ptr<vsomeip::application> app_; + bool is_registered_; + bool use_tcp_; + uint32_t cycle_; + + std::thread offer_thread_; + std::mutex mutex_; + std::condition_variable condition_; + bool blocked_; + + std::thread notify_thread_; + std::mutex notify_mutex_; + std::condition_variable notify_condition_; + bool is_offered_; }; int main(int argc, char **argv) { - bool use_tcp = false; - uint32_t cycle = 1000; // default 1s - - std::string tcp_enable("--tcp"); - std::string udp_enable("--udp"); - std::string cycle_arg("--cycle"); - - for (int i = 1; i < argc; i++) { - if (tcp_enable == argv[i]) { - use_tcp = true; - break; - } - if (udp_enable == argv[i]) { - use_tcp = false; - break; - } - - if (cycle_arg == argv[i] && i+1 < argc) { - i++; - std::stringstream converter; - converter << argv[i]; - converter >> cycle; - } - } - - service_sample its_sample(use_tcp, cycle); - its_sample.init(); - its_sample.start(); - - return 0; + bool use_tcp = false; + uint32_t cycle = 1000; // default 1s + + std::string tcp_enable("--tcp"); + std::string udp_enable("--udp"); + std::string cycle_arg("--cycle"); + + for (int i = 1; i < argc; i++) { + if (tcp_enable == argv[i]) { + use_tcp = true; + break; + } + if (udp_enable == argv[i]) { + use_tcp = false; + break; + } + + if (cycle_arg == argv[i] && i + 1 < argc) { + i++; + std::stringstream converter; + converter << argv[i]; + converter >> cycle; + } + } + + service_sample its_sample(use_tcp, cycle); + its_sample.init(); + its_sample.start(); + + return 0; } diff --git a/examples/readme.txt b/examples/readme.txt index 6385c08..834485e 100644 --- a/examples/readme.txt +++ b/examples/readme.txt @@ -1,5 +1,12 @@ -To start the examples from the build-directory do: +To use the example applications you need two devices on the same network. The network addresses within +the configuration files need to be adapted to match the devices addresses. -env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=client-sample ./client-sample -env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=service-sample ./service-sample -env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=other-client-sample ./client-sample +To start the request/response-example from the build-directory do: + +HOST1: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=client-sample ./request-sample +HOST2: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=service-sample ./response-sample + +To start the subscribe/notify-example from the build-directory do: + +HOST1: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=client-sample ./subscribe-sample +HOST2: env VSOMEIP_CONFIGURATION_FILE=../config/vsomeip.xml VSOMEIP_APPLICATION_NAME=service-sample ./notify-sample diff --git a/examples/subscribe-sample.cpp b/examples/subscribe-sample.cpp index bb1beaf..2c6312b 100644 --- a/examples/subscribe-sample.cpp +++ b/examples/subscribe-sample.cpp @@ -16,77 +16,92 @@ #include "sample-ids.hpp" class client_sample { - public: - client_sample(bool _use_tcp) - : app_(vsomeip::runtime::get()->create_application()), - use_tcp_(_use_tcp) { - } - - void init() { - app_->init(); - - VSOMEIP_INFO<< "Client settings [protocol=" - << (use_tcp_ ? "TCP" : "UDP") - << "]"; - - app_->register_message_handler( - vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD, - std::bind(&client_sample::on_message, this, std::placeholders::_1)); - - app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, - SAMPLE_EVENTGROUP_ID); - } - - void start() { - app_->start(); - } - - void on_message(std::shared_ptr<vsomeip::message> &_response) { - std::stringstream its_message; - its_message << "Received a notification from Service [" << std::setw(4) - << std::setfill('0') << std::hex << _response->get_service() - << "." << std::setw(4) << std::setfill('0') << std::hex - << _response->get_instance() << "] to Client/Session [" - << std::setw(4) << std::setfill('0') << std::hex - << _response->get_client() << "/" << std::setw(4) - << std::setfill('0') << std::hex << _response->get_session() - << "] = "; - std::shared_ptr<vsomeip::payload> its_payload = _response->get_payload(); - its_message << "(" << std::dec << its_payload->get_length() << ")"; -#if 0 - for (uint32_t i = 0; i < its_payload->get_length(); ++i) - its_message << std::hex << std::setw(2) << std::setfill('0') - << (int) its_payload->get_data()[i] << " "; -#endif - VSOMEIP_INFO << its_message.str(); - } +public: + client_sample(bool _use_tcp) : + app_(vsomeip::runtime::get()->create_application()), use_tcp_( + _use_tcp) { + } + + void init() { + app_->init(); + + VSOMEIP_INFO<< "Client settings [protocol=" + << (use_tcp_ ? "TCP" : "UDP") + << "]"; + + app_->register_message_handler(vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, + vsomeip::ANY_METHOD, + std::bind(&client_sample::on_message, this, + std::placeholders::_1)); + + app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, + SAMPLE_EVENTGROUP_ID); + } + + void start() { + app_->start(); + } + + void on_message(std::shared_ptr<vsomeip::message> &_response) { + std::stringstream its_message; + its_message << "Received a notification for Event [" << std::setw(4) + << std::setfill('0') << std::hex << _response->get_service() + << "." << _response->get_instance() << "." + << _response->get_method() << "] to Client/Session [" + << std::setw(4) << std::setfill('0') << std::hex + << _response->get_client() << "/" << std::setw(4) + << std::setfill('0') << std::hex << _response->get_session() + << "] = "; + std::shared_ptr<vsomeip::payload> its_payload = + _response->get_payload(); + its_message << "(" << std::dec << its_payload->get_length() << ") "; + for (uint32_t i = 0; i < its_payload->get_length(); ++i) + its_message << std::hex << std::setw(2) << std::setfill('0') + << (int) its_payload->get_data()[i] << " "; + VSOMEIP_INFO << its_message.str(); + + if (_response->get_client() == 0) { + if ((its_payload->get_length() % 5) == 0) + app_->get(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID); + + if ((its_payload->get_length() % 8) == 0) { + const vsomeip::byte_t its_data[] + = { 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x50, 0x51, 0x52 }; + std::shared_ptr<vsomeip::payload> its_new_payload + = vsomeip::runtime::get()->create_payload(); + its_new_payload->set_data(its_data, sizeof(its_data)); + app_->set(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_new_payload); + } + } + } private: - std::shared_ptr< vsomeip::application > app_; - bool use_tcp_; - bool be_quiet_; + std::shared_ptr< vsomeip::application > app_; + bool use_tcp_; + bool be_quiet_; }; int main(int argc, char **argv) { - bool use_tcp = false; - bool be_quiet = false; - uint32_t cycle = 1000; // Default: 1s - - std::string tcp_enable("--tcp"); - std::string udp_enable("--udp"); - - int i = 1; - while (i < argc) { - if (tcp_enable == argv[i]) { - use_tcp = true; - } else if (udp_enable == argv[i]) { - use_tcp = false; - } - i++; - } - - client_sample its_sample(use_tcp); - its_sample.init(); - its_sample.start(); - return 0; + bool use_tcp = false; + bool be_quiet = false; + uint32_t cycle = 1000; // Default: 1s + + std::string tcp_enable("--tcp"); + std::string udp_enable("--udp"); + + int i = 1; + while (i < argc) { + if (tcp_enable == argv[i]) { + use_tcp = true; + } else if (udp_enable == argv[i]) { + use_tcp = false; + } + i++; + } + + client_sample its_sample(use_tcp); + its_sample.init(); + its_sample.start(); + return 0; } diff --git a/exportmap.gcc b/exportmap.gcc index a86d0e4..4931d62 100644 --- a/exportmap.gcc +++ b/exportmap.gcc @@ -7,6 +7,8 @@ global: vsomeip::serializer::*; *vsomeip::deserializer; vsomeip::deserializer::*; + *vsomeip::endpoint_definition; + vsomeip::endpoint_definition*; *vsomeip::tcp*; vsomeip::tcp*; *vsomeip::udp*; diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp index 52ad7da..b07cdf9 100644 --- a/implementation/routing/include/event.hpp +++ b/implementation/routing/include/event.hpp @@ -21,6 +21,7 @@ namespace vsomeip { class endpoint; +class endpoint_definition; class message; class payload; class routing_manager; @@ -38,7 +39,7 @@ class event : public std::enable_shared_from_this<event> { event_t get_event() const; void set_event(event_t _event); - std::shared_ptr<payload> get_payload() const; + const std::shared_ptr<payload> get_payload() const; void set_payload(std::shared_ptr<payload> _payload); bool is_field() const; @@ -57,6 +58,8 @@ class event : public std::enable_shared_from_this<event> { void add_eventgroup(eventgroup_t _eventgroup); void set_eventgroups(const std::set<eventgroup_t> &_eventgroups); + void notify_one(const std::shared_ptr<endpoint_definition> &_target); + private: void update_cbk(boost::system::error_code const &_error); void notify(); diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp index f169ac3..be8cc20 100644 --- a/implementation/routing/include/routing_manager.hpp +++ b/implementation/routing/include/routing_manager.hpp @@ -18,6 +18,7 @@ namespace vsomeip { class endpoint; +class endpoint_definition; class event; class payload; class service_info; @@ -61,8 +62,18 @@ public: virtual bool send(client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush, bool _reliable) = 0; - virtual void set(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::shared_ptr<payload> &_value) = 0; + virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message>) = 0; + + virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size) = 0; + + virtual bool get(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event) = 0; + + virtual bool set(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event, + const std::shared_ptr<payload> &_value) = 0; virtual bool is_available(service_t _service, instance_t _instance) const = 0; @@ -75,6 +86,6 @@ public: virtual void remove_local(client_t _client) = 0; }; -} // namespace vsomeip +} // namespace vsomeip #endif diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp index 3ba3b2f..cc5dc87 100644 --- a/implementation/routing/include/routing_manager_impl.hpp +++ b/implementation/routing/include/routing_manager_impl.hpp @@ -40,174 +40,186 @@ class service_discovery; } // namespace sd -class routing_manager_impl : public routing_manager, public endpoint_host, - public sd::service_discovery_host, public std::enable_shared_from_this< - routing_manager_impl> { - public: - routing_manager_impl(routing_manager_host *_host); - ~routing_manager_impl(); - - boost::asio::io_service & get_io(); - std::shared_ptr<configuration> get_configuration() const; - - void init(); - void start(); - void stop(); - - void offer_service(client_t _client, service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, - ttl_t _ttl); - - void stop_offer_service(client_t _client, service_t _service, - instance_t _instance); - - void request_service(client_t _client, service_t _service, - instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl); - - void release_service(client_t _client, service_t _service, - instance_t _instance); - - void subscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); - - void unsubscribe(client_t _client, service_t _service, instance_t _instance, - eventgroup_t _eventgroup); - - bool send(client_t _client, std::shared_ptr<message> _message, bool _flush, - bool _reliable); - - bool send(client_t _client, const byte_t *_data, uint32_t _size, - instance_t _instance, bool _flush, bool _reliable); - - void set(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::shared_ptr<payload> &_payload); - - bool is_available(service_t _service, instance_t _instance) const; - - // interface to stub - std::shared_ptr<endpoint> create_local(client_t _client); - std::shared_ptr<endpoint> find_local(client_t _client); - std::shared_ptr<endpoint> find_or_create_local(client_t _client); - void remove_local(client_t _client); - std::shared_ptr<endpoint> find_local(service_t _service, - instance_t _instance); - - // interface "endpoint_host" - std::shared_ptr<endpoint> find_remote_client(service_t _service, - instance_t _instance, - bool _reliable); - void on_connect(std::shared_ptr<endpoint> _endpoint); - void on_disconnect(std::shared_ptr<endpoint> _endpoint); - void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); - - // interface "service_discovery_host" - typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t; - const servicegroups_t & get_servicegroups() const; - std::shared_ptr<eventgroupinfo> find_eventgroup( - service_t _service, instance_t _instance, eventgroup_t _eventgroup) const; - services_t get_offered_services(const std::string &_name) const; - void create_service_discovery_endpoint(const std::string &_address, - uint16_t _port, bool _reliable); - bool send_to(const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, const byte_t *_data, uint32_t _size); - void init_routing_info(); - void add_routing_info(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, - ttl_t _ttl, const boost::asio::ip::address &_address, - uint16_t _port, bool _reliable); - void del_routing_info(service_t _service, instance_t _instance, - bool _reliable); - - void init_event_routing_info(); - void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target); - void on_unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target); - void on_subscribe_ack(service_t _service, instance_t _instance, - const boost::asio::ip::address &_address, uint16_t _port); - - private: - bool deliver_message(const byte_t *_data, length_t _length, - instance_t _instance); - - client_t find_local_client(service_t _service, instance_t _instance); - std::set<client_t> find_local_clients(service_t _service, instance_t _instance, eventgroup_t _eventgroup); - instance_t find_instance(service_t _service, endpoint *_endpoint); - - std::shared_ptr<serviceinfo> find_service(service_t _service, - instance_t _instance) const; - std::shared_ptr<serviceinfo> create_service(service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, - ttl_t _ttl); - - std::shared_ptr<endpoint> create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable); - std::shared_ptr<endpoint> find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable); - std::shared_ptr<endpoint> find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable); - - std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port, - bool _reliable); - std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port, - bool _reliable); - std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port, - bool _reliable); - - std::set<std::shared_ptr<event> > find_events(service_t _service, - instance_t _instance, - eventgroup_t _eventgroup); - std::shared_ptr<event> find_event(service_t _service, instance_t _instance, - event_t _event) const; - - private: - boost::asio::io_service &io_; - routing_manager_host *host_; - - std::shared_ptr<configuration> configuration_; - - std::shared_ptr<deserializer> deserializer_; - std::shared_ptr<serializer> serializer_; - - std::shared_ptr<routing_manager_stub> stub_; - std::shared_ptr<sd::service_discovery> discovery_; - - // Routing info - - // Local - std::map<client_t, std::shared_ptr<endpoint> > local_clients_; - std::map<service_t, std::map<instance_t, client_t> > local_services_; - - // Server endpoints for local services - std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > server_endpoints_; - std::map<service_t, std::map<endpoint *, instance_t> > service_instances_; - - // Client endpoints for remote services - std::map<boost::asio::ip::address, - std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > > client_endpoints_; - std::map<service_t, - std::map<instance_t, std::map<bool, std::shared_ptr<endpoint> > > > remote_services_; - - // Servicegroups - std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_; - std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo> > > services_; - - // Eventgroups - std::map<service_t, - std::map<instance_t, - std::map<eventgroup_t, std::shared_ptr<eventgroupinfo> > > > eventgroups_; - std::map<service_t, - std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_; - std::map<service_t, - std::map<instance_t, - std::map<eventgroup_t, std::set<client_t> > > > eventgroup_clients_; - - // Mutexes - std::recursive_mutex endpoint_mutex_; - std::mutex serialize_mutex_; +class routing_manager_impl: public routing_manager, + public endpoint_host, + public sd::service_discovery_host, + public std::enable_shared_from_this<routing_manager_impl> { +public: + routing_manager_impl(routing_manager_host *_host); + ~routing_manager_impl(); + + boost::asio::io_service & get_io(); + std::shared_ptr<configuration> get_configuration() const; + + void init(); + void start(); + void stop(); + + void offer_service(client_t _client, service_t _service, + instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl); + + void stop_offer_service(client_t _client, service_t _service, + instance_t _instance); + + void request_service(client_t _client, service_t _service, + instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl); + + void release_service(client_t _client, service_t _service, + instance_t _instance); + + void subscribe(client_t _client, service_t _service, instance_t _instance, + eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl); + + void unsubscribe(client_t _client, service_t _service, instance_t _instance, + eventgroup_t _eventgroup); + + bool send(client_t _client, std::shared_ptr<message> _message, bool _flush, + bool _reliable); + + bool send(client_t _client, const byte_t *_data, uint32_t _size, + instance_t _instance, bool _flush, bool _reliable); + + bool send_to(const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message); + + bool send_to(const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size); + + bool get(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event); + + bool set(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event, + const std::shared_ptr<payload> &_payload); + + bool is_available(service_t _service, instance_t _instance) const; + + // interface to stub + std::shared_ptr<endpoint> create_local(client_t _client); + std::shared_ptr<endpoint> find_local(client_t _client); + std::shared_ptr<endpoint> find_or_create_local(client_t _client); + void remove_local(client_t _client); + std::shared_ptr<endpoint> find_local(service_t _service, + instance_t _instance); + + // interface "endpoint_host" + std::shared_ptr<endpoint> find_remote_client(service_t _service, + instance_t _instance, + bool _reliable); + void on_connect(std::shared_ptr<endpoint> _endpoint); + void on_disconnect(std::shared_ptr<endpoint> _endpoint); + void on_message(const byte_t *_data, length_t _length, endpoint *_receiver); + + // interface "service_discovery_host" + typedef std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_t; + const servicegroups_t & get_servicegroups() const; + std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service, + instance_t _instance, eventgroup_t _eventgroup) const; + services_t get_offered_services(const std::string &_name) const; + void create_service_discovery_endpoint(const std::string &_address, + uint16_t _port, bool _reliable); + void init_routing_info(); + void add_routing_info(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, ttl_t _ttl, + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable); + void del_routing_info(service_t _service, instance_t _instance, + bool _reliable); + + void init_event_routing_info(); + void on_subscribe(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, + std::shared_ptr<endpoint_definition> _subscriber, + std::shared_ptr<endpoint_definition> _target); + void on_unsubscribe(service_t _service, instance_t _instance, + eventgroup_t _eventgroup, + std::shared_ptr<endpoint_definition> _target); + void on_subscribe_ack(service_t _service, instance_t _instance, + const boost::asio::ip::address &_address, uint16_t _port); + +private: + bool deliver_message(const byte_t *_data, length_t _length, + instance_t _instance); + + client_t find_local_client(service_t _service, instance_t _instance); + std::set<client_t> find_local_clients(service_t _service, + instance_t _instance, eventgroup_t _eventgroup); + instance_t find_instance(service_t _service, endpoint *_endpoint); + + std::shared_ptr<serviceinfo> find_service(service_t _service, + instance_t _instance) const; + std::shared_ptr<serviceinfo> create_service(service_t _service, + instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl); + + std::shared_ptr<endpoint> create_client_endpoint( + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable); + std::shared_ptr<endpoint> find_client_endpoint( + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable); + std::shared_ptr<endpoint> find_or_create_client_endpoint( + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable); + + std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port, + bool _reliable); + std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port, + bool _reliable); + std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port, + bool _reliable); + + std::set<std::shared_ptr<event> > find_events(service_t _service, + instance_t _instance, eventgroup_t _eventgroup); + std::shared_ptr<event> find_event(service_t _service, instance_t _instance, + event_t _event) const; + +private: + boost::asio::io_service &io_; + routing_manager_host *host_; + + std::shared_ptr<configuration> configuration_; + + std::shared_ptr<deserializer> deserializer_; + std::shared_ptr<serializer> serializer_; + + std::shared_ptr<routing_manager_stub> stub_; + std::shared_ptr<sd::service_discovery> discovery_; + + // Routing info + + // Local + std::map<client_t, std::shared_ptr<endpoint> > local_clients_; + std::map<service_t, std::map<instance_t, client_t> > local_services_; + + // Server endpoints for local services + std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > server_endpoints_; + std::map<service_t, std::map<endpoint *, instance_t> > service_instances_; + + // Client endpoints for remote services + std::map<boost::asio::ip::address, + std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint> > > > client_endpoints_; + std::map<service_t, + std::map<instance_t, std::map<bool, std::shared_ptr<endpoint> > > > remote_services_; + + // Servicegroups + std::map<std::string, std::shared_ptr<servicegroup> > servicegroups_; + std::map<service_t, std::map<instance_t, std::shared_ptr<serviceinfo> > > services_; + + // Eventgroups + std::map<service_t, + std::map<instance_t, + std::map<eventgroup_t, std::shared_ptr<eventgroupinfo> > > > eventgroups_; + std::map<service_t, + std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_; + std::map<service_t, + std::map<instance_t, std::map<eventgroup_t, std::set<client_t> > > > eventgroup_clients_; + + // Mutexes + std::recursive_mutex endpoint_mutex_; + std::mutex serialize_mutex_; }; } // namespace vsomeip diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp index f871ca2..abbe1cf 100644 --- a/implementation/routing/include/routing_manager_proxy.hpp +++ b/implementation/routing/include/routing_manager_proxy.hpp @@ -54,13 +54,23 @@ public: eventgroup_t _eventgroup); bool send(client_t _client, std::shared_ptr<message> _message, bool _flush, - bool _reliable); + bool _reliable); bool send(client_t _client, const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush = true, bool _reliable = false); - void set(client_t _client, service_t _service, instance_t _instance, - event_t _event, const std::shared_ptr<payload> &_value); + bool send_to(const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message); + + bool send_to(const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size); + + bool get(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event); + + bool set(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event, + const std::shared_ptr<payload> &_value); void on_connect(std::shared_ptr<endpoint> _endpoint); void on_disconnect(std::shared_ptr<endpoint> _endpoint); diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp index 3a96227..2b21c4a 100644 --- a/implementation/routing/src/event.cpp +++ b/implementation/routing/src/event.cpp @@ -9,6 +9,7 @@ #include <vsomeip/defines.hpp> #include <vsomeip/logger.hpp> #include <vsomeip/message.hpp> +#include <vsomeip/payload.hpp> #include <vsomeip/runtime.hpp> #include "../include/event.hpp" @@ -17,82 +18,94 @@ namespace vsomeip { -event::event(routing_manager *_routing) - : routing_(_routing), - message_(runtime::get()->create_notification()), - cycle_timer_(_routing->get_io()), - is_updating_on_change_(true) { +event::event(routing_manager *_routing) : + routing_(_routing), message_(runtime::get()->create_notification()), cycle_timer_( + _routing->get_io()), is_updating_on_change_(true) { } service_t event::get_service() const { - return message_->get_service(); + return (message_->get_service()); } void event::set_service(service_t _service) { - message_->set_service(_service); + message_->set_service(_service); } instance_t event::get_instance() const { - return message_->get_instance(); + return (message_->get_instance()); } void event::set_instance(instance_t _instance) { - message_->set_instance(_instance); + message_->set_instance(_instance); } event_t event::get_event() const { - return message_->get_method(); + return (message_->get_method()); } void event::set_event(event_t _event) { - message_->set_method(_event); // TODO: maybe we should check for the leading 0-bit + message_->set_method(_event); // TODO: maybe we should check for the leading 0-bit } bool event::is_field() const { - return is_field_; + return (is_field_); } void event::set_field(bool _is_field) { - is_field_ = _is_field; + is_field_ = _is_field; } -std::shared_ptr<payload> event::get_payload() const { - return message_->get_payload(); +const std::shared_ptr<payload> event::get_payload() const { + return (message_->get_payload()); } void event::set_payload(std::shared_ptr<payload> _payload) { - bool is_change = _payload != message_->get_payload(); - if (true) { - message_->set_payload(_payload); - if (is_updating_on_change_) { - notify(); - } - } + std::shared_ptr<payload> its_payload = message_->get_payload(); + bool is_change = (its_payload->get_length() != _payload->get_length()); + if (!is_change) { + std::size_t its_pos = 0; + const byte_t *its_old_data = its_payload->get_data(); + const byte_t *its_new_data = _payload->get_data(); + while (!is_change && its_pos < its_payload->get_length()) { + is_change = (*its_old_data++ != *its_new_data++); + its_pos++; + } + } + + if (is_change) { + std::shared_ptr<payload> its_new_payload + = runtime::get()->create_payload( + _payload->get_data(), _payload->get_length()); + message_->set_payload(its_new_payload); + if (is_updating_on_change_) { + notify(); + } + } } void event::set_update_on_change(bool _is_active) { - is_updating_on_change_ = _is_active; + is_updating_on_change_ = _is_active; } void event::set_update_cycle(std::chrono::milliseconds &_cycle) { - cycle_ = _cycle; - cycle_timer_.cancel(); + cycle_ = _cycle; + cycle_timer_.cancel(); - if (std::chrono::milliseconds::zero() != _cycle) { - cycle_timer_.expires_from_now(cycle_); - std::function<void(boost::system::error_code const &)> its_handler = - std::bind(&event::update_cbk, shared_from_this(), - std::placeholders::_1); - cycle_timer_.async_wait(its_handler); - } + if (std::chrono::milliseconds::zero() != _cycle) { + cycle_timer_.expires_from_now(cycle_); + std::function<void(boost::system::error_code const &)> its_handler = + std::bind(&event::update_cbk, shared_from_this(), + std::placeholders::_1); + cycle_timer_.async_wait(its_handler); + } } const std::set<eventgroup_t> & event::get_eventgroups() const { - return eventgroups_; + return (eventgroups_); } void event::add_eventgroup(eventgroup_t _eventgroup) { - eventgroups_.insert(_eventgroup); + eventgroups_.insert(_eventgroup); } void event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) { @@ -100,18 +113,23 @@ void event::set_eventgroups(const std::set<eventgroup_t> &_eventgroups) { } void event::update_cbk(boost::system::error_code const &_error) { - if (!_error) { - cycle_timer_.expires_from_now(cycle_); - notify(); - std::function<void(boost::system::error_code const &)> its_handler = - std::bind(&event::update_cbk, shared_from_this(), - std::placeholders::_1); - cycle_timer_.async_wait(its_handler); - } + if (!_error) { + cycle_timer_.expires_from_now(cycle_); + notify(); + std::function<void(boost::system::error_code const &)> its_handler = + std::bind(&event::update_cbk, shared_from_this(), + std::placeholders::_1); + cycle_timer_.async_wait(its_handler); + } } void event::notify() { - routing_->send(VSOMEIP_ROUTING_CLIENT, message_, true, false); + // TODO: find out how to provide the proper reliability + routing_->send(VSOMEIP_ROUTING_CLIENT, message_, true, false); +} + +void event::notify_one(const std::shared_ptr<endpoint_definition> &_target) { + routing_->send_to(_target, message_); } } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp index 80d8fb9..890c0c5 100644 --- a/implementation/routing/src/routing_manager_impl.cpp +++ b/implementation/routing/src/routing_manager_impl.cpp @@ -12,6 +12,8 @@ #include <vsomeip/constants.hpp> #include <vsomeip/logger.hpp> #include <vsomeip/message.hpp> +#include <vsomeip/payload.hpp> +#include <vsomeip/runtime.hpp> #include "../include/event.hpp" #include "../include/eventgroupinfo.hpp" @@ -37,1032 +39,1205 @@ namespace vsomeip { -routing_manager_impl::routing_manager_impl(routing_manager_host *_host) - : host_(_host), - io_(_host->get_io()), - deserializer_(std::make_shared<deserializer>()), - serializer_(std::make_shared<serializer>()), - configuration_(host_->get_configuration()) { +routing_manager_impl::routing_manager_impl(routing_manager_host *_host) : + host_(_host), io_(_host->get_io()), deserializer_( + std::make_shared<deserializer>()), serializer_( + std::make_shared<serializer>()), configuration_( + host_->get_configuration()) { } routing_manager_impl::~routing_manager_impl() { } boost::asio::io_service & routing_manager_impl::get_io() { - return (io_); + return (io_); } void routing_manager_impl::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - - serializer_->create_data(its_max_message_size); - - // TODO: Only instantiate the stub if needed - stub_ = std::make_shared < routing_manager_stub > (this); - stub_->init(); - - if (configuration_->is_service_discovery_enabled()) { - VSOMEIP_INFO<< "Service Discovery enabled."; - sd::runtime **its_runtime = - static_cast<sd::runtime **>(utility::load_library( - VSOMEIP_SD_LIBRARY, - VSOMEIP_SD_RUNTIME_SYMBOL_STRING)); - - if (0 != its_runtime && 0 != (*its_runtime)) { - VSOMEIP_INFO << "Service Discovery module loaded."; - discovery_ = (*its_runtime)->create_service_discovery(this); - discovery_->init(); - } - - init_event_routing_info(); - } else { - init_routing_info(); - } + uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) + its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; + if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) + its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; + + serializer_->create_data(its_max_message_size); + + // TODO: Only instantiate the stub if needed + stub_ = std::make_shared<routing_manager_stub>(this); + stub_->init(); + + if (configuration_->is_service_discovery_enabled()) { + VSOMEIP_INFO<< "Service Discovery enabled."; + sd::runtime **its_runtime = + static_cast<sd::runtime **>(utility::load_library( + VSOMEIP_SD_LIBRARY, + VSOMEIP_SD_RUNTIME_SYMBOL_STRING)); + + if (0 != its_runtime && 0 != (*its_runtime)) { + VSOMEIP_INFO << "Service Discovery module loaded."; + discovery_ = (*its_runtime)->create_service_discovery(this); + discovery_->init(); + } + + init_event_routing_info(); + } else { + init_routing_info(); + } } void routing_manager_impl::start() { - stub_->start(); - if (discovery_) - discovery_->start(); + stub_->start(); + if (discovery_) + discovery_->start(); - host_->on_event(event_type_e::REGISTERED); + host_->on_event(event_type_e::REGISTERED); } void routing_manager_impl::stop() { - host_->on_event(event_type_e::DEREGISTERED); + host_->on_event(event_type_e::DEREGISTERED); - if (discovery_) - discovery_->stop(); - stub_->stop(); + if (discovery_) + discovery_->stop(); + stub_->stop(); } void routing_manager_impl::offer_service(client_t _client, service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - local_services_[_service][_instance] = _client; - - // Remote route (incoming only) - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (its_info) { - if (its_info->get_major() == _major && its_info->get_minor() == _minor) { - its_info->set_ttl(_ttl); - } else { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); - } - } else { - (void) create_service(_service, _instance, _major, _minor, _ttl); - } - - host_->on_availability(_service, _instance, true); + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl) { + local_services_[_service][_instance] = _client; + + // Remote route (incoming only) + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (its_info) { + if (its_info->get_major() == _major + && its_info->get_minor() == _minor) { + its_info->set_ttl(_ttl); + if (discovery_) { + discovery_->on_offer_change(its_info->get_group()->get_name()); + } + } else { + host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); + } + } else { + (void) create_service(_service, _instance, _major, _minor, _ttl); + } + + host_->on_availability(_service, _instance, true); } void routing_manager_impl::stop_offer_service(client_t its_client, - service_t _service, - instance_t _instance) { - if (discovery_) { - auto found_service = services_.find(_service); - if (found_service != services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - found_instance->second->set_ttl(0); - } - } - } else { - // TODO: allow to withdraw a service on one endpoint only - del_routing_info(_service, _instance, false); - del_routing_info(_service, _instance, true); - } + service_t _service, instance_t _instance) { + if (discovery_) { + auto found_service = services_.find(_service); + if (found_service != services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + found_instance->second->set_ttl(0); + discovery_->on_offer_change( + found_instance->second->get_group()->get_name()); + } + } + } else { + // TODO: allow to withdraw a service on one endpoint only + del_routing_info(_service, _instance, false); + del_routing_info(_service, _instance, true); + } } void routing_manager_impl::request_service(client_t _client, service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (its_info) { - if ((_major > its_info->get_major()) - || (_major == its_info->get_major() && _minor > its_info->get_minor()) - || (_ttl > its_info->get_ttl())) { - host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); - } else { - its_info->add_client(_client); - } - } else { - if (discovery_) - discovery_->request_service(_service, _instance, _major, _minor, _ttl); - } + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl) { + + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (its_info) { + if ((_major > its_info->get_major()) + || (_major == its_info->get_major() + && _minor > its_info->get_minor()) + || (_ttl > its_info->get_ttl())) { + host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH); + } else { + its_info->add_client(_client); + } + } else { + if (discovery_) + discovery_->request_service(_service, _instance, _major, _minor, + _ttl); + } } void routing_manager_impl::release_service(client_t _client, service_t _service, - instance_t _instance) { - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (its_info) { - its_info->remove_client(_client); - } else { - if (discovery_) - discovery_->release_service(_service, _instance); - } + instance_t _instance) { + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (its_info) { + its_info->remove_client(_client); + } else { + if (discovery_) + discovery_->release_service(_service, _instance); + } } void routing_manager_impl::subscribe(client_t _client, service_t _service, - instance_t _instance, - eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) { - if (discovery_) { - eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); - if (0 == find_local_client(_service, _instance)) { - discovery_->subscribe(_service, _instance, _eventgroup, _major, _ttl); - } - } else { - VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; - } + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + ttl_t _ttl) { + if (discovery_) { + eventgroup_clients_[_service][_instance][_eventgroup].insert(_client); + if (0 == find_local_client(_service, _instance)) { + discovery_->subscribe(_service, _instance, _eventgroup, _major, + _ttl); + } + } else { + VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; + } } void routing_manager_impl::unsubscribe(client_t _client, service_t _service, - instance_t _instance, - eventgroup_t _eventgroup) { - if (discovery_) { - auto found_service = eventgroup_clients_.find(_service); - if (found_service != eventgroup_clients_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - found_eventgroup->second.erase(_client); - if (0 == found_eventgroup->second.size()) { - eventgroup_clients_.erase(_eventgroup); - } - } - } - } - discovery_->unsubscribe(_service, _instance, _eventgroup); - } else { - VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; - } + instance_t _instance, eventgroup_t _eventgroup) { + if (discovery_) { + auto found_service = eventgroup_clients_.find(_service); + if (found_service != eventgroup_clients_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find( + _eventgroup); + if (found_eventgroup != found_instance->second.end()) { + found_eventgroup->second.erase(_client); + if (0 == found_eventgroup->second.size()) { + eventgroup_clients_.erase(_eventgroup); + } + } + } + } + discovery_->unsubscribe(_service, _instance, _eventgroup); + } else { + VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!"; + } } bool routing_manager_impl::send(client_t its_client, - std::shared_ptr<message> _message, - bool _reliable, - bool _flush) { - bool is_sent(false); - std::unique_lock<std::mutex> its_lock(serialize_mutex_); - - if (utility::is_request(_message->get_message_type())) { - _message->set_client(its_client); - } - - if (serializer_->serialize(_message.get())) { - is_sent = send(its_client, serializer_->get_data(), serializer_->get_size(), - _message->get_instance(), _reliable, _flush); - serializer_->reset(); - } - return (is_sent); + std::shared_ptr<message> _message, + bool _reliable, + bool _flush) { + bool is_sent(false); + std::unique_lock<std::mutex> its_lock(serialize_mutex_); // TODO: lock serialization only + + if (utility::is_request(_message->get_message_type())) { + _message->set_client(its_client); + } + if (serializer_->serialize(_message.get())) { + is_sent = send(its_client, serializer_->get_data(), + serializer_->get_size(), _message->get_instance(), _reliable, + _flush); + serializer_->reset(); + } + + return (is_sent); } bool routing_manager_impl::send(client_t _client, const byte_t *_data, - length_t _size, instance_t _instance, - bool _flush, - bool _reliable) { - bool is_sent(false); - - std::shared_ptr<endpoint> its_target; - bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]); - bool is_notification = utility::is_notification(_data); - - client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], - _data[VSOMEIP_CLIENT_POS_MAX]); - service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], - _data[VSOMEIP_SERVICE_POS_MAX]); - - if (_size > VSOMEIP_MESSAGE_TYPE_POS) { - if (is_request) { - its_target = find_local(its_service, _instance); - } else { - its_target = find_local(its_client); - } - - if (its_target) { - std::vector<byte_t> its_command( - VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) - + sizeof(bool) + sizeof(bool)); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, - sizeof(client_t)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, - sizeof(_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, _size); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size], &_instance, - sizeof(instance_t)); - std::memcpy( - &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t)], - &_reliable, sizeof(bool)); - std::memcpy( - &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) - + sizeof(bool)], - &_flush, sizeof(bool)); - is_sent = its_target->send(&its_command[0], its_command.size(), _flush); - } else { - // Check whether hosting application should get the message - // If not, check routes to external - if ((its_client == host_->get_client() && !is_request) - || (find_local_client(its_service, _instance) == host_->get_client() - && is_request)) { - // TODO: find out how to handle session id here - is_sent = deliver_message(_data, _size, _instance); - } else { - if (is_request) { - its_target = find_remote_client(its_service, _instance, _reliable); - if (its_target) { - is_sent = its_target->send(_data, _size, _flush); - } else { - VSOMEIP_ERROR<< "Routing error. Client from remote service could not be found!"; - } - } else { - std::shared_ptr<serviceinfo> its_info( - find_service(its_service, _instance)); - if (its_info) { - its_target = its_info->get_endpoint(_reliable); - if (its_target) { - if (is_notification) { - method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], - _data[VSOMEIP_METHOD_POS_MAX]); - std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method); - if (its_event) { - for (auto its_group : its_event->get_eventgroups()) { - // local - auto its_local_clients = find_local_clients(its_service, _instance, its_group); - for (auto its_local_client : its_local_clients) { - std::shared_ptr<endpoint> its_local_target = find_local(its_local_client); - if (its_target) { - its_local_target->send(_data, _size); - } - } - - // remote - auto its_eventgroup = find_eventgroup(its_service, _instance, its_group); - if (its_eventgroup) { - for (auto its_remote : its_eventgroup->get_targets()) { - its_target->send_to(its_remote, _data, _size); - } - } - } - } - } else { - is_sent = its_target->send(_data, _size, _flush); - } - } else { - VSOMEIP_ERROR - << "Routing error. Service endpoint could not be found!"; - } - } else { - VSOMEIP_ERROR << "Routing error. Service could not be found!"; - } - } - } - } - } - - return (is_sent); + length_t _size, instance_t _instance, + bool _flush, + bool _reliable) { + bool is_sent(false); + + std::shared_ptr<endpoint> its_target; + bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]); + bool is_notification = utility::is_notification(_data); + + client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); + + if (_size > VSOMEIP_MESSAGE_TYPE_POS) { + if (is_request) { + its_target = find_local(its_service, _instance); + } else { + its_target = find_local(its_client); + } + + if (its_target) { + std::vector<byte_t> its_command( + VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) + + sizeof(bool) + sizeof(bool)); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, + sizeof(client_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, + sizeof(_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, + _size); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size], + &_instance, sizeof(instance_t)); + std::memcpy( + &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + + sizeof(instance_t)], &_reliable, sizeof(bool)); + std::memcpy( + &its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + + sizeof(instance_t) + sizeof(bool)], &_flush, + sizeof(bool)); + is_sent = its_target->send(&its_command[0], its_command.size(), + _flush); + } else { + // Check whether hosting application should get the message + // If not, check routes to external + if ((its_client == host_->get_client() && !is_request) + || (find_local_client(its_service, _instance) + == host_->get_client() && is_request)) { + // TODO: find out how to handle session id here + is_sent = deliver_message(_data, _size, _instance); + } else { + if (is_request) { + its_target = find_remote_client(its_service, _instance, + _reliable); + if (its_target) { + is_sent = its_target->send(_data, _size, _flush); + } else { + VSOMEIP_ERROR<< "Routing error. Client from remote service could not be found!"; + } + } else { + std::shared_ptr<serviceinfo> its_info( + find_service(its_service, _instance)); + if (its_info) { + its_target = its_info->get_endpoint(_reliable); + if (its_target) { + if (is_notification) { + method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method); + if (its_event) { + for (auto its_group : its_event->get_eventgroups()) { + // local + auto its_local_clients = find_local_clients(its_service, _instance, its_group); + for (auto its_local_client : its_local_clients) { + std::shared_ptr<endpoint> its_local_target = find_local(its_local_client); + if (its_target) { + its_local_target->send(_data, _size); + } + } + + // remote + auto its_eventgroup = find_eventgroup(its_service, _instance, its_group); + if (its_eventgroup) { + for (auto its_remote : its_eventgroup->get_targets()) { + its_target->send_to(its_remote, _data, _size); + } + } + } + } + } else { + is_sent = its_target->send(_data, _size, _flush); + } + } else { + VSOMEIP_ERROR << "Routing error. Service endpoint could not be found!"; + } + } else { + VSOMEIP_ERROR << "Routing error. Service could not be found!"; + } + } + } + } + } + + return (is_sent); } -void routing_manager_impl::set(client_t its_client, service_t _service, - instance_t _instance, event_t _event, - const std::shared_ptr<payload> &_payload) { - std::shared_ptr<event> its_event = find_event(_service, _instance, _event); - if (its_event) { - its_event->set_payload(_payload); - } else { - VSOMEIP_ERROR<< "Event [" << std::hex << std::setw(4) << std::setfill('0') - << _service << "." << std::setw(4) << std::setfill('0') << _instance - << "." << std::setw(4) << std::setfill('0') << _event - << "] is unknown!"; - } +bool routing_manager_impl::get(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event) { + bool is_sent(false); + std::shared_ptr<event> its_event = find_event(_service, _instance, _event); + if (its_event) { // local + // TODO: bring back the result to the application + } else { // remote + std::shared_ptr<endpoint> its_target = find_remote_client(_service, _instance, false); + if (its_target) { + std::shared_ptr<message> its_request = runtime::get()->create_request(); + if (its_request) { + its_request->set_service(_service); + its_request->set_instance(_instance); + its_request->set_method(_event); + its_request->set_client(_client); + its_request->set_session(_session); + + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(its_request.get())) { + is_sent = its_target->send(serializer_->get_data(), serializer_->get_size()); + } else { + VSOMEIP_ERROR << "routing_manager_impl: serialization error."; + } + serializer_->reset(); + } + } else { + VSOMEIP_ERROR << "routing_manager_impl::get: cannot find endpoint for event."; + } + } + return (is_sent); } -bool routing_manager_impl::send_to(const boost::asio::ip::address &_address, - uint16_t _port, bool _reliable, - const byte_t *_data, uint32_t _size) { - std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port, - _reliable); - if (its_endpoint) - return (its_endpoint->send_to( - std::make_shared<endpoint_definition>( - _address, _port, _reliable), _data, _size)); - - return (false); +bool routing_manager_impl::set(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event, + const std::shared_ptr<payload> &_payload) { + bool is_set(false); + std::shared_ptr<event> its_event = find_event(_service, _instance, _event); + if (its_event) { + its_event->set_payload(_payload); + // TODO: somehow bring back the result to the application as set according to SOME/IP is set+get + is_set = true; + } else { + std::shared_ptr<endpoint> its_target = find_remote_client(_service, _instance, false); + if (its_target) { + std::shared_ptr<message> its_request = runtime::get()->create_request(); + if (its_request) { + its_request->set_service(_service); + its_request->set_instance(_instance); + its_request->set_method(_event); + its_request->set_client(_client); + its_request->set_session(_session); + its_request->set_payload(_payload); + + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(its_request.get())) { + is_set = its_target->send(serializer_->get_data(), serializer_->get_size()); + } + serializer_->reset(); + } + } else { + VSOMEIP_ERROR << "routing_manager_impl::set: cannot find endpoint for event."; + } + } + return (is_set); +} + +bool routing_manager_impl::send_to( + const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message) { + bool is_sent(false); + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(_message.get())) { + is_sent = send_to(_target, + serializer_->get_data(), serializer_->get_size()); + serializer_->reset(); + } else { + VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed."; + } + return (is_sent); +} + +bool routing_manager_impl::send_to( + const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size) { + std::shared_ptr<endpoint> its_endpoint = find_or_create_server_endpoint( + _target->get_port(), _target->is_reliable()); + + return (its_endpoint && its_endpoint->send_to(_target, _data, _size)); } void routing_manager_impl::on_message(const byte_t *_data, length_t _size, - endpoint *_receiver) { + endpoint *_receiver) { #if 0 - std::stringstream msg; - msg << "rmi::on_message: "; - for (uint32_t i = 0; i < _size; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "rmi::on_message: "; + for (uint32_t i = 0; i < _size; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) { - service_t its_service = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); - if (its_service == VSOMEIP_SD_SERVICE) { - if (discovery_) - discovery_->on_message(_data, _size); - } else { - instance_t its_instance = find_instance(its_service, _receiver); - if (its_instance != ANY_INSTANCE) { - client_t its_client(VSOMEIP_ROUTING_CLIENT); - if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { - its_client = find_local_client(its_service, its_instance); - } else { - its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN], - _data[VSOMEIP_CLIENT_POS_MAX]); - } - - if (its_client == host_->get_client() || utility::is_notification(_data)) { - deliver_message(_data, _size, its_instance); - } else if (its_client != VSOMEIP_ROUTING_CLIENT) { - send(its_client, _data, _size, its_instance, true, false); - } else { - VSOMEIP_ERROR << "Cannot determine target application!"; - } - } else { - VSOMEIP_ERROR - << "Cannot determine service instance for [" << its_service << "]"; - } - } - } else { - //send_error(); // TODO: send error "malformed message" - } + service_t its_service; + instance_t its_instance; + method_t its_method; + client_t its_client; + session_t its_session; + + if (_size >= VSOMEIP_SOMEIP_HEADER_SIZE) { + its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], + _data[VSOMEIP_SERVICE_POS_MAX]); + if (its_service == VSOMEIP_SD_SERVICE) { + if (discovery_) + discovery_->on_message(_data, _size); + } else { + its_instance = find_instance(its_service, _receiver); + if (its_instance != ANY_INSTANCE) { + if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + its_method = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_METHOD_POS_MIN], + _data[VSOMEIP_METHOD_POS_MAX]); + if (utility::is_event(its_method)) { + std::shared_ptr<event> its_event = find_event( + its_service, its_instance, its_method); + if (its_event) { + if (its_event->is_field()) { + uint32_t its_length = utility::get_payload_size(_data, _size); + if (its_length > 0) { // set + std::shared_ptr<payload> its_payload = + runtime::get()->create_payload( + &_data[VSOMEIP_PAYLOAD_POS], + its_length); + its_event->set_payload(its_payload); + } + + if (!utility::is_request_no_return( + _data[VSOMEIP_RETURN_CODE_POS])) { + std::shared_ptr<message> its_response = + runtime::get()->create_message(); + its_client = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + its_session = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SESSION_POS_MIN], + _data[VSOMEIP_SESSION_POS_MAX]); + + its_response->set_service(its_service); + its_response->set_method(its_method); + its_response->set_client(its_client); + its_response->set_session(its_session); + its_response->set_message_type( + message_type_e::RESPONSE); + its_response->set_payload(its_event->get_payload()); + + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(its_response.get())) { + _receiver->send(serializer_->get_data(), serializer_->get_size(), true); + } else { + VSOMEIP_ERROR << "routing_manager_impl::on_message: serialization error."; + } + serializer_->reset(); + } + } else { + std::shared_ptr<message> its_response = + runtime::get()->create_message(); + its_client = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + its_session = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SESSION_POS_MIN], + _data[VSOMEIP_SESSION_POS_MAX]); + + its_response->set_service(its_service); + its_response->set_method(its_method); + its_response->set_client(its_client); + its_response->set_session(its_session); + its_response->set_message_type(message_type_e::ERROR); + + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(its_response.get())) { + _receiver->send(serializer_->get_data(), serializer_->get_size(), true); + } else { + VSOMEIP_ERROR << "routing_manager_impl::on_message: serialization error."; + } + serializer_->reset(); + } + } else { + its_client = VSOMEIP_ROUTING_CLIENT; + } + } else { + its_client = find_local_client(its_service, + its_instance); + } + } else { + its_client = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + } + + if (its_client == host_->get_client() + || utility::is_notification(_data)) { + deliver_message(_data, _size, its_instance); + } else if (its_client != VSOMEIP_ROUTING_CLIENT) { + send(its_client, _data, _size, its_instance, true, false); + } else { + VSOMEIP_ERROR<< "Cannot determine target application!"; + } + } else { + VSOMEIP_ERROR + << "Cannot determine service instance for [" << its_service << "]"; + } + } + } else { + //send_error(); // TODO: send error "malformed message" + } } void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) { - for (auto &its_service : remote_services_) { - for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, true); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, true); - } - } - } - } + for (auto &its_service : remote_services_) { + for (auto &its_instance : its_service.second) { + auto found_endpoint = its_instance.second.find(false); + if (found_endpoint != its_instance.second.end()) { + host_->on_availability(its_service.first, its_instance.first, + true); + } else { + found_endpoint = its_instance.second.find(true); + if (found_endpoint != its_instance.second.end()) { + host_->on_availability(its_service.first, + its_instance.first, true); + } + } + } + } } void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) { - for (auto &its_service : remote_services_) { - for (auto &its_instance : its_service.second) { - auto found_endpoint = its_instance.second.find(false); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, false); - } else { - found_endpoint = its_instance.second.find(true); - if (found_endpoint != its_instance.second.end()) { - host_->on_availability(its_service.first, its_instance.first, false); - } - } - } - } + for (auto &its_service : remote_services_) { + for (auto &its_instance : its_service.second) { + auto found_endpoint = its_instance.second.find(false); + if (found_endpoint != its_instance.second.end()) { + host_->on_availability(its_service.first, its_instance.first, + false); + } else { + found_endpoint = its_instance.second.find(true); + if (found_endpoint != its_instance.second.end()) { + host_->on_availability(its_service.first, + its_instance.first, false); + } + } + } + } } bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size, - instance_t _instance) { - bool is_sent(false); - deserializer_->set_data(_data, _size); - std::shared_ptr<message> its_message(deserializer_->deserialize_message()); - if (its_message) { - its_message->set_instance(_instance); - host_->on_message(its_message); - is_sent = true; - } else { - // TODO: send error "Malformed Message" - //send_error(); - } - return (is_sent); + instance_t _instance) { + bool is_sent(false); + deserializer_->set_data(_data, _size); + std::shared_ptr<message> its_message(deserializer_->deserialize_message()); + if (its_message) { + its_message->set_instance(_instance); + host_->on_message(its_message); + is_sent = true; + } else { + // TODO: send error "Malformed Message" + //send_error(); + } + return (is_sent); } bool routing_manager_impl::is_available(service_t _service, - instance_t _instance) const { - auto find_local_service = local_services_.find(_service); - if (find_local_service != local_services_.end()) { - auto find_local_instance = find_local_service->second.find(_instance); - if (find_local_instance != find_local_service->second.end()) { - return (true); - } - } - - auto find_remote_service = remote_services_.find(_service); - if (find_remote_service != remote_services_.end()) { - auto find_remote_instance = find_remote_service->second.find(_instance); - if (find_remote_instance != find_remote_service->second.end()) { - return (true); - } - } - - return (false); + instance_t _instance) const { + auto find_local_service = local_services_.find(_service); + if (find_local_service != local_services_.end()) { + auto find_local_instance = find_local_service->second.find(_instance); + if (find_local_instance != find_local_service->second.end()) { + return (true); + } + } + + auto find_remote_service = remote_services_.find(_service); + if (find_remote_service != remote_services_.end()) { + auto find_remote_instance = find_remote_service->second.find(_instance); + if (find_remote_instance != find_remote_service->second.end()) { + return (true); + } + } + + return (false); } const std::map<std::string, std::shared_ptr<servicegroup> > & routing_manager_impl::get_servicegroups() const { - return (servicegroups_); + return (servicegroups_); } std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup( - service_t _service, instance_t _instance, eventgroup_t _eventgroup) const { - std::shared_ptr<eventgroupinfo> its_info(nullptr); - auto found_service = eventgroups_.find(_service); - if (found_service != eventgroups_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - its_info = found_eventgroup->second; - std::shared_ptr<serviceinfo> its_service_info = find_service(_service, - _instance); - if (its_service_info) { - if (_eventgroup == its_service_info->get_multicast_group()) { - boost::asio::ip::address its_multicast_address = - boost::asio::ip::address::from_string( - its_service_info->get_multicast_address()); - uint16_t its_multicast_port = - its_service_info->get_multicast_port(); - its_info->set_multicast(its_multicast_address, its_multicast_port); - } - its_info->set_major(its_service_info->get_major()); - its_info->set_ttl(its_service_info->get_ttl()); - } - } - } - } - return (its_info); + service_t _service, instance_t _instance, + eventgroup_t _eventgroup) const { + std::shared_ptr<eventgroupinfo> its_info(nullptr); + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + its_info = found_eventgroup->second; + std::shared_ptr<serviceinfo> its_service_info = find_service( + _service, _instance); + if (its_service_info) { + if (_eventgroup + == its_service_info->get_multicast_group()) { + boost::asio::ip::address its_multicast_address = + boost::asio::ip::address::from_string( + its_service_info->get_multicast_address()); + uint16_t its_multicast_port = + its_service_info->get_multicast_port(); + its_info->set_multicast(its_multicast_address, + its_multicast_port); + } + its_info->set_major(its_service_info->get_major()); + its_info->set_ttl(its_service_info->get_ttl()); + } + } + } + } + return (its_info); } std::shared_ptr<configuration> routing_manager_impl::get_configuration() const { - return (host_->get_configuration()); + return (host_->get_configuration()); } void routing_manager_impl::create_service_discovery_endpoint( - const std::string &_address, uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint( - _port, _reliable); - if (!its_service_endpoint) { - its_service_endpoint = create_server_endpoint(_port, _reliable); - - std::shared_ptr<serviceinfo> its_info( - std::make_shared < serviceinfo > (ANY_MAJOR, ANY_MINOR, ANY_TTL)); - its_info->set_endpoint(its_service_endpoint, _reliable); - - // routing info - services_[VSOMEIP_SD_SERVICE][VSOMEIP_SD_INSTANCE] = its_info; - - its_service_endpoint->add_multicast(VSOMEIP_SD_SERVICE, VSOMEIP_SD_METHOD, - _address, _port); - its_service_endpoint->join(_address); - its_service_endpoint->start(); - } + const std::string &_address, uint16_t _port, bool _reliable) { + std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port, + _reliable); + if (!its_service_endpoint) { + its_service_endpoint = create_server_endpoint(_port, _reliable); + + std::shared_ptr<serviceinfo> its_info( + std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR, ANY_TTL)); + its_info->set_endpoint(its_service_endpoint, _reliable); + + // routing info + services_[VSOMEIP_SD_SERVICE][VSOMEIP_SD_INSTANCE] = its_info; + + its_service_endpoint->add_multicast(VSOMEIP_SD_SERVICE, + VSOMEIP_SD_METHOD, _address, _port); + its_service_endpoint->join(_address); + its_service_endpoint->start(); + } } services_t routing_manager_impl::get_offered_services( - const std::string &_name) const { - services_t its_offers; - auto find_servicegroup = servicegroups_.find(_name); - if (find_servicegroup != servicegroups_.end()) { - return (find_servicegroup->second->get_services()); - } - - return (its_offers); + const std::string &_name) const { + services_t its_offers; + auto find_servicegroup = servicegroups_.find(_name); + if (find_servicegroup != servicegroups_.end()) { + return (find_servicegroup->second->get_services()); + } + + return (its_offers); } /////////////////////////////////////////////////////////////////////////////// // PRIVATE /////////////////////////////////////////////////////////////////////////////// std::shared_ptr<serviceinfo> routing_manager_impl::find_service( - service_t _service, instance_t _instance) const { - std::shared_ptr<serviceinfo> its_info; - auto found_service = services_.find(_service); - if (found_service != services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - its_info = found_instance->second; - } - } - return (its_info); + service_t _service, instance_t _instance) const { + std::shared_ptr<serviceinfo> its_info; + auto found_service = services_.find(_service); + if (found_service != services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + its_info = found_instance->second; + } + } + return (its_info); } std::shared_ptr<serviceinfo> routing_manager_impl::create_service( - service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - std::shared_ptr<serviceinfo> its_info; - if (configuration_) { - its_info = std::make_shared < serviceinfo > (_major, _minor, _ttl); - - uint16_t its_reliable_port = configuration_->get_reliable_port(_service, - _instance); - uint16_t its_unreliable_port = configuration_->get_unreliable_port( - _service, _instance); - - its_info->set_multicast_address( - configuration_->get_multicast_address(_service, _instance)); - its_info->set_multicast_port( - configuration_->get_multicast_port(_service, _instance)); - its_info->set_multicast_group( - configuration_->get_multicast_group(_service, _instance)); - - std::shared_ptr<endpoint> its_reliable_endpoint; - std::shared_ptr<endpoint> its_unreliable_endpoint; - - if (ILLEGAL_PORT != its_reliable_port) { - its_reliable_endpoint = find_or_create_server_endpoint(its_reliable_port, - true); - its_info->set_endpoint(its_reliable_endpoint, true); - - // TODO: put this in a method and check whether an assignment already exists! - service_instances_[_service][its_reliable_endpoint.get()] = _instance; - } - - if (ILLEGAL_PORT != its_unreliable_port) { - its_unreliable_endpoint = find_or_create_server_endpoint( - its_unreliable_port, false); - its_info->set_endpoint(its_unreliable_endpoint, false); - - service_instances_[_service][its_unreliable_endpoint.get()] = _instance; - } - - if (ILLEGAL_PORT != its_reliable_port - || ILLEGAL_PORT != its_unreliable_port) { - std::string its_servicegroup = configuration_->get_group(_service, - _instance); - auto found_servicegroup = servicegroups_.find(its_servicegroup); - if (found_servicegroup == servicegroups_.end()) { - servicegroups_[its_servicegroup] - = std::make_shared<servicegroup>(its_servicegroup); - } - servicegroups_[its_servicegroup]->add_service( - _service, _instance, its_info); - services_[_service][_instance] = its_info; - } else { - host_->on_error(error_code_e::PORT_CONFIGURATION_MISSING); - } - } else { - host_->on_error(error_code_e::CONFIGURATION_MISSING); - } - - return (its_info); + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl) { + std::shared_ptr<serviceinfo> its_info; + if (configuration_) { + its_info = std::make_shared<serviceinfo>(_major, _minor, _ttl); + + uint16_t its_reliable_port = configuration_->get_reliable_port(_service, + _instance); + uint16_t its_unreliable_port = configuration_->get_unreliable_port( + _service, _instance); + + its_info->set_multicast_address( + configuration_->get_multicast_address(_service, _instance)); + its_info->set_multicast_port( + configuration_->get_multicast_port(_service, _instance)); + its_info->set_multicast_group( + configuration_->get_multicast_group(_service, _instance)); + + std::shared_ptr<endpoint> its_reliable_endpoint; + std::shared_ptr<endpoint> its_unreliable_endpoint; + + if (ILLEGAL_PORT != its_reliable_port) { + its_reliable_endpoint = find_or_create_server_endpoint( + its_reliable_port, + true); + its_info->set_endpoint(its_reliable_endpoint, true); + + // TODO: put this in a method and check whether an assignment already exists! + service_instances_[_service][its_reliable_endpoint.get()] = + _instance; + } + + if (ILLEGAL_PORT != its_unreliable_port) { + its_unreliable_endpoint = find_or_create_server_endpoint( + its_unreliable_port, false); + its_info->set_endpoint(its_unreliable_endpoint, false); + + service_instances_[_service][its_unreliable_endpoint.get()] = + _instance; + } + + if (ILLEGAL_PORT != its_reliable_port + || ILLEGAL_PORT != its_unreliable_port) { + std::string its_servicegroup = configuration_->get_group(_service, + _instance); + auto found_servicegroup = servicegroups_.find(its_servicegroup); + if (found_servicegroup == servicegroups_.end()) { + servicegroups_[its_servicegroup] = + std::make_shared<servicegroup>(its_servicegroup); + } + servicegroups_[its_servicegroup]->add_service(_service, _instance, + its_info); + services_[_service][_instance] = its_info; + } else { + host_->on_error(error_code_e::PORT_CONFIGURATION_MISSING); + } + } else { + host_->on_error(error_code_e::CONFIGURATION_MISSING); + } + + return (its_info); } std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_endpoint; - try { - if (_reliable) { - its_endpoint = std::make_shared < tcp_client_endpoint_impl - > (shared_from_this(), boost::asio::ip::tcp::endpoint(_address, - _port), io_); - - if (configuration_->has_enabled_magic_cookies(_address.to_string(), - _port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - its_endpoint = std::make_shared < udp_client_endpoint_impl - > (shared_from_this(), boost::asio::ip::udp::endpoint(_address, - _port), io_); - } - - client_endpoints_[_address][_port][_reliable] = its_endpoint; - its_endpoint->start(); - } catch (std::exception &e) { - host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED); - } - - return (its_endpoint); + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable) { + std::shared_ptr<endpoint> its_endpoint; + try { + if (_reliable) { + its_endpoint = std::make_shared<tcp_client_endpoint_impl>( + shared_from_this(), + boost::asio::ip::tcp::endpoint(_address, _port), io_); + + if (configuration_->has_enabled_magic_cookies(_address.to_string(), + _port)) { + its_endpoint->enable_magic_cookies(); + } + } else { + its_endpoint = std::make_shared<udp_client_endpoint_impl>( + shared_from_this(), + boost::asio::ip::udp::endpoint(_address, _port), io_); + } + + client_endpoints_[_address][_port][_reliable] = its_endpoint; + its_endpoint->start(); + } catch (std::exception &e) { + host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED); + } + + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_endpoint; - auto found_address = client_endpoints_.find(_address); - if (found_address != client_endpoints_.end()) { - auto found_port = found_address->second.find(_port); - if (found_port != found_address->second.end()) { - auto found_endpoint = found_port->second.find(_reliable); - if (found_endpoint != found_port->second.end()) { - its_endpoint = found_endpoint->second; - } - } - } - return (its_endpoint); + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable) { + std::shared_ptr<endpoint> its_endpoint; + auto found_address = client_endpoints_.find(_address); + if (found_address != client_endpoints_.end()) { + auto found_port = found_address->second.find(_port); + if (found_port != found_address->second.end()) { + auto found_endpoint = found_port->second.find(_reliable); + if (found_endpoint != found_port->second.end()) { + its_endpoint = found_endpoint->second; + } + } + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_or_create_client_endpoint( - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) { - std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint = find_client_endpoint(_address, _port, - _reliable); - if (0 == its_endpoint) { - its_endpoint = create_client_endpoint(_address, _port, _reliable); - } - return (its_endpoint); + const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable) { + std::unique_lock<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> its_endpoint = find_client_endpoint(_address, + _port, _reliable); + if (0 == its_endpoint) { + its_endpoint = create_client_endpoint(_address, _port, _reliable); + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint( - uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_endpoint; - - try { - boost::asio::ip::address its_unicast = configuration_->get_unicast(); - if (_reliable) { - its_endpoint = std::make_shared < tcp_server_endpoint_impl - > (shared_from_this(), boost::asio::ip::tcp::endpoint(its_unicast, - _port), io_); - if (configuration_->has_enabled_magic_cookies(its_unicast.to_string(), - _port)) { - its_endpoint->enable_magic_cookies(); - } - } else { - if (its_unicast.is_v4()) { - its_unicast = boost::asio::ip::address_v4::any(); - } else { - // TODO: how is "ANY" specified in IPv6? - } - its_endpoint = std::make_shared < udp_server_endpoint_impl - > (shared_from_this(), boost::asio::ip::udp::endpoint(its_unicast, - _port), io_); - } - - server_endpoints_[_port][_reliable] = its_endpoint; - its_endpoint->start(); - } catch (std::exception &e) { - host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); - } - - return (its_endpoint); + uint16_t _port, bool _reliable) { + std::shared_ptr<endpoint> its_endpoint; + + try { + boost::asio::ip::address its_unicast = configuration_->get_unicast(); + if (_reliable) { + its_endpoint = std::make_shared<tcp_server_endpoint_impl>( + shared_from_this(), + boost::asio::ip::tcp::endpoint(its_unicast, _port), io_); + if (configuration_->has_enabled_magic_cookies( + its_unicast.to_string(), _port)) { + its_endpoint->enable_magic_cookies(); + } + } else { + if (its_unicast.is_v4()) { + its_unicast = boost::asio::ip::address_v4::any(); + } else { + // TODO: how is "ANY" specified in IPv6? + } + its_endpoint = std::make_shared<udp_server_endpoint_impl>( + shared_from_this(), + boost::asio::ip::udp::endpoint(its_unicast, _port), io_); + } + + server_endpoints_[_port][_reliable] = its_endpoint; + its_endpoint->start(); + } catch (std::exception &e) { + host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED); + } + + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint( - uint16_t _port, bool _reliable) { - std::shared_ptr<endpoint> its_endpoint; - auto found_port = server_endpoints_.find(_port); - if (found_port != server_endpoints_.end()) { - auto found_endpoint = found_port->second.find(_reliable); - if (found_endpoint != found_port->second.end()) { - its_endpoint = found_endpoint->second; - } - } - return (its_endpoint); + uint16_t _port, bool _reliable) { + std::shared_ptr<endpoint> its_endpoint; + auto found_port = server_endpoints_.find(_port); + if (found_port != server_endpoints_.end()) { + auto found_endpoint = found_port->second.find(_reliable); + if (found_endpoint != found_port->second.end()) { + its_endpoint = found_endpoint->second; + } + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint( - uint16_t _port, bool _reliable) { - std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port, - _reliable); - if (0 == its_endpoint) { - its_endpoint = create_server_endpoint(_port, _reliable); - } - return (its_endpoint); + uint16_t _port, bool _reliable) { + std::unique_lock<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port, + _reliable); + if (0 == its_endpoint) { + its_endpoint = create_server_endpoint(_port, _reliable); + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_local(client_t _client) { - std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint; - auto found_endpoint = local_clients_.find(_client); - if (found_endpoint != local_clients_.end()) { - its_endpoint = found_endpoint->second; - } - return (its_endpoint); + std::unique_lock<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> its_endpoint; + auto found_endpoint = local_clients_.find(_client); + if (found_endpoint != local_clients_.end()) { + its_endpoint = found_endpoint->second; + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::create_local(client_t _client) { - std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_); - - std::stringstream its_path; - its_path << base_path << std::hex << _client; - - std::shared_ptr<endpoint> its_endpoint = std::make_shared - < local_client_endpoint_impl - > (shared_from_this(), boost::asio::local::stream_protocol::endpoint( - its_path.str()), io_); - local_clients_[_client] = its_endpoint; - its_endpoint->start(); - return (its_endpoint); + std::unique_lock<std::recursive_mutex> its_lock(endpoint_mutex_); + + std::stringstream its_path; + its_path << base_path << std::hex << _client; + + std::shared_ptr<endpoint> its_endpoint = std::make_shared< + local_client_endpoint_impl>(shared_from_this(), + boost::asio::local::stream_protocol::endpoint(its_path.str()), io_); + local_clients_[_client] = its_endpoint; + its_endpoint->start(); + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_impl::find_or_create_local( - client_t _client) { - std::shared_ptr<endpoint> its_endpoint(find_local(_client)); - if (!its_endpoint) { - its_endpoint = create_local(_client); - } - return (its_endpoint); + client_t _client) { + std::shared_ptr<endpoint> its_endpoint(find_local(_client)); + if (!its_endpoint) { + its_endpoint = create_local(_client); + } + return (its_endpoint); } void routing_manager_impl::remove_local(client_t _client) { - std::unique_lock < std::recursive_mutex > its_lock(endpoint_mutex_); - std::shared_ptr<endpoint> its_endpoint = find_local(_client); - its_endpoint->stop(); - local_clients_.erase(_client); + std::unique_lock<std::recursive_mutex> its_lock(endpoint_mutex_); + std::shared_ptr<endpoint> its_endpoint = find_local(_client); + its_endpoint->stop(); + local_clients_.erase(_client); } -std::shared_ptr<endpoint> routing_manager_impl::find_local( - service_t _service, instance_t _instance) { - return (find_local(find_local_client(_service, _instance))); +std::shared_ptr<endpoint> routing_manager_impl::find_local(service_t _service, + instance_t _instance) { + return (find_local(find_local_client(_service, _instance))); } client_t routing_manager_impl::find_local_client(service_t _service, - instance_t _instance) { - client_t its_client(0); - auto found_service = local_services_.find(_service); - if (found_service != local_services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - its_client = found_instance->second; - } - } - return (its_client); + instance_t _instance) { + client_t its_client(0); + auto found_service = local_services_.find(_service); + if (found_service != local_services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + its_client = found_instance->second; + } + } + return (its_client); } -std::set<client_t> routing_manager_impl::find_local_clients( - service_t _service, instance_t _instance, eventgroup_t _eventgroup) { - std::set<client_t> its_clients; - auto found_service = eventgroup_clients_.find(_service); - if (found_service != eventgroup_clients_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - its_clients = found_eventgroup->second; - } - } - } - return (its_clients); +std::set<client_t> routing_manager_impl::find_local_clients(service_t _service, + instance_t _instance, eventgroup_t _eventgroup) { + std::set<client_t> its_clients; + auto found_service = eventgroup_clients_.find(_service); + if (found_service != eventgroup_clients_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + its_clients = found_eventgroup->second; + } + } + } + return (its_clients); } instance_t routing_manager_impl::find_instance(service_t _service, - endpoint * _endpoint) { - instance_t its_instance(0xFFFF); - auto found_service = service_instances_.find(_service); - if (found_service != service_instances_.end()) { - auto found_endpoint = found_service->second.find(_endpoint); - if (found_endpoint != found_service->second.end()) { - its_instance = found_endpoint->second; - } - } - return (its_instance); + endpoint * _endpoint) { + instance_t its_instance(0xFFFF); + auto found_service = service_instances_.find(_service); + if (found_service != service_instances_.end()) { + auto found_endpoint = found_service->second.find(_endpoint); + if (found_endpoint != found_service->second.end()) { + its_instance = found_endpoint->second; + } + } + return (its_instance); } std::shared_ptr<endpoint> routing_manager_impl::find_remote_client( - service_t _service, instance_t _instance, bool _reliable) { - std::shared_ptr<endpoint> its_endpoint; - auto found_service = remote_services_.find(_service); - if (found_service != remote_services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_reliability = found_instance->second.find(_reliable); - if (found_reliability != found_instance->second.end()) { - its_endpoint = found_reliability->second; - } - } - } - return (its_endpoint); + service_t _service, instance_t _instance, bool _reliable) { + std::shared_ptr<endpoint> its_endpoint; + auto found_service = remote_services_.find(_service); + if (found_service != remote_services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_reliability = found_instance->second.find(_reliable); + if (found_reliability != found_instance->second.end()) { + its_endpoint = found_reliability->second; + } + } + } + return (its_endpoint); } std::shared_ptr<event> routing_manager_impl::find_event(service_t _service, - instance_t _instance, - event_t _event) const { - std::shared_ptr<event> its_event; - auto find_service = events_.find(_service); - if (find_service != events_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - auto find_event = find_instance->second.find(_event); - if (find_event != find_instance->second.end()) { - its_event = find_event->second; - } - } - } - return (its_event); + instance_t _instance, event_t _event) const { + std::shared_ptr<event> its_event; + auto find_service = events_.find(_service); + if (find_service != events_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + auto find_event = find_instance->second.find(_event); + if (find_event != find_instance->second.end()) { + its_event = find_event->second; + } + } + } + return (its_event); } std::set<std::shared_ptr<event> > routing_manager_impl::find_events( - service_t _service, instance_t _instance, eventgroup_t _eventgroup) { - std::set<std::shared_ptr<event> > its_events; - auto found_service = eventgroups_.find(_service); - if (found_service != eventgroups_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - return (found_eventgroup->second->get_events()); - } - } - } - return (its_events); + service_t _service, instance_t _instance, eventgroup_t _eventgroup) { + std::set<std::shared_ptr<event> > its_events; + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + return (found_eventgroup->second->get_events()); + } + } + } + return (its_events); } -void routing_manager_impl::add_routing_info( - service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) { - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (!its_info) { - its_info = create_service(_service, _instance, _major, _minor, _ttl); - services_[_service][_instance] = its_info; - } - - std::shared_ptr<endpoint> its_endpoint( - find_or_create_client_endpoint(_address, _port, _reliable)); - its_info->set_endpoint(its_endpoint, _reliable); - - remote_services_[_service][_instance][_reliable] = its_endpoint; - service_instances_[_service][its_endpoint.get()] = _instance; - stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); - - if (its_endpoint->is_connected()) - host_->on_availability(_service, _instance, true); +void routing_manager_impl::add_routing_info(service_t _service, + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable) { + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (!its_info) { + its_info = create_service(_service, _instance, _major, _minor, _ttl); + services_[_service][_instance] = its_info; + } + + std::shared_ptr<endpoint> its_endpoint( + find_or_create_client_endpoint(_address, _port, _reliable)); + its_info->set_endpoint(its_endpoint, _reliable); + + remote_services_[_service][_instance][_reliable] = its_endpoint; + service_instances_[_service][its_endpoint.get()] = _instance; + stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); + + if (its_endpoint->is_connected()) + host_->on_availability(_service, _instance, true); } void routing_manager_impl::del_routing_info(service_t _service, - instance_t _instance, - bool _reliable) { - std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); - if (its_info) { - std::shared_ptr<endpoint> its_empty_endpoint; - - // TODO: only tell the application if the service is completely gone - host_->on_availability(_service, _instance, false); - stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance); - - // Implicit unsubscribe - auto found_service = eventgroups_.find(_service); - if (found_service != eventgroups_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - its_eventgroup.second->clear_targets(); - } - } - } - - std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(_reliable); - if (its_endpoint) { - if (1 >= service_instances_[_service].size()) { - service_instances_.erase(_service); - } else { - service_instances_[_service].erase(its_endpoint.get()); - } - - remote_services_[_service][_instance].erase(_reliable); - auto found_endpoint = remote_services_[_service][_instance].find( - !_reliable); - if (found_endpoint == remote_services_[_service][_instance].end()) { - remote_services_[_service].erase(_instance); - } - if (1 >= remote_services_[_service].size()) { - remote_services_.erase(_service); - } - } - - if (!its_info->get_endpoint(!_reliable)) { - its_info->get_group()->remove_service(_service, _instance); - if (1 >= services_[_service].size()) { - services_.erase(_service); - } else { - services_[_service].erase(_instance); - } - } else { - its_info->set_endpoint(its_empty_endpoint, _reliable); - } - } + instance_t _instance, + bool _reliable) { + std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance)); + if (its_info) { + std::shared_ptr<endpoint> its_empty_endpoint; + + // TODO: only tell the application if the service is completely gone + host_->on_availability(_service, _instance, false); + stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, + _instance); + + // Implicit unsubscribe + auto found_service = eventgroups_.find(_service); + if (found_service != eventgroups_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + its_eventgroup.second->clear_targets(); + } + } + } + + std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint( + _reliable); + if (its_endpoint) { + if (1 >= service_instances_[_service].size()) { + service_instances_.erase(_service); + } else { + service_instances_[_service].erase(its_endpoint.get()); + } + + remote_services_[_service][_instance].erase(_reliable); + auto found_endpoint = remote_services_[_service][_instance].find( + !_reliable); + if (found_endpoint == remote_services_[_service][_instance].end()) { + remote_services_[_service].erase(_instance); + } + if (1 >= remote_services_[_service].size()) { + remote_services_.erase(_service); + } + } + + if (!its_info->get_endpoint(!_reliable)) { + its_info->get_group()->remove_service(_service, _instance); + if (1 >= services_[_service].size()) { + services_.erase(_service); + } else { + services_[_service].erase(_instance); + } + } else { + its_info->set_endpoint(its_empty_endpoint, _reliable); + } + } } void routing_manager_impl::init_routing_info() { - VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; - for (auto i : configuration_->get_remote_services()) { - std::string its_address = configuration_->get_unicast(i.first, i.second); - uint16_t its_reliable = configuration_->get_reliable_port(i.first, - i.second); - uint16_t its_unreliable = configuration_->get_unreliable_port(i.first, - i.second); - - if (VSOMEIP_INVALID_PORT != its_reliable) { - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_reliable, true); - } - - if (VSOMEIP_INVALID_PORT != its_unreliable) { - add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, - DEFAULT_TTL, - boost::asio::ip::address::from_string(its_address), - its_unreliable, false); - } - } + VSOMEIP_INFO<< "Service Discovery disabled. Using static routing information."; + for (auto i : configuration_->get_remote_services()) { + std::string its_address = configuration_->get_unicast(i.first, i.second); + uint16_t its_reliable = configuration_->get_reliable_port(i.first, + i.second); + uint16_t its_unreliable = configuration_->get_unreliable_port(i.first, + i.second); + + if (VSOMEIP_INVALID_PORT != its_reliable) { + add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, + DEFAULT_TTL, + boost::asio::ip::address::from_string(its_address), + its_reliable, true); + } + + if (VSOMEIP_INVALID_PORT != its_unreliable) { + add_routing_info(i.first, i.second, DEFAULT_MAJOR, DEFAULT_MINOR, + DEFAULT_TTL, + boost::asio::ip::address::from_string(its_address), + its_unreliable, false); + } + } } void routing_manager_impl::init_event_routing_info() { - // TODO: the following should be done before(!) initializing - // the configuration object to allow the configuration to - // directly write to the target structure! - std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events = - configuration_->get_events(); - for (auto i : its_events) { - for (auto j : i.second) { - for (auto k : j.second) { - std::shared_ptr<event> its_event(std::make_shared < event > (this)); - its_event->set_service(i.first); - its_event->set_instance(j.first); - its_event->set_event(k); - configuration_->set_event(its_event); - events_[i.first][j.first][k] = its_event; - } - } - } - - std::map<service_t, - std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups = - configuration_->get_eventgroups(); - for (auto i : its_eventgroups) { - for (auto j : i.second) { - for (auto k : j.second) { - eventgroups_[i.first][j.first][k.first] = std::make_shared< - eventgroupinfo>(); - for (auto l : k.second) { - std::shared_ptr<event> its_event = find_event(i.first, j.first, l); - if (its_event) { - eventgroups_[i.first][j.first][k.first]->add_event(its_event); - its_event->add_eventgroup(k.first); - } - } - } - } - } + // TODO: the following should be done before(!) initializing + // the configuration object to allow the configuration to + // directly write to the target structure! + std::map<service_t, std::map<instance_t, std::set<event_t> > > its_events = + configuration_->get_events(); + for (auto i : its_events) { + for (auto j : i.second) { + for (auto k : j.second) { + std::shared_ptr<event> its_event(std::make_shared<event>(this)); + its_event->set_service(i.first); + its_event->set_instance(j.first); + its_event->set_event(k); + configuration_->set_event(its_event); + events_[i.first][j.first][k] = its_event; + } + } + } + + std::map<service_t, + std::map<instance_t, std::map<eventgroup_t, std::set<event_t> > > > its_eventgroups = + configuration_->get_eventgroups(); + for (auto i : its_eventgroups) { + for (auto j : i.second) { + for (auto k : j.second) { + eventgroups_[i.first][j.first][k.first] = std::make_shared< + eventgroupinfo>(); + for (auto l : k.second) { + std::shared_ptr<event> its_event = find_event(i.first, + j.first, l); + if (its_event) { + eventgroups_[i.first][j.first][k.first]->add_event( + its_event); + its_event->add_eventgroup(k.first); + } + } + } + } + } #if 1 - for (auto i : eventgroups_) { - for (auto j : i.second) { - for (auto k : j.second) { - VSOMEIP_DEBUG<< "Eventgroup [" << std::hex << std::setw(4) - << std::setfill('0') << i.first << "." << j.first << "." << k.first - << "] (MC: "; - for (auto l : k.second->get_events()) { - VSOMEIP_DEBUG << " Event " << std::hex << std::setw(4) - << std::setfill('0') << l->get_event(); - } - } - } - } + for (auto i : eventgroups_) { + for (auto j : i.second) { + for (auto k : j.second) { + VSOMEIP_DEBUG<< "Eventgroup [" << std::hex << std::setw(4) + << std::setfill('0') << i.first << "." << j.first << "." << k.first + << "] (MC: "; + for (auto l : k.second->get_events()) { + VSOMEIP_DEBUG << " Event " << std::hex << std::setw(4) + << std::setfill('0') << l->get_event(); + } + } + } + } #endif } void routing_manager_impl::on_subscribe( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target) { - std::shared_ptr<eventgroupinfo> its_eventgroup - = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - its_eventgroup->add_target(_target); - } else { - VSOMEIP_ERROR<< "subscribe: attempt to subscribe to unknown eventgroup!"; - } + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<endpoint_definition> _subscriber, + std::shared_ptr<endpoint_definition> _target) { + std::shared_ptr<eventgroupinfo> its_eventgroup + = find_eventgroup(_service, _instance, _eventgroup); + if (its_eventgroup) { + its_eventgroup->add_target(_target); // unicast or multicast + for (auto its_event : its_eventgroup->get_events()) { + if (its_event->is_field()) { + its_event->notify_one(_subscriber); // unicast + } + } + } else { + VSOMEIP_ERROR<< "subscribe: attempt to subscribe to unknown eventgroup!"; + } } -void routing_manager_impl::on_unsubscribe( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<endpoint_definition> _target) { - std::shared_ptr<eventgroupinfo> its_eventgroup - = find_eventgroup(_service, _instance, _eventgroup); - if (its_eventgroup) { - its_eventgroup->del_target(_target); - } else { - VSOMEIP_ERROR<<"unsubscribe: attempt to subscribe to unknown eventgroup!"; - } +void routing_manager_impl::on_unsubscribe(service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<endpoint_definition> _target) { + std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service, + _instance, _eventgroup); + if (its_eventgroup) { + its_eventgroup->del_target(_target); + } else { + VSOMEIP_ERROR<<"unsubscribe: attempt to subscribe to unknown eventgroup!"; + } } -void routing_manager_impl::on_subscribe_ack( - service_t _service, instance_t _instance, - const boost::asio::ip::address &_address, uint16_t _port) { - // TODO: find a way of getting rid of the following endpoint in - // case it used for multicast exclusively and the subscription - // is withdrawn or the service got lost - std::shared_ptr<endpoint> its_endpoint - = find_or_create_server_endpoint(_port, false); - if (its_endpoint) { - service_instances_[_service][its_endpoint.get()] = _instance; - its_endpoint->join(_address.to_string()); - } else { - VSOMEIP_ERROR << "Could not find/create multicast endpoint!"; - } +void routing_manager_impl::on_subscribe_ack(service_t _service, + instance_t _instance, const boost::asio::ip::address &_address, + uint16_t _port) { + // TODO: find a way of getting rid of the following endpoint in + // case it used for multicast exclusively and the subscription + // is withdrawn or the service got lost + std::shared_ptr<endpoint> its_endpoint = find_or_create_server_endpoint( + _port, false); + if (its_endpoint) { + service_instances_[_service][its_endpoint.get()] = _instance; + its_endpoint->join(_address.to_string()); + } else { + VSOMEIP_ERROR<<"Could not find/create multicast endpoint!"; + } } -} // namespace vsomeip +} + // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp index 4729e27..423058f 100644 --- a/implementation/routing/src/routing_manager_proxy.cpp +++ b/implementation/routing/src/routing_manager_proxy.cpp @@ -25,251 +25,262 @@ namespace vsomeip { -routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) - : io_(_host->get_io()), - host_(_host), - client_(_host->get_client()), - sender_(0), - receiver_(0), - serializer_(std::make_shared<serializer>()), - deserializer_(std::make_shared<deserializer>()) { +routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host) : + io_(_host->get_io()), host_(_host), client_(_host->get_client()), sender_( + 0), receiver_(0), serializer_(std::make_shared<serializer>()), deserializer_( + std::make_shared<deserializer>()) { } routing_manager_proxy::~routing_manager_proxy() { } boost::asio::io_service & routing_manager_proxy::get_io() { - return io_; + return (io_); } void routing_manager_proxy::init() { - uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; - if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; - if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) - its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; + uint32_t its_max_message_size = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE; + if (VSOMEIP_MAX_TCP_MESSAGE_SIZE > its_max_message_size) + its_max_message_size = VSOMEIP_MAX_TCP_MESSAGE_SIZE; + if (VSOMEIP_MAX_UDP_MESSAGE_SIZE > its_max_message_size) + its_max_message_size = VSOMEIP_MAX_UDP_MESSAGE_SIZE; - serializer_->create_data(its_max_message_size); + serializer_->create_data(its_max_message_size); - std::stringstream its_sender_path; - sender_ = create_local(VSOMEIP_ROUTING_CLIENT); + std::stringstream its_sender_path; + sender_ = create_local(VSOMEIP_ROUTING_CLIENT); - std::stringstream its_client; - its_client << base_path << std::hex << client_; + std::stringstream its_client; + its_client << base_path << std::hex << client_; - ::unlink(its_client.str().c_str()); - receiver_ = std::make_shared<local_server_endpoint_impl>( - shared_from_this(), - boost::asio::local::stream_protocol::endpoint(its_client.str()), io_); + ::unlink(its_client.str().c_str()); + receiver_ = std::make_shared<local_server_endpoint_impl>(shared_from_this(), + boost::asio::local::stream_protocol::endpoint(its_client.str()), + io_); - VSOMEIP_DEBUG<< "Listening at " << its_client.str(); + VSOMEIP_DEBUG<< "Listening at " << its_client.str(); } void routing_manager_proxy::start() { - if (sender_) - sender_->start(); + if (sender_) + sender_->start(); - if (receiver_) - receiver_->start(); + if (receiver_) + receiver_->start(); - // Tell the stub where to find us - register_application(); + // Tell the stub where to find us + register_application(); } void routing_manager_proxy::stop() { - // Tell the stub we are no longer active - deregister_application(); + // Tell the stub we are no longer active + deregister_application(); - if (receiver_) - receiver_->stop(); + if (receiver_) + receiver_->stop(); - std::stringstream its_client; - its_client << base_path << std::hex << client_; - ::unlink(its_client.str().c_str()); + std::stringstream its_client; + its_client << base_path << std::hex << client_; + ::unlink(its_client.str().c_str()); } void routing_manager_proxy::offer_service(client_t _client, service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, ttl_t _ttl) { - - byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_OFFER_SERVICE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; - - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_OFFER_SERVICE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, - sizeof(_minor)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, - sizeof(_ttl)); - - if (sender_) - sender_->send(its_command, sizeof(its_command)); + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl) { + + byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_OFFER_SERVICE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_OFFER_SERVICE; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4] = _major; + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_minor, + sizeof(_minor)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_ttl, + sizeof(_ttl)); + + if (sender_) + sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::stop_offer_service(client_t _client, - service_t _service, - instance_t _instance) { - - byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; - - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_STOP_OFFER_SERVICE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - - if (sender_) - sender_->send(its_command, sizeof(its_command)); + service_t _service, instance_t _instance) { + + byte_t its_command[VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_STOP_OFFER_SERVICE; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + + if (sender_) + sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::request_service(client_t _client, - service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, - ttl_t _ttl) { + service_t _service, instance_t _instance, major_version_t _major, + minor_version_t _minor, ttl_t _ttl) { } void routing_manager_proxy::release_service(client_t _client, - service_t _service, - instance_t _instance) { + service_t _service, instance_t _instance) { } void routing_manager_proxy::subscribe(client_t _client, service_t _service, - instance_t _instance, - eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) { - byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; - - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, - sizeof(_eventgroup)); - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_ttl, - sizeof(_ttl)); - - if (sender_) - sender_->send(its_command, sizeof(its_command)); + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + ttl_t _ttl) { + byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SUBSCRIBE; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, + sizeof(_eventgroup)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major; + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_ttl, + sizeof(_ttl)); + + if (sender_) + sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::unsubscribe(client_t _client, service_t _service, - instance_t _instance, - eventgroup_t _eventgroup) { - byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE]; - uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE - - VSOMEIP_COMMAND_HEADER_SIZE; - - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, - sizeof(_service)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, - sizeof(_instance)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, - sizeof(_eventgroup)); - - if (sender_) - sender_->send(its_command, sizeof(its_command)); + instance_t _instance, eventgroup_t _eventgroup) { + byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE]; + uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE + - VSOMEIP_COMMAND_HEADER_SIZE; + + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_UNSUBSCRIBE; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service, + sizeof(_service)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance, + sizeof(_instance)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup, + sizeof(_eventgroup)); + + if (sender_) + sender_->send(its_command, sizeof(its_command)); } bool routing_manager_proxy::send(client_t its_client, - std::shared_ptr<message> _message, - bool _flush, - bool _reliable) { - bool is_sent(false); - std::unique_lock<std::mutex> its_lock(serialize_mutex_); - if (serializer_->serialize(_message.get())) { - is_sent = send(its_client, serializer_->get_data(), serializer_->get_size(), - _message->get_instance(), _flush, _reliable); - serializer_->reset(); - } - return is_sent; + std::shared_ptr<message> _message, + bool _flush, + bool _reliable) { + bool is_sent(false); + std::unique_lock<std::mutex> its_lock(serialize_mutex_); + if (serializer_->serialize(_message.get())) { + is_sent = send(its_client, serializer_->get_data(), + serializer_->get_size(), _message->get_instance(), _flush, + _reliable); + serializer_->reset(); + } + return (is_sent); } bool routing_manager_proxy::send(client_t _client, const byte_t *_data, - length_t _size, instance_t _instance, - bool _flush, - bool _reliable) { - bool is_sent(false); - std::shared_ptr<endpoint> its_target; - - if (_size > VSOMEIP_MESSAGE_TYPE_POS) { - if (is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { - service_t its_service = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]); - std::unique_lock<std::mutex> its_lock(send_mutex_); - its_target = find_local(its_service, _instance); - } else { - client_t its_client = VSOMEIP_BYTES_TO_WORD( - _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]); - std::unique_lock<std::mutex> its_lock(send_mutex_); - its_target = find_local(its_client); - } - - // If no direct endpoint could be found, route to stub - if (!its_target) - its_target = sender_; - - std::vector<byte_t> its_command( - VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) + sizeof(bool) - + sizeof(bool)); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, - sizeof(client_t)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, - sizeof(_size)); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, _size); - std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size], &_instance, - sizeof(instance_t)); - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t)] = - _flush; - its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) - + sizeof(bool)] = _reliable; + length_t _size, instance_t _instance, + bool _flush, + bool _reliable) { + bool is_sent(false); + std::shared_ptr<endpoint> its_target; + + if (_size > VSOMEIP_MESSAGE_TYPE_POS) { + if (is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) { + service_t its_service = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_SERVICE_POS_MIN], + _data[VSOMEIP_SERVICE_POS_MAX]); + std::unique_lock<std::mutex> its_lock(send_mutex_); + its_target = find_local(its_service, _instance); + } else { + client_t its_client = VSOMEIP_BYTES_TO_WORD( + _data[VSOMEIP_CLIENT_POS_MIN], + _data[VSOMEIP_CLIENT_POS_MAX]); + std::unique_lock<std::mutex> its_lock(send_mutex_); + its_target = find_local(its_client); + } + + // If no direct endpoint could be found, route to stub + if (!its_target) + its_target = sender_; + + std::vector<byte_t> its_command( + VSOMEIP_COMMAND_HEADER_SIZE + _size + sizeof(instance_t) + + sizeof(bool) + sizeof(bool)); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_SEND; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client, + sizeof(client_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &_size, + sizeof(_size)); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], _data, _size); + std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size], + &_instance, sizeof(instance_t)); + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t)] = + _flush; + its_command[VSOMEIP_COMMAND_PAYLOAD_POS + _size + sizeof(instance_t) + + sizeof(bool)] = _reliable; #if 0 - std::cout << "rmp:send: "; - for (int i = 0; i < its_command.size(); i++) - std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; - std::cout << std::endl; + std::cout << "rmp:send: "; + for (int i = 0; i < its_command.size(); i++) + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)its_command[i] << " "; + std::cout << std::endl; #endif - is_sent = its_target->send(&its_command[0], its_command.size()); - } - return is_sent; + is_sent = its_target->send(&its_command[0], its_command.size()); + } + return (is_sent); } -void routing_manager_proxy::set(client_t _client, service_t _service, - instance_t _instance, event_t _event, - const std::shared_ptr<payload> &_value) { +bool routing_manager_proxy::send_to( + const std::shared_ptr<endpoint_definition> &_target, + std::shared_ptr<message> _message) { + return (false); +} + +bool routing_manager_proxy::send_to( + const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size) { + return (false); +} + +bool routing_manager_proxy::get(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event) { + bool is_gotten(false); + return (is_gotten); +} + +bool routing_manager_proxy::set(client_t _client, session_t _session, + service_t _service, instance_t _instance, event_t _event, + const std::shared_ptr<payload> &_value) { + bool is_set(false); + return (is_set); } void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) { @@ -279,264 +290,265 @@ void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) { } void routing_manager_proxy::on_message(const byte_t *_data, length_t _size, - endpoint *_receiver) { + endpoint *_receiver) { #if 0 - std::cout << "rmp::on_message: "; - for (int i = 0; i < _size; ++i) - std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - std::cout << std::endl; + std::cout << "rmp::on_message: "; + for (int i = 0; i < _size; ++i) + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + std::cout << std::endl; #endif - byte_t its_command; - client_t its_client; - length_t its_length; - - if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) { - its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; - std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], - sizeof(its_client)); - std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], - sizeof(its_length)); - - switch (its_command) { - case VSOMEIP_SEND: { - instance_t its_instance; - std::memcpy( - &its_instance, - &_data[_size - sizeof(instance_t) - sizeof(bool) - sizeof(bool)], - sizeof(instance_t)); - deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], - its_length); - std::shared_ptr<message> its_message( - deserializer_->deserialize_message()); - if (its_message) { - its_message->set_instance(its_instance); - host_->on_message(its_message); - } else { - // TODO: send_error(return_code_e::E_MALFORMED_MESSAGE); - } - deserializer_->reset(); - } - break; - - case VSOMEIP_ROUTING_INFO: - on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length); - break; - - case VSOMEIP_PING: - send_pong(); - break; - - default: - break; - } - } + byte_t its_command; + client_t its_client; + length_t its_length; + + if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) { + its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; + std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], + sizeof(its_client)); + std::memcpy(&its_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], + sizeof(its_length)); + + switch (its_command) { + case VSOMEIP_SEND: { + instance_t its_instance; + std::memcpy(&its_instance, + &_data[_size - sizeof(instance_t) - sizeof(bool) + - sizeof(bool)], sizeof(instance_t)); + deserializer_->set_data(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], + its_length); + std::shared_ptr<message> its_message( + deserializer_->deserialize_message()); + if (its_message) { + its_message->set_instance(its_instance); + host_->on_message(its_message); + } else { + // TODO: send_error(return_code_e::E_MALFORMED_MESSAGE); + } + deserializer_->reset(); + } + break; + + case VSOMEIP_ROUTING_INFO: + on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length); + break; + + case VSOMEIP_PING: + send_pong(); + break; + + default: + break; + } + } } void routing_manager_proxy::on_routing_info(const byte_t *_data, - uint32_t _size) { + uint32_t _size) { #if 0 - std::cout << "rmp::on_routing_info: "; - for (int i = 0; i < _size; ++i) - std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - std::cout << std::endl; + std::cout << "rmp::on_routing_info: "; + for (int i = 0; i < _size; ++i) + std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + std::cout << std::endl; #endif - event_type_e its_state(event_type_e::DEREGISTERED); - - std::map<service_t, std::map<instance_t, client_t> > old_local_services = - local_services_; - local_services_.clear(); - - uint32_t i = 0; - while (i + sizeof(uint32_t) <= _size) { - uint32_t its_client_size; - std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); - i += sizeof(uint32_t); - - if (i + sizeof(client_t) <= _size) { - client_t its_client; - std::memcpy(&its_client, &_data[i], sizeof(client_t)); - i += sizeof(client_t); - - if (its_client != client_) { - (void) find_or_create_local(its_client); - } else { - its_state = event_type_e::REGISTERED; - } - - if (i + sizeof(uint32_t) <= _size) { - uint32_t its_services_size; - std::memcpy(&its_services_size, &_data[i], sizeof(uint32_t)); - i += sizeof(uint32_t); - - uint32_t j = 0; - while (j + sizeof(service_t) + sizeof(instance_t) <= its_services_size) { - service_t its_service; - std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); - j += sizeof(service_t); - - instance_t its_instance; - std::memcpy(&its_instance, &_data[i + j], sizeof(instance_t)); - j += sizeof(instance_t); - - if (its_client != client_) - local_services_[its_service][its_instance] = its_client; - } - - i += its_services_size; - } - } - } - - // inform host about its own registration state - host_->on_event(its_state); - - // Check for services that are no longer available - for (auto i : old_local_services) { - auto found_service = local_services_.find(i.first); - if (found_service != local_services_.end()) { - for (auto j : i.second) { - auto found_instance = found_service->second.find(j.first); - if (found_instance == found_service->second.end()) { - host_->on_availability(i.first, j.first, false); - } - } - } else { - for (auto j : i.second) { - host_->on_availability(i.first, j.first, false); - } - } - } - - // Check for services that are newly available - for (auto i : local_services_) { - auto found_service = old_local_services.find(i.first); - if (found_service != old_local_services.end()) { - for (auto j : i.second) { - auto found_instance = found_service->second.find(j.first); - if (found_instance == found_service->second.end()) { - host_->on_availability(i.first, j.first, true); - } - } - } else { - for (auto j : i.second) { - host_->on_availability(i.first, j.first, true); - } - } - } + event_type_e its_state(event_type_e::DEREGISTERED); + + std::map<service_t, std::map<instance_t, client_t> > old_local_services = + local_services_; + local_services_.clear(); + + uint32_t i = 0; + while (i + sizeof(uint32_t) <= _size) { + uint32_t its_client_size; + std::memcpy(&its_client_size, &_data[i], sizeof(uint32_t)); + i += sizeof(uint32_t); + + if (i + sizeof(client_t) <= _size) { + client_t its_client; + std::memcpy(&its_client, &_data[i], sizeof(client_t)); + i += sizeof(client_t); + + if (its_client != client_) { + (void) find_or_create_local(its_client); + } else { + its_state = event_type_e::REGISTERED; + } + + if (i + sizeof(uint32_t) <= _size) { + uint32_t its_services_size; + std::memcpy(&its_services_size, &_data[i], sizeof(uint32_t)); + i += sizeof(uint32_t); + + uint32_t j = 0; + while (j + sizeof(service_t) + sizeof(instance_t) + <= its_services_size) { + service_t its_service; + std::memcpy(&its_service, &_data[i + j], sizeof(service_t)); + j += sizeof(service_t); + + instance_t its_instance; + std::memcpy(&its_instance, &_data[i + j], + sizeof(instance_t)); + j += sizeof(instance_t); + + if (its_client != client_) + local_services_[its_service][its_instance] = its_client; + } + + i += its_services_size; + } + } + } + + // inform host about its own registration state + host_->on_event(its_state); + + // Check for services that are no longer available + for (auto i : old_local_services) { + auto found_service = local_services_.find(i.first); + if (found_service != local_services_.end()) { + for (auto j : i.second) { + auto found_instance = found_service->second.find(j.first); + if (found_instance == found_service->second.end()) { + host_->on_availability(i.first, j.first, false); + } + } + } else { + for (auto j : i.second) { + host_->on_availability(i.first, j.first, false); + } + } + } + + // Check for services that are newly available + for (auto i : local_services_) { + auto found_service = old_local_services.find(i.first); + if (found_service != old_local_services.end()) { + for (auto j : i.second) { + auto found_instance = found_service->second.find(j.first); + if (found_instance == found_service->second.end()) { + host_->on_availability(i.first, j.first, true); + } + } + } else { + for (auto j : i.second) { + host_->on_availability(i.first, j.first, true); + } + } + } } bool routing_manager_proxy::is_available(service_t _service, - instance_t _instance) const { - auto found_local_service = local_services_.find(_service); - if (found_local_service != local_services_.end()) { - auto found_local_instance = found_local_service->second.find(_instance); - if (found_local_instance != found_local_service->second.end()) { - return true; - } - } - - // TODO: ask routing manager for external services - return false; + instance_t _instance) const { + auto found_local_service = local_services_.find(_service); + if (found_local_service != local_services_.end()) { + auto found_local_instance = found_local_service->second.find(_instance); + if (found_local_instance != found_local_service->second.end()) { + return (true); + } + } + + // TODO: ask routing manager for external services + return (false); } void routing_manager_proxy::register_application() { - byte_t its_command[] = { - VSOMEIP_REGISTER_APPLICATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + byte_t its_command[] = { + VSOMEIP_REGISTER_APPLICATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memset(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], 0, sizeof(uint32_t)); + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memset(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], 0, + sizeof(uint32_t)); - if (sender_) - sender_->send(its_command, sizeof(its_command)); + if (sender_) + sender_->send(its_command, sizeof(its_command)); } void routing_manager_proxy::deregister_application() { - uint32_t its_size = sizeof(client_); - - std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); - its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_DEREGISTER_APPLICATION; - std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_)); - std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, - sizeof(its_size)); - if (sender_) - sender_->send(&its_command[0], its_command.size()); + uint32_t its_size = sizeof(client_); + + std::vector<byte_t> its_command(VSOMEIP_COMMAND_HEADER_SIZE + its_size); + its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_DEREGISTER_APPLICATION; + std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_)); + std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size, + sizeof(its_size)); + if (sender_) + sender_->send(&its_command[0], its_command.size()); } std::shared_ptr<endpoint> routing_manager_proxy::find_local(client_t _client) { - std::shared_ptr<endpoint> its_endpoint; - auto found_endpoint = local_endpoints_.find(_client); - if (found_endpoint != local_endpoints_.end()) { - its_endpoint = found_endpoint->second; - } - return its_endpoint; + std::shared_ptr<endpoint> its_endpoint; + auto found_endpoint = local_endpoints_.find(_client); + if (found_endpoint != local_endpoints_.end()) { + its_endpoint = found_endpoint->second; + } + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_proxy::create_local( - client_t _client) { - std::stringstream its_path; - its_path << base_path << std::hex << _client; + client_t _client) { + std::stringstream its_path; + its_path << base_path << std::hex << _client; - VSOMEIP_DEBUG<< "Connecting to [" << std::hex << _client - << "] at " << its_path.str(); + VSOMEIP_DEBUG<< "Connecting to [" << std::hex << _client + << "] at " << its_path.str(); - std::shared_ptr<endpoint> its_endpoint = std::make_shared< - local_client_endpoint_impl>( - shared_from_this(), - boost::asio::local::stream_protocol::endpoint(its_path.str()), io_); + std::shared_ptr<endpoint> its_endpoint = std::make_shared< + local_client_endpoint_impl>(shared_from_this(), + boost::asio::local::stream_protocol::endpoint(its_path.str()), io_); - local_endpoints_[_client] = its_endpoint; + local_endpoints_[_client] = its_endpoint; - return its_endpoint; + return (its_endpoint); } std::shared_ptr<endpoint> routing_manager_proxy::find_or_create_local( - client_t _client) { - std::shared_ptr<endpoint> its_endpoint(find_local(_client)); - if (0 == its_endpoint) { - its_endpoint = create_local(_client); - its_endpoint->start(); - } - return its_endpoint; + client_t _client) { + std::shared_ptr<endpoint> its_endpoint(find_local(_client)); + if (0 == its_endpoint) { + its_endpoint = create_local(_client); + its_endpoint->start(); + } + return (its_endpoint); } void routing_manager_proxy::remove_local(client_t _client) { - std::shared_ptr<endpoint> its_endpoint(find_local(_client)); - if (its_endpoint) - its_endpoint->stop(); - local_endpoints_.erase(_client); + std::shared_ptr<endpoint> its_endpoint(find_local(_client)); + if (its_endpoint) + its_endpoint->stop(); + local_endpoints_.erase(_client); } -std::shared_ptr<endpoint> routing_manager_proxy::find_local( - service_t _service, instance_t _instance) { - client_t its_client(0); - auto found_service = local_services_.find(_service); - if (found_service != local_services_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - its_client = found_instance->second; - } - } - return find_local(its_client); +std::shared_ptr<endpoint> routing_manager_proxy::find_local(service_t _service, + instance_t _instance) { + client_t its_client(0); + auto found_service = local_services_.find(_service); + if (found_service != local_services_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + its_client = found_instance->second; + } + } + return (find_local(its_client)); } bool routing_manager_proxy::is_request(byte_t _message_type) const { - message_type_e its_type = static_cast<message_type_e>(_message_type); - return (its_type < message_type_e::NOTIFICATION - || its_type == message_type_e::REQUEST_ACK - || its_type == message_type_e::REQUEST_NO_RETURN_ACK); + message_type_e its_type = static_cast<message_type_e>(_message_type); + return (its_type < message_type_e::NOTIFICATION + || its_type == message_type_e::REQUEST_ACK + || its_type == message_type_e::REQUEST_NO_RETURN_ACK); } void routing_manager_proxy::send_pong() const { - byte_t its_pong[] = { - VSOMEIP_PONG, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + byte_t its_pong[] = { + VSOMEIP_PONG, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - std::memcpy(&its_pong[VSOMEIP_COMMAND_CLIENT_POS], &client_, - sizeof(client_t)); + std::memcpy(&its_pong[VSOMEIP_COMMAND_CLIENT_POS], &client_, + sizeof(client_t)); - if (sender_) - sender_->send(its_pong, sizeof(its_pong)); + if (sender_) + sender_->send(its_pong, sizeof(its_pong)); } } // namespace vsomeip diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp index c8dd00a..ec1d2f1 100644 --- a/implementation/routing/src/routing_manager_stub.cpp +++ b/implementation/routing/src/routing_manager_stub.cpp @@ -82,6 +82,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) { byte_t its_command; client_t its_client; + session_t its_session; std::string its_client_endpoint; service_t its_service; instance_t its_instance; @@ -99,6 +100,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, its_command = _data[VSOMEIP_COMMAND_TYPE_POS]; std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], sizeof(its_client)); + // TODO: read session std::memcpy(&its_size, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN], sizeof(its_size)); @@ -173,7 +175,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size, case VSOMEIP_SET: its_data = &_data[VSOMEIP_COMMAND_PAYLOAD_POS]; its_payload = runtime::get()->create_payload(its_data, its_size); - routing_->set(its_client, its_service, its_instance, its_event, + routing_->set(its_client, its_session, its_service, its_instance, its_event, its_payload); break; } diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp index b2faad0..799650d 100644 --- a/implementation/runtime/include/application_impl.hpp +++ b/implementation/runtime/include/application_impl.hpp @@ -53,6 +53,8 @@ public: bool is_available(service_t _service, instance_t _instance); void send(std::shared_ptr<message> _message, bool _flush, bool _reliable); + + void get(service_t _service, instance_t, event_t _event); void set(service_t _service, instance_t _instance, event_t _event, const std::shared_ptr<payload> &_payload); @@ -77,7 +79,7 @@ public: void on_event(event_type_e _event); void on_availability(service_t _service, instance_t _instance, - bool _is_available) const; + bool _is_available) const; void on_message(std::shared_ptr<message> _message); void on_error(error_code_e _error); @@ -86,6 +88,12 @@ public: private: void service(boost::asio::io_service &_io); + inline void update_session() { + session_++; + if (0 == session_) { + session_++; + } + } private: client_t client_; // unique application identifier diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp index 9f2053c..2040ffb 100644 --- a/implementation/runtime/include/runtime_impl.hpp +++ b/implementation/runtime/include/runtime_impl.hpp @@ -20,10 +20,10 @@ public: std::shared_ptr<application> create_application( const std::string &_name) const; + std::shared_ptr<message> create_message() const; std::shared_ptr<message> create_request() const; std::shared_ptr<message> create_response( const std::shared_ptr<message> &_request) const; - std::shared_ptr<message> create_notification() const; std::shared_ptr<payload> create_payload() const; diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp index ba6ff38..78ed2fb 100644 --- a/implementation/runtime/src/application_impl.cpp +++ b/implementation/runtime/src/application_impl.cpp @@ -170,19 +170,27 @@ void application_impl::send(std::shared_ptr<message> _message, bool _flush, // in case of successful sending, increment the session-id if (routing_->send(client_, _message, _flush, _reliable)) { if (is_request) { - session_++; - if (0 == session_) { - session_++; - } + update_session(); } } } } +void application_impl::get(service_t _service, instance_t _instance, event_t _event) { + if (routing_) { + if (routing_->get(client_, session_, _service, _instance, _event)) { + update_session(); + } + } +} + void application_impl::set(service_t _service, instance_t _instance, event_t _event, const std::shared_ptr<payload> &_payload) { - if (routing_) - routing_->set(client_, _service, _instance, _event, _payload); + if (routing_) { + if (routing_->set(client_, session_, _service, _instance, _event, _payload)) { + update_session(); + } + } } void application_impl::register_event_handler(event_handler_t _handler) { diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp index 10ed87e..7c8491a 100644 --- a/implementation/runtime/src/runtime_impl.cpp +++ b/implementation/runtime/src/runtime_impl.cpp @@ -15,7 +15,7 @@ namespace vsomeip { runtime * runtime_impl::get() { static runtime_impl the_runtime; - return &the_runtime; + return (&the_runtime); } runtime_impl::~runtime_impl() { @@ -23,7 +23,15 @@ runtime_impl::~runtime_impl() { std::shared_ptr<application> runtime_impl::create_application( const std::string &_name) const { - return std::make_shared < application_impl > (_name); + return (std::make_shared < application_impl > (_name)); +} + +std::shared_ptr<message> runtime_impl::create_message() const { + std::shared_ptr<message_impl> its_message = + std::make_shared<message_impl>(); + its_message->set_protocol_version(VSOMEIP_PROTOCOL_VERSION); + its_message->set_return_code(return_code_e::E_OK); + return (its_message); } std::shared_ptr<message> runtime_impl::create_request() const { @@ -32,7 +40,7 @@ std::shared_ptr<message> runtime_impl::create_request() const { its_request->set_protocol_version(VSOMEIP_PROTOCOL_VERSION); its_request->set_message_type(message_type_e::REQUEST); its_request->set_return_code(return_code_e::E_OK); - return its_request; + return (its_request); } std::shared_ptr<message> runtime_impl::create_response( @@ -47,30 +55,30 @@ std::shared_ptr<message> runtime_impl::create_response( its_response->set_interface_version(_request->get_interface_version()); its_response->set_message_type(message_type_e::RESPONSE); its_response->set_return_code(return_code_e::E_OK); - return its_response; + return (its_response); } std::shared_ptr<message> runtime_impl::create_notification() const { - std::shared_ptr<message_impl> its_request = + std::shared_ptr<message_impl> its_notification = std::make_shared<message_impl>(); - its_request->set_protocol_version(VSOMEIP_PROTOCOL_VERSION); - its_request->set_message_type(message_type_e::NOTIFICATION); - its_request->set_return_code(return_code_e::E_OK); - return its_request; + its_notification->set_protocol_version(VSOMEIP_PROTOCOL_VERSION); + its_notification->set_message_type(message_type_e::NOTIFICATION); + its_notification->set_return_code(return_code_e::E_OK); + return (its_notification); } std::shared_ptr<payload> runtime_impl::create_payload() const { - return std::make_shared<payload_impl>(); + return (std::make_shared<payload_impl>()); } std::shared_ptr<payload> runtime_impl::create_payload( const byte_t *_data, uint32_t _size) const { - return std::make_shared<payload_impl>(_data, _size); + return (std::make_shared<payload_impl>(_data, _size)); } std::shared_ptr<payload> runtime_impl::create_payload( const std::vector<byte_t> &_data) const { - return std::make_shared<payload_impl>(_data); + return (std::make_shared<payload_impl>(_data)); } } // namespace vsomeip diff --git a/implementation/service_discovery/include/fsm_events.hpp b/implementation/service_discovery/include/fsm_events.hpp index c498ee0..0d1dcc1 100644 --- a/implementation/service_discovery/include/fsm_events.hpp +++ b/implementation/service_discovery/include/fsm_events.hpp @@ -16,31 +16,42 @@ namespace sc = boost::statechart; namespace vsomeip { namespace sd { -struct ev_none: sc::event< ev_none > {}; -struct ev_timeout: sc::event< ev_timeout > {}; - -struct ev_status_change: sc::event< ev_status_change > { - ev_status_change(bool _is_up) : is_up_(_is_up) {}; +struct ev_none : sc::event<ev_none> { +}; - bool is_up_; +struct ev_timeout : sc::event<ev_timeout> { }; -struct ev_find_service: sc::event< ev_find_service > { +struct ev_status_change : sc::event<ev_status_change> { + ev_status_change(bool _is_up) + : is_up_(_is_up) { + } - ev_find_service(service_t _service, instance_t _instance, - major_version_t _major, minor_version_t _minor, ttl_t _ttl) - : service_(_service), instance_(_instance), - major_(_major), minor_(_minor), ttl_(_ttl) { - } + bool is_up_; +}; + +struct ev_find_service : sc::event<ev_find_service> { + + ev_find_service(service_t _service, instance_t _instance, + major_version_t _major, minor_version_t _minor, ttl_t _ttl) + : service_(_service), + instance_(_instance), + major_(_major), + minor_(_minor), + ttl_(_ttl) { + } + + service_t service_; + instance_t instance_; + major_version_t major_; + minor_version_t minor_; + ttl_t ttl_; +}; - service_t service_; - instance_t instance_; - major_version_t major_; - minor_version_t minor_; - ttl_t ttl_; +struct ev_offer_change : sc::event<ev_offer_change> { }; -} // namespace sd -} // namespace vsomeip +} // namespace sd +} // namespace vsomeip #endif // VSOMEIP_FSM_EVENTS_HPP diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp index 47455a0..6ab6460 100644 --- a/implementation/service_discovery/include/service_discovery.hpp +++ b/implementation/service_discovery/include/service_discovery.hpp @@ -40,6 +40,8 @@ public: virtual void send(const std::string &_name, bool _is_announcing) = 0; virtual void on_message(const byte_t *_data, length_t _length) = 0; + + virtual void on_offer_change(const std::string &_name) = 0; }; } // namespace sd diff --git a/implementation/service_discovery/include/service_discovery_fsm.hpp b/implementation/service_discovery/include/service_discovery_fsm.hpp index e5663be..54fd042 100644 --- a/implementation/service_discovery/include/service_discovery_fsm.hpp +++ b/implementation/service_discovery/include/service_discovery_fsm.hpp @@ -110,6 +110,7 @@ struct announce: sc::state< announce, active > { sc::result react(const ev_timeout &_event); sc::result react(const ev_find_service &_event); + sc::result react(const ev_offer_change &_event); }; } // namespace _offer diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp index 84e5297..24eecdb 100644 --- a/implementation/service_discovery/include/service_discovery_host.hpp +++ b/implementation/service_discovery/include/service_discovery_host.hpp @@ -42,8 +42,8 @@ class service_discovery_host { virtual bool send(client_t _client, std::shared_ptr<message> _message, bool _flush, bool _reliable) = 0; - virtual bool send_to(const boost::asio::ip::address &_address, uint16_t _port, - bool _reliable, const byte_t *_data, uint32_t _size) = 0; + virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target, + const byte_t *_data, uint32_t _size) = 0; virtual void add_routing_info(service_t _service, instance_t _instance, major_version_t _major, minor_version_t _minor, @@ -55,6 +55,7 @@ class service_discovery_host { bool _reliable) = 0; virtual void on_subscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<endpoint_definition> _subscriber, std::shared_ptr<endpoint_definition> _target) = 0; virtual void on_unsubscribe(service_t _service, instance_t _instance, eventgroup_t _eventgroup, diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp index 4279cbf..0013ac4 100644 --- a/implementation/service_discovery/include/service_discovery_impl.hpp +++ b/implementation/service_discovery/include/service_discovery_impl.hpp @@ -62,6 +62,8 @@ class service_discovery_impl : public service_discovery, void on_message(const byte_t *_data, length_t _length); + void on_offer_change(const std::string &_name); + private: session_t get_session(const boost::asio::ip::address &_address); void increment_session(const boost::asio::ip::address &_address); @@ -77,13 +79,11 @@ class service_discovery_impl : public service_discovery, void insert_subscription(std::shared_ptr<message_impl> &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<subscription> &_subscription, - bool _is_subscription); + std::shared_ptr<subscription> &_subscription); void insert_subscription_ack(std::shared_ptr<message_impl> &_message, service_t _service, instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<eventgroupinfo> &_info, - bool _is_subscription); + std::shared_ptr<eventgroupinfo> &_info); void process_serviceentry( std::shared_ptr<serviceentry_impl> &_entry, diff --git a/implementation/service_discovery/src/service_discovery_fsm.cpp b/implementation/service_discovery/src/service_discovery_fsm.cpp index 2f9f986..7f53cb0 100644 --- a/implementation/service_discovery/src/service_discovery_fsm.cpp +++ b/implementation/service_discovery/src/service_discovery_fsm.cpp @@ -131,6 +131,10 @@ sc::result announce::react(const ev_find_service &_event) { return discard_event(); } +sc::result announce::react(const ev_offer_change &_event) { + return transit< announce >(); +} + } // namespace _sd /////////////////////////////////////////////////////////////////////////////// diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp index fc63632..9b4fd61 100644 --- a/implementation/service_discovery/src/service_discovery_impl.cpp +++ b/implementation/service_discovery/src/service_discovery_impl.cpp @@ -35,660 +35,698 @@ namespace vsomeip { namespace sd { -service_discovery_impl::service_discovery_impl(service_discovery_host *_host) - : host_(_host), - io_(_host->get_io()), - default_(std::make_shared < service_discovery_fsm > ("default", this)), - serializer_(std::make_shared<serializer>()), - deserializer_(std::make_shared<deserializer>()) { +service_discovery_impl::service_discovery_impl(service_discovery_host *_host) : + host_(_host), io_(_host->get_io()), default_( + std::make_shared<service_discovery_fsm>("default", this)), serializer_( + std::make_shared<serializer>()), deserializer_( + std::make_shared<deserializer>()) { } service_discovery_impl::~service_discovery_impl() { } std::shared_ptr<configuration> service_discovery_impl::get_configuration() const { - return host_->get_configuration(); + return host_->get_configuration(); } boost::asio::io_service & service_discovery_impl::get_io() { - return io_; + return io_; } void service_discovery_impl::init() { - std::shared_ptr<configuration> its_configuration = host_->get_configuration(); - if (its_configuration) { - unicast_ = its_configuration->get_unicast(); - - std::set < std::string > its_servicegroups = its_configuration - ->get_servicegroups(); - for (auto its_group : its_servicegroups) { - if (its_group != "default" - && its_configuration->is_local_servicegroup(its_group)) { - additional_[its_group] = std::make_shared < service_discovery_fsm - > (its_group, this); - } - } - - port_ = its_configuration->get_service_discovery_port(); - reliable_ = (its_configuration->get_service_discovery_protocol() == "tcp"); - - serializer_->create_data(reliable_ ? - VSOMEIP_MAX_TCP_MESSAGE_SIZE : - VSOMEIP_MAX_UDP_MESSAGE_SIZE); - - host_->create_service_discovery_endpoint( - its_configuration->get_service_discovery_multicast(), port_, reliable_); - - } else { - VSOMEIP_ERROR << "SD: no configuration found!"; - } + std::shared_ptr<configuration> its_configuration = + host_->get_configuration(); + if (its_configuration) { + unicast_ = its_configuration->get_unicast(); + + std::set<std::string> its_servicegroups = + its_configuration->get_servicegroups(); + for (auto its_group : its_servicegroups) { + if (its_group != "default" + && its_configuration->is_local_servicegroup(its_group)) { + additional_[its_group] = + std::make_shared<service_discovery_fsm>(its_group, + this); + } + } + + port_ = its_configuration->get_service_discovery_port(); + reliable_ = (its_configuration->get_service_discovery_protocol() + == "tcp"); + + serializer_->create_data(reliable_ ? + VSOMEIP_MAX_TCP_MESSAGE_SIZE : + VSOMEIP_MAX_UDP_MESSAGE_SIZE); + + host_->create_service_discovery_endpoint( + its_configuration->get_service_discovery_multicast(), port_, + reliable_); + + } else { + VSOMEIP_ERROR<< "SD: no configuration found!"; + } } void service_discovery_impl::start() { - default_->start(); - for (auto &its_group : additional_) { - its_group.second->start(); - } - - default_->process(ev_none()); - for (auto &its_group : additional_) { - its_group.second->process(ev_none()); - } + default_->start(); + for (auto &its_group : additional_) { + its_group.second->start(); + } + + default_->process(ev_none()); + for (auto &its_group : additional_) { + its_group.second->process(ev_none()); + } } void service_discovery_impl::stop() { } void service_discovery_impl::request_service(service_t _service, - instance_t _instance, - major_version_t _major, - minor_version_t _minor, - ttl_t _ttl) { - auto find_service = requested_.find(_service); - if (find_service != requested_.end()) { - auto find_instance = find_service->second.find(_instance); - if (find_instance != find_service->second.end()) { - // TODO: check version and report errors - } else { - find_service->second[_instance] - = std::make_shared<request>(_major, _minor, _ttl); - } - } else { - requested_[_service][_instance] - = std::make_shared<request>(_major, _minor, _ttl); - } + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl) { + auto find_service = requested_.find(_service); + if (find_service != requested_.end()) { + auto find_instance = find_service->second.find(_instance); + if (find_instance != find_service->second.end()) { + // TODO: check version and report errors + } else { + find_service->second[_instance] = std::make_shared<request>(_major, + _minor, _ttl); + } + } else { + requested_[_service][_instance] = std::make_shared<request>(_major, + _minor, _ttl); + } } void service_discovery_impl::release_service(service_t _service, - instance_t _instance) { - auto find_service = requested_.find(_service); - if (find_service != requested_.end()) { - find_service->second.erase(_instance); - } + instance_t _instance) { + auto find_service = requested_.find(_service); + if (find_service != requested_.end()) { + find_service->second.erase(_instance); + } } void service_discovery_impl::subscribe(service_t _service, instance_t _instance, - eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl) { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - if (found_eventgroup->second->get_major() == _major) { - found_eventgroup->second->set_ttl(_ttl); - } else { - VSOMEIP_ERROR << "Subscriptions to different versions of the same " - "service instance are not supported!"; - } - return; - } - } - } - - std::shared_ptr<endpoint> its_reliable - = host_->find_remote_client(_service, _instance, true); - std::shared_ptr<endpoint> its_unreliable - = host_->find_remote_client(_service, _instance, false); - std::shared_ptr<subscription> its_subscription - = std::make_shared<subscription>(_major, _ttl, - its_reliable, its_unreliable); - subscribed_[_service][_instance][_eventgroup] = its_subscription; + eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl) { + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + if (found_eventgroup->second->get_major() == _major) { + found_eventgroup->second->set_ttl(_ttl); + } else { + VSOMEIP_ERROR<< "Subscriptions to different versions of the same " + "service instance are not supported!"; + } + return; + } + } + } + + std::shared_ptr<endpoint> its_reliable = host_->find_remote_client(_service, + _instance, true); + std::shared_ptr<endpoint> its_unreliable = host_->find_remote_client( + _service, _instance, false); + std::shared_ptr<subscription> its_subscription = std::make_shared< + subscription>(_major, _ttl, its_reliable, its_unreliable); + subscribed_[_service][_instance][_eventgroup] = its_subscription; } void service_discovery_impl::unsubscribe(service_t _service, - instance_t _instance, - eventgroup_t _eventgroup) { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - found_eventgroup->second->set_ttl(0); // is read once and removed afterwards! - } - } - } + instance_t _instance, eventgroup_t _eventgroup) { + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + found_eventgroup->second->set_ttl(0); // is read once and removed afterwards! + } + } + } } -session_t service_discovery_impl::get_session(const boost::asio::ip::address &_address) { - session_t its_session; - auto found_session = sessions_.find(_address); - if (found_session == sessions_.end()) { - its_session = sessions_[_address] = 1; - } else { - its_session = found_session->second; - } - return its_session; +session_t service_discovery_impl::get_session( + const boost::asio::ip::address &_address) { + session_t its_session; + auto found_session = sessions_.find(_address); + if (found_session == sessions_.end()) { + its_session = sessions_[_address] = 1; + } else { + its_session = found_session->second; + } + return its_session; } -void service_discovery_impl::increment_session(const boost::asio::ip::address &_address) { - auto found_session = sessions_.find(_address); - if (found_session != sessions_.end()) { - found_session->second ++; - if (0 == found_session->second) { +void service_discovery_impl::increment_session( + const boost::asio::ip::address &_address) { + auto found_session = sessions_.find(_address); + if (found_session != sessions_.end()) { found_session->second++; - // TODO: what about the reboot flag? - } - } + if (0 == found_session->second) { + found_session->second++; + // TODO: what about the reboot flag? + } + } } void service_discovery_impl::insert_option( - std::shared_ptr<message_impl> &_message, std::shared_ptr<entry_impl> _entry, - const boost::asio::ip::address &_address, uint16_t _port, bool _is_reliable) { - if (unicast_ == _address) { - if (unicast_.is_v4()) { - ipv4_address_t its_address = unicast_.to_v4().to_bytes(); - std::shared_ptr<ipv4_option_impl> its_option - = _message->create_ipv4_option(false); - if (its_option) { - its_option->set_address(its_address); - its_option->set_port(_port); - its_option->set_udp(!_is_reliable); - _entry->assign_option(its_option, 1); - } - } else { - ipv6_address_t its_address = unicast_.to_v6().to_bytes(); - std::shared_ptr<ipv6_option_impl> its_option - = _message->create_ipv6_option(false); - if (its_option) { - its_option->set_address(its_address); - its_option->set_port(_port); - its_option->set_udp(!_is_reliable); - _entry->assign_option(its_option, 1); - } - } - } else { - if (_address.is_v4()) { - ipv4_address_t its_address = _address.to_v4().to_bytes(); - std::shared_ptr<ipv4_option_impl> its_option - = _message->create_ipv4_option(true); - if (its_option) { - its_option->set_address(its_address); - its_option->set_port(_port); - _entry->assign_option(its_option, 1); - } - } else { - ipv6_address_t its_address = _address.to_v6().to_bytes(); - std::shared_ptr<ipv6_option_impl> its_option - = _message->create_ipv6_option(true); - if (its_option) { - its_option->set_address(its_address); - its_option->set_port(_port); - _entry->assign_option(its_option, 1); - } - } - } + std::shared_ptr<message_impl> &_message, + std::shared_ptr<entry_impl> _entry, + const boost::asio::ip::address &_address, uint16_t _port, + bool _is_reliable) { + if (unicast_ == _address) { + if (unicast_.is_v4()) { + ipv4_address_t its_address = unicast_.to_v4().to_bytes(); + std::shared_ptr<ipv4_option_impl> its_option = + _message->create_ipv4_option(false); + if (its_option) { + its_option->set_address(its_address); + its_option->set_port(_port); + its_option->set_udp(!_is_reliable); + _entry->assign_option(its_option, 1); + } + } else { + ipv6_address_t its_address = unicast_.to_v6().to_bytes(); + std::shared_ptr<ipv6_option_impl> its_option = + _message->create_ipv6_option(false); + if (its_option) { + its_option->set_address(its_address); + its_option->set_port(_port); + its_option->set_udp(!_is_reliable); + _entry->assign_option(its_option, 1); + } + } + } else { + if (_address.is_v4()) { + ipv4_address_t its_address = _address.to_v4().to_bytes(); + std::shared_ptr<ipv4_option_impl> its_option = + _message->create_ipv4_option(true); + if (its_option) { + its_option->set_address(its_address); + its_option->set_port(_port); + _entry->assign_option(its_option, 1); + } + } else { + ipv6_address_t its_address = _address.to_v6().to_bytes(); + std::shared_ptr<ipv6_option_impl> its_option = + _message->create_ipv6_option(true); + if (its_option) { + its_option->set_address(its_address); + its_option->set_port(_port); + _entry->assign_option(its_option, 1); + } + } + } } void service_discovery_impl::insert_find_entries( - std::shared_ptr<message_impl> &_message, requests_t &_requests) { - for (auto its_service : _requests) { - for (auto its_instance : its_service.second) { - auto its_request = its_instance.second; - std::shared_ptr<serviceentry_impl> its_entry - = _message->create_service_entry(); - if (its_entry) { - its_entry->set_type(entry_type_e::FIND_SERVICE); - its_entry->set_service(its_service.first); - its_entry->set_instance(its_instance.first); - its_entry->set_major_version(its_request->get_major()); - its_entry->set_minor_version(its_request->get_minor()); - its_entry->set_ttl(its_request->get_ttl()); - } else { - VSOMEIP_ERROR << "Failed to create service entry!"; - } + std::shared_ptr<message_impl> &_message, requests_t &_requests) { + for (auto its_service : _requests) { + for (auto its_instance : its_service.second) { + auto its_request = its_instance.second; + std::shared_ptr<serviceentry_impl> its_entry = + _message->create_service_entry(); + if (its_entry) { + its_entry->set_type(entry_type_e::FIND_SERVICE); + its_entry->set_service(its_service.first); + its_entry->set_instance(its_instance.first); + its_entry->set_major_version(its_request->get_major()); + its_entry->set_minor_version(its_request->get_minor()); + its_entry->set_ttl(its_request->get_ttl()); + } else { + VSOMEIP_ERROR<< "Failed to create service entry!"; + } + } } - } } void service_discovery_impl::insert_offer_entries( - std::shared_ptr<message_impl> &_message, services_t &_services) { - for (auto its_service : _services) { - for (auto its_instance : its_service.second) { - auto its_info = its_instance.second; - std::shared_ptr<serviceentry_impl> its_entry = _message - ->create_service_entry(); - if (its_entry) { - its_entry->set_type(entry_type_e::OFFER_SERVICE); - its_entry->set_service(its_service.first); - its_entry->set_instance(its_instance.first); - its_entry->set_major_version(its_info->get_major()); - its_entry->set_minor_version(its_info->get_minor()); - its_entry->set_ttl(its_info->get_ttl()); - - std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(true); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), true); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, its_instance.first, - true); - } - } - - its_endpoint = its_info->get_endpoint(false); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), false); - if (0 == its_info->get_ttl()) { - host_->del_routing_info(its_service.first, its_instance.first, - false); - } - } - } else { - VSOMEIP_ERROR << "Failed to create service entry."; - } - } - } + std::shared_ptr<message_impl> &_message, services_t &_services) { + for (auto its_service : _services) { + for (auto its_instance : its_service.second) { + auto its_info = its_instance.second; + std::shared_ptr<serviceentry_impl> its_entry = + _message->create_service_entry(); + if (its_entry) { + its_entry->set_type(entry_type_e::OFFER_SERVICE); + its_entry->set_service(its_service.first); + its_entry->set_instance(its_instance.first); + its_entry->set_major_version(its_info->get_major()); + its_entry->set_minor_version(its_info->get_minor()); + its_entry->set_ttl(its_info->get_ttl()); + + std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint( + true); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_port(), true); + if (0 == its_info->get_ttl()) { + host_->del_routing_info(its_service.first, + its_instance.first, + true); + } + } + + its_endpoint = its_info->get_endpoint(false); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, + its_endpoint->get_port(), false); + if (0 == its_info->get_ttl()) { + host_->del_routing_info(its_service.first, + its_instance.first, + false); + } + } + } else { + VSOMEIP_ERROR<< "Failed to create service entry."; + } + } + } } void service_discovery_impl::insert_subscription( - std::shared_ptr<message_impl> &_message, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<subscription> &_subscription, bool _is_subscription) { - std::shared_ptr<eventgroupentry_impl> its_entry = _message - ->create_eventgroup_entry(); - its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP); - its_entry->set_service(_service); - its_entry->set_instance(_instance); - its_entry->set_eventgroup(_eventgroup); - its_entry->set_major_version(_subscription->get_major()); - its_entry->set_ttl(_subscription->get_ttl()); - std::shared_ptr<endpoint> its_endpoint = _subscription->get_endpoint(true); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), true); - } - its_endpoint = _subscription->get_endpoint(false); - if (its_endpoint) { - insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), false); - } + std::shared_ptr<message_impl> &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<subscription> &_subscription) { + std::shared_ptr<eventgroupentry_impl> its_entry = + _message->create_eventgroup_entry(); + its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_eventgroup(_eventgroup); + its_entry->set_major_version(_subscription->get_major()); + its_entry->set_ttl(_subscription->get_ttl()); + std::shared_ptr<endpoint> its_endpoint = _subscription->get_endpoint(true); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), + true); + } + its_endpoint = _subscription->get_endpoint(false); + if (its_endpoint) { + insert_option(_message, its_entry, unicast_, its_endpoint->get_port(), + false); + } } void service_discovery_impl::insert_subscription_ack( - std::shared_ptr<message_impl> &_message, service_t _service, - instance_t _instance, eventgroup_t _eventgroup, - std::shared_ptr<eventgroupinfo> &_info, bool _is_subscription) { - std::shared_ptr<eventgroupentry_impl> its_entry - = _message->create_eventgroup_entry(); - its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK); - its_entry->set_service(_service); - its_entry->set_instance(_instance); - its_entry->set_eventgroup(_eventgroup); - its_entry->set_major_version(_info->get_major()); - its_entry->set_ttl(_info->get_ttl()); - - boost::asio::ip::address its_address; - uint16_t its_port; - if (_info->get_multicast(its_address, its_port)) { - insert_option(_message, its_entry, its_address, its_port, false); - } + std::shared_ptr<message_impl> &_message, service_t _service, + instance_t _instance, eventgroup_t _eventgroup, + std::shared_ptr<eventgroupinfo> &_info) { + std::shared_ptr<eventgroupentry_impl> its_entry = + _message->create_eventgroup_entry(); + its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK); + its_entry->set_service(_service); + its_entry->set_instance(_instance); + its_entry->set_eventgroup(_eventgroup); + its_entry->set_major_version(_info->get_major()); + its_entry->set_ttl(_info->get_ttl()); + + boost::asio::ip::address its_address; + uint16_t its_port; + if (_info->get_multicast(its_address, its_port)) { + insert_option(_message, its_entry, its_address, its_port, false); + } } void service_discovery_impl::send(const std::string &_name, - bool _is_announcing) { - std::shared_ptr<message_impl> its_message = runtime::get()->create_message(); - - // TODO: optimize building of SD message (common options, utilize the two runs) - - // If we are the default group and not in main phase, include "FindOffer"-entries - if (_name == "default" && !_is_announcing) { - insert_find_entries(its_message, requested_); - } - - // Always include the "OfferService"-entries for the service group - services_t its_offers = host_->get_offered_services(_name); - insert_offer_entries(its_message, its_offers); - - // Serialize and send - if (its_message->get_entries().size() > 0) { - its_message->set_session(get_session(unicast_)); - if (host_->send(VSOMEIP_SD_CLIENT, its_message, true, false)) { - increment_session(unicast_); - } - } +bool _is_announcing) { + std::shared_ptr<message_impl> its_message = + runtime::get()->create_message(); + + // TODO: optimize building of SD message (common options, utilize the two runs) + + // If we are the default group and not in main phase, include "FindOffer"-entries + if (_name == "default" && !_is_announcing) { + insert_find_entries(its_message, requested_); + } + + // Always include the "OfferService"-entries for the service group + services_t its_offers = host_->get_offered_services(_name); + insert_offer_entries(its_message, its_offers); + + // Serialize and send + if (its_message->get_entries().size() > 0) { + its_message->set_session(get_session(unicast_)); + if (host_->send(VSOMEIP_SD_CLIENT, its_message, true, false)) { + increment_session(unicast_); + } + } } // Interface endpoint_host void service_discovery_impl::on_message(const byte_t *_data, length_t _length) { #if 0 - std::stringstream msg; - msg << "sdi::on_message: "; - for (length_t i = 0; i < _length; ++i) - msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; - VSOMEIP_DEBUG << msg.str(); + std::stringstream msg; + msg << "sdi::on_message: "; + for (length_t i = 0; i < _length; ++i) + msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " "; + VSOMEIP_DEBUG << msg.str(); #endif - deserializer_->set_data(_data, _length); - std::shared_ptr<message_impl> its_message( - deserializer_->deserialize_sd_message()); - if (its_message) { - std::vector < std::shared_ptr<option_impl> - > its_options = its_message->get_options(); - for (auto its_entry : its_message->get_entries()) { - if (its_entry->is_service_entry()) { - std::shared_ptr<serviceentry_impl> its_service_entry = - std::dynamic_pointer_cast < serviceentry_impl > (its_entry); - process_serviceentry(its_service_entry, its_options); - } else { - std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry = - std::dynamic_pointer_cast < eventgroupentry_impl > (its_entry); - process_eventgroupentry(its_eventgroup_entry, its_options); - } - } - } + deserializer_->set_data(_data, _length); + std::shared_ptr<message_impl> its_message( + deserializer_->deserialize_sd_message()); + if (its_message) { + std::vector<std::shared_ptr<option_impl> > its_options = + its_message->get_options(); + for (auto its_entry : its_message->get_entries()) { + if (its_entry->is_service_entry()) { + std::shared_ptr<serviceentry_impl> its_service_entry = + std::dynamic_pointer_cast<serviceentry_impl>(its_entry); + process_serviceentry(its_service_entry, its_options); + } else { + std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry = + std::dynamic_pointer_cast<eventgroupentry_impl>( + its_entry); + process_eventgroupentry(its_eventgroup_entry, its_options); + } + } + } +} + +void service_discovery_impl::on_offer_change(const std::string &_name) { + if (_name == "default") { + default_->process(ev_offer_change()); + } else { + auto found_group = additional_.find(_name); + if (found_group != additional_.end()) { + found_group->second->process(ev_offer_change()); + } + } } // Entry processing void service_discovery_impl::process_serviceentry( - std::shared_ptr<serviceentry_impl> &_entry, - const std::vector<std::shared_ptr<option_impl> > &_options) { - service_t its_service = _entry->get_service(); - instance_t its_instance = _entry->get_instance(); - major_version_t its_major = _entry->get_major_version(); - minor_version_t its_minor = _entry->get_minor_version(); - ttl_t its_ttl = _entry->get_ttl(); - - for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector<byte_t> its_option_address; - uint16_t its_option_port = VSOMEIP_INVALID_PORT; - std::shared_ptr<option_impl> its_option = _options[its_index]; - switch (its_option->get_type()) { - case option_type_e::IP4_ENDPOINT: { - std::shared_ptr<ipv4_option_impl> its_ipv4_option = - std::dynamic_pointer_cast < ipv4_option_impl > (its_option); - - boost::asio::ip::address_v4 its_ipv4_address( - its_ipv4_option->get_address()); - boost::asio::ip::address its_address(its_ipv4_address); - its_option_port = its_ipv4_option->get_port(); - - handle_service_availability(its_service, its_instance, its_major, - its_minor, its_ttl, its_address, - its_option_port, - !its_ipv4_option->is_udp()); - break; - } - case option_type_e::IP6_ENDPOINT: { - std::shared_ptr<ipv6_option_impl> its_ipv6_option = - std::dynamic_pointer_cast < ipv6_option_impl > (its_option); - - boost::asio::ip::address_v6 its_ipv6_address( - its_ipv6_option->get_address()); - boost::asio::ip::address its_address(its_ipv6_address); - its_option_port = its_ipv6_option->get_port(); - - handle_service_availability(its_service, its_instance, its_major, - its_minor, its_ttl, its_address, - its_option_port, - !its_ipv6_option->is_udp()); - break; - } - case option_type_e::IP4_MULTICAST: - case option_type_e::IP6_MULTICAST: - VSOMEIP_ERROR << "Invalid service option (Multicast)"; - break; - default: - VSOMEIP_WARNING << "Unsupported service option"; - break; - } - } - } + std::shared_ptr<serviceentry_impl> &_entry, + const std::vector<std::shared_ptr<option_impl> > &_options) { + service_t its_service = _entry->get_service(); + instance_t its_instance = _entry->get_instance(); + major_version_t its_major = _entry->get_major_version(); + minor_version_t its_minor = _entry->get_minor_version(); + ttl_t its_ttl = _entry->get_ttl(); + + for (auto i : { 1, 2 }) { + for (auto its_index : _entry->get_options(i)) { + std::vector<byte_t> its_option_address; + uint16_t its_option_port = VSOMEIP_INVALID_PORT; + std::shared_ptr<option_impl> its_option = _options[its_index]; + switch (its_option->get_type()) { + case option_type_e::IP4_ENDPOINT: { + std::shared_ptr<ipv4_option_impl> its_ipv4_option = + std::dynamic_pointer_cast<ipv4_option_impl>(its_option); + + boost::asio::ip::address_v4 its_ipv4_address( + its_ipv4_option->get_address()); + boost::asio::ip::address its_address(its_ipv4_address); + its_option_port = its_ipv4_option->get_port(); + + handle_service_availability(its_service, its_instance, + its_major, its_minor, its_ttl, its_address, + its_option_port, !its_ipv4_option->is_udp()); + break; + } + case option_type_e::IP6_ENDPOINT: { + std::shared_ptr<ipv6_option_impl> its_ipv6_option = + std::dynamic_pointer_cast<ipv6_option_impl>(its_option); + + boost::asio::ip::address_v6 its_ipv6_address( + its_ipv6_option->get_address()); + boost::asio::ip::address its_address(its_ipv6_address); + its_option_port = its_ipv6_option->get_port(); + + handle_service_availability(its_service, its_instance, + its_major, its_minor, its_ttl, its_address, + its_option_port, !its_ipv6_option->is_udp()); + break; + } + case option_type_e::IP4_MULTICAST: + case option_type_e::IP6_MULTICAST: + VSOMEIP_ERROR<< "Invalid service option (Multicast)"; + break; + default: + VSOMEIP_WARNING << "Unsupported service option"; + break; + } + } + } } void service_discovery_impl::process_eventgroupentry( - std::shared_ptr<eventgroupentry_impl> &_entry, - const std::vector<std::shared_ptr<option_impl> > &_options) { - service_t its_service = _entry->get_service(); - instance_t its_instance = _entry->get_instance(); - eventgroup_t its_eventgroup = _entry->get_eventgroup(); - entry_type_e its_type = _entry->get_type(); - major_version_t its_major = _entry->get_major_version(); - ttl_t its_ttl = _entry->get_ttl(); - - boost::asio::ip::address its_reliable_address; - uint16_t its_reliable_port = VSOMEIP_INVALID_PORT; - boost::asio::ip::address its_unreliable_address; - uint16_t its_unreliable_port = VSOMEIP_INVALID_PORT; - - for (auto i : { 1, 2 }) { - for (auto its_index : _entry->get_options(i)) { - std::vector<byte_t> its_option_address; - std::shared_ptr<option_impl> its_option = _options[its_index]; - switch (its_option->get_type()) { - case option_type_e::IP4_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { - std::shared_ptr<ipv4_option_impl> its_ipv4_option = - std::dynamic_pointer_cast < ipv4_option_impl > (its_option); - - boost::asio::ip::address_v4 its_ipv4_address( - its_ipv4_option->get_address()); - - // TODO: add error handling (port already set) here - if (its_ipv4_option->is_udp()) { - its_unreliable_address = its_ipv4_address; - its_unreliable_port = its_ipv4_option->get_port(); - } else { - its_reliable_address = its_ipv4_address; - its_reliable_port = its_ipv4_option->get_port(); - } - } else { - VSOMEIP_ERROR << "Invalid eventgroup option (IPv4 Endpoint)"; - } - break; - } - case option_type_e::IP6_ENDPOINT: { - if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { - std::shared_ptr<ipv6_option_impl> its_ipv6_option = - std::dynamic_pointer_cast < ipv6_option_impl > (its_option); - - boost::asio::ip::address_v6 its_ipv6_address( - its_ipv6_option->get_address()); - - // TODO: add error handling (port already set) here - if (its_ipv6_option->is_udp()) { - its_unreliable_address = its_ipv6_address; - its_unreliable_port = its_ipv6_option->get_port(); - } else { - its_unreliable_address = its_ipv6_address; - its_reliable_port = its_ipv6_option->get_port(); - } - } else { - VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Endpoint)"; - } - break; - } - case option_type_e::IP4_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) { - std::shared_ptr<ipv4_option_impl> its_ipv4_option = - std::dynamic_pointer_cast < ipv4_option_impl > (its_option); - - boost::asio::ip::address_v4 its_ipv4_address( - its_ipv4_option->get_address()); - - its_unreliable_address = its_ipv4_address; - its_unreliable_port = its_ipv4_option->get_port(); - } else { - VSOMEIP_ERROR << "Invalid eventgroup option (IPv4 Multicast)"; - } - break; - case option_type_e::IP6_MULTICAST: - if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) { - std::shared_ptr<ipv6_option_impl> its_ipv6_option = - std::dynamic_pointer_cast < ipv6_option_impl > (its_option); - - boost::asio::ip::address_v6 its_ipv6_address( - its_ipv6_option->get_address()); - - its_unreliable_address = its_ipv6_address; - its_unreliable_port = its_ipv6_option->get_port(); - } else { - VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Multicast)"; - } - break; - default: - VSOMEIP_WARNING << "Unsupported eventgroup option"; - break; - } - } - } - - if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { - handle_eventgroup_subscription( - its_service, - its_instance, - its_eventgroup, - its_major, - its_ttl, - (its_reliable_port != VSOMEIP_INVALID_PORT ? - its_reliable_address : its_unreliable_address), - its_reliable_port, its_unreliable_port); - } else { - handle_eventgroup_subscription_ack(its_service, its_instance, - its_eventgroup, its_major, its_ttl, - its_unreliable_address, - its_unreliable_port); - } + std::shared_ptr<eventgroupentry_impl> &_entry, + const std::vector<std::shared_ptr<option_impl> > &_options) { + service_t its_service = _entry->get_service(); + instance_t its_instance = _entry->get_instance(); + eventgroup_t its_eventgroup = _entry->get_eventgroup(); + entry_type_e its_type = _entry->get_type(); + major_version_t its_major = _entry->get_major_version(); + ttl_t its_ttl = _entry->get_ttl(); + + boost::asio::ip::address its_reliable_address; + uint16_t its_reliable_port = VSOMEIP_INVALID_PORT; + boost::asio::ip::address its_unreliable_address; + uint16_t its_unreliable_port = VSOMEIP_INVALID_PORT; + + for (auto i : { 1, 2 }) { + for (auto its_index : _entry->get_options(i)) { + std::vector<byte_t> its_option_address; + std::shared_ptr<option_impl> its_option = _options[its_index]; + switch (its_option->get_type()) { + case option_type_e::IP4_ENDPOINT: { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + std::shared_ptr<ipv4_option_impl> its_ipv4_option = + std::dynamic_pointer_cast<ipv4_option_impl>( + its_option); + + boost::asio::ip::address_v4 its_ipv4_address( + its_ipv4_option->get_address()); + + // TODO: add error handling (port already set) here + if (its_ipv4_option->is_udp()) { + its_unreliable_address = its_ipv4_address; + its_unreliable_port = its_ipv4_option->get_port(); + } else { + its_reliable_address = its_ipv4_address; + its_reliable_port = its_ipv4_option->get_port(); + } + } else { + VSOMEIP_ERROR<< "Invalid eventgroup option (IPv4 Endpoint)"; + } + break; + } + case option_type_e::IP6_ENDPOINT: { + if (entry_type_e::SUBSCRIBE_EVENTGROUP == _entry->get_type()) { + std::shared_ptr<ipv6_option_impl> its_ipv6_option = + std::dynamic_pointer_cast < ipv6_option_impl > (its_option); + + boost::asio::ip::address_v6 its_ipv6_address( + its_ipv6_option->get_address()); + + // TODO: add error handling (port already set) here + if (its_ipv6_option->is_udp()) { + its_unreliable_address = its_ipv6_address; + its_unreliable_port = its_ipv6_option->get_port(); + } else { + its_unreliable_address = its_ipv6_address; + its_reliable_port = its_ipv6_option->get_port(); + } + } else { + VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Endpoint)"; + } + break; + } + case option_type_e::IP4_MULTICAST: + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) { + std::shared_ptr<ipv4_option_impl> its_ipv4_option = + std::dynamic_pointer_cast < ipv4_option_impl > (its_option); + + boost::asio::ip::address_v4 its_ipv4_address( + its_ipv4_option->get_address()); + + its_unreliable_address = its_ipv4_address; + its_unreliable_port = its_ipv4_option->get_port(); + } else { + VSOMEIP_ERROR << "Invalid eventgroup option (IPv4 Multicast)"; + } + break; + case option_type_e::IP6_MULTICAST: + if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == _entry->get_type()) { + std::shared_ptr<ipv6_option_impl> its_ipv6_option = + std::dynamic_pointer_cast < ipv6_option_impl > (its_option); + + boost::asio::ip::address_v6 its_ipv6_address( + its_ipv6_option->get_address()); + + its_unreliable_address = its_ipv6_address; + its_unreliable_port = its_ipv6_option->get_port(); + } else { + VSOMEIP_ERROR << "Invalid eventgroup option (IPv6 Multicast)"; + } + break; + default: + VSOMEIP_WARNING << "Unsupported eventgroup option"; + break; + } + } +} + + if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) { + handle_eventgroup_subscription(its_service, its_instance, + its_eventgroup, its_major, its_ttl, + (its_reliable_port != VSOMEIP_INVALID_PORT ? + its_reliable_address : its_unreliable_address), + its_reliable_port, its_unreliable_port); + } else { + handle_eventgroup_subscription_ack(its_service, its_instance, + its_eventgroup, its_major, its_ttl, its_unreliable_address, + its_unreliable_port); + } } -void service_discovery_impl::handle_service_availability( - service_t _service, instance_t _instance, major_version_t _major, - minor_version_t _minor, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port, bool _reliable) { - - if (0 < _ttl) { - host_->add_routing_info(_service, _instance, _major, _minor, _ttl, _address, - _port, _reliable); - - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - if (0 < found_instance->second.size()) { - std::shared_ptr<message_impl> its_message = runtime::get() - ->create_message(); - for (auto its_eventgroup : found_instance->second) { - std::shared_ptr<subscription> its_subscription(its_eventgroup.second); - if (!its_subscription->is_acknowleged()) { - its_subscription->set_endpoint( - host_->find_remote_client(_service, _instance, true), true); - its_subscription->set_endpoint( - host_->find_remote_client(_service, _instance, false), false); - - // TODO: consume major & ttl - insert_subscription(its_message, _service, _instance, - its_eventgroup.first, its_subscription, true); - } - } - - if (0 < its_message->get_entries().size()) { - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to(_address, port_, reliable_, - serializer_->get_data(), serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); - } - } - } - } - } else { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - for (auto &its_eventgroup : found_instance->second) { - its_eventgroup.second->set_acknowledged(false); - } - } - } - host_->del_routing_info(_service, _instance, _reliable); - } +void service_discovery_impl::handle_service_availability(service_t _service, + instance_t _instance, major_version_t _major, minor_version_t _minor, + ttl_t _ttl, const boost::asio::ip::address &_address, uint16_t _port, + bool _reliable) { + + if (0 < _ttl) { + host_->add_routing_info(_service, _instance, _major, _minor, _ttl, + _address, _port, _reliable); + + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + if (0 < found_instance->second.size()) { + std::shared_ptr<message_impl> its_message = + runtime::get()->create_message(); + for (auto its_eventgroup : found_instance->second) { + std::shared_ptr<subscription> its_subscription( + its_eventgroup.second); + if (!its_subscription->is_acknowleged()) { + its_subscription->set_endpoint( + host_->find_remote_client(_service, + _instance, true), true); + its_subscription->set_endpoint( + host_->find_remote_client(_service, + _instance, false), false); + + // TODO: consume major & ttl + insert_subscription(its_message, _service, + _instance, its_eventgroup.first, + its_subscription); + } + } + + if (0 < its_message->get_entries().size()) { + its_message->set_session(get_session(_address)); + serializer_->serialize(its_message.get()); + if (host_->send_to( + std::make_shared<endpoint_definition>(_address, + port_, reliable_), + serializer_->get_data(), + serializer_->get_size())) { + increment_session(_address); + } + serializer_->reset(); + } + } + } + } + } else { + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + for (auto &its_eventgroup : found_instance->second) { + its_eventgroup.second->set_acknowledged(false); + } + } + } + host_->del_routing_info(_service, _instance, _reliable); + } } -void service_discovery_impl::handle_eventgroup_subscription( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _reliable_port, - uint16_t _unreliable_port) { - std::shared_ptr<message_impl> its_message = runtime::get()->create_message(); - if (its_message) { - std::shared_ptr<eventgroupinfo> its_info - = host_->find_eventgroup(_service, _instance, _eventgroup); - - // Could not find eventgroup --> send Nack - if (!its_info || _major > its_info->get_major() - || _ttl > its_info->get_ttl()) { - its_info = std::make_shared<eventgroupinfo>(_major, 0); - } else { - boost::asio::ip::address its_address; - uint16_t its_port; - bool its_reliable; - if (VSOMEIP_INVALID_PORT != _unreliable_port) { - if (!its_info->get_multicast(its_address, its_port)) { - its_address = _address; - its_port = _unreliable_port; - } - its_reliable = false; - } else { - its_address = _address; - its_port = _reliable_port; - its_reliable = true; - } - host_->on_subscribe(_service, _instance, _eventgroup, - std::make_shared<endpoint_definition>(its_address, its_port, its_reliable)); - } - - insert_subscription_ack(its_message, _service, _instance, _eventgroup, - its_info, false); - - its_message->set_session(get_session(_address)); - serializer_->serialize(its_message.get()); - if (host_->send_to(_address, port_, reliable_, - serializer_->get_data(), serializer_->get_size())) { - increment_session(_address); - } - serializer_->reset(); - } +void service_discovery_impl::handle_eventgroup_subscription(service_t _service, + instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, + ttl_t _ttl, const boost::asio::ip::address &_address, + uint16_t _reliable_port, uint16_t _unreliable_port) { + std::shared_ptr<message_impl> its_message = + runtime::get()->create_message(); + if (its_message) { + std::shared_ptr<eventgroupinfo> its_info = host_->find_eventgroup( + _service, _instance, _eventgroup); + + bool is_nack(false); + std::shared_ptr<endpoint_definition> its_subscriber; + std::shared_ptr<endpoint_definition> its_target; + + // Could not find eventgroup --> send Nack + if (!its_info || _major > its_info->get_major() + || _ttl > its_info->get_ttl()) { + its_info = std::make_shared<eventgroupinfo>(_major, 0); + is_nack = true; + } else { + boost::asio::ip::address its_target_address; + uint16_t its_target_port; + if (VSOMEIP_INVALID_PORT != _unreliable_port) { + its_subscriber = std::make_shared<endpoint_definition>( + _address, _unreliable_port, false); + if (!its_info->get_multicast(its_target_address, + its_target_port)) { + its_target = std::make_shared<endpoint_definition>( + its_target_address, its_target_port, false); + } else { + its_target = its_subscriber; + } + } else { + its_subscriber = std::make_shared<endpoint_definition>( + _address, _reliable_port, true); + its_target = its_subscriber; + } + } + + insert_subscription_ack(its_message, + _service, _instance, _eventgroup, its_info); + + its_message->set_session(get_session(_address)); + serializer_->serialize(its_message.get()); + if (host_->send_to( + std::make_shared<endpoint_definition>(_address, port_, + reliable_), serializer_->get_data(), + serializer_->get_size())) { + increment_session(_address); + } + serializer_->reset(); + + // Finally register the new subscriber and send him all the fields(!) + if (!is_nack) { + host_->on_subscribe(_service, _instance, _eventgroup, + its_subscriber, its_target); + } + } } void service_discovery_impl::handle_eventgroup_subscription_ack( - service_t _service, instance_t _instance, eventgroup_t _eventgroup, - major_version_t _major, ttl_t _ttl, - const boost::asio::ip::address &_address, uint16_t _port) { - auto found_service = subscribed_.find(_service); - if (found_service != subscribed_.end()) { - auto found_instance = found_service->second.find(_instance); - if (found_instance != found_service->second.end()) { - auto found_eventgroup = found_instance->second.find(_eventgroup); - if (found_eventgroup != found_instance->second.end()) { - found_eventgroup->second->set_acknowledged(true); - if (_address.is_multicast()) { - host_->on_subscribe_ack(_service, _instance, _address, _port); - } - } - } - } + service_t _service, instance_t _instance, eventgroup_t _eventgroup, + major_version_t _major, ttl_t _ttl, + const boost::asio::ip::address &_address, uint16_t _port) { + auto found_service = subscribed_.find(_service); + if (found_service != subscribed_.end()) { + auto found_instance = found_service->second.find(_instance); + if (found_instance != found_service->second.end()) { + auto found_eventgroup = found_instance->second.find(_eventgroup); + if (found_eventgroup != found_instance->second.end()) { + found_eventgroup->second->set_acknowledged(true); + if (_address.is_multicast()) { + host_->on_subscribe_ack(_service, _instance, _address, + _port); + } + } + } + } } } // namespace sd diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp index e9b4e9d..8ad1989 100644 --- a/implementation/utility/include/utility.hpp +++ b/implementation/utility/include/utility.hpp @@ -16,30 +16,53 @@ namespace vsomeip { class utility { -public: - static void * load_library(const std::string &_path, const std::string &_symbol); + public: + static void * load_library(const std::string &_path, + const std::string &_symbol); - static inline bool is_request(std::shared_ptr< message > _message) { - return (_message ? is_request(_message->get_message_type()) : false); - } + static inline bool is_request(std::shared_ptr<message> _message) { + return (_message ? is_request(_message->get_message_type()) : false); + } - static inline bool is_request(byte_t _type) { - return is_request(static_cast< message_type_e >(_type)); - } + static inline bool is_request(byte_t _type) { + return is_request(static_cast<message_type_e>(_type)); + } - static inline bool is_request(message_type_e _type) { - return ((_type < message_type_e::NOTIFICATION) || - (_type >= message_type_e::REQUEST_ACK && - _type <= message_type_e::REQUEST_NO_RETURN_ACK)); - } + static inline bool is_request(message_type_e _type) { + return ((_type < message_type_e::NOTIFICATION) + || (_type >= message_type_e::REQUEST_ACK + && _type <= message_type_e::REQUEST_NO_RETURN_ACK)); + } - static bool is_notification(const byte_t *_data); + static inline bool is_request_no_return(std::shared_ptr<message> _message) { + return (_message && is_request_no_return(_message->get_message_type())); + } - static uint32_t get_message_size(std::vector< byte_t > &_data); + static inline bool is_request_no_return(byte_t _type) { + return (is_request_no_return(static_cast<message_type_e>(_type))); + } - static bool exists(const std::string &_path); + static inline bool is_request_no_return(message_type_e _type) { + return (_type == message_type_e::REQUEST_NO_RETURN + || _type == message_type_e::REQUEST_NO_RETURN_ACK); + } + + static inline bool is_event(byte_t _data) { + return (0 == (0x80 & _data)); + } + + static bool is_notification(const byte_t *_data); + + static uint32_t get_message_size(const byte_t *_data, uint32_t _size); + static inline uint32_t get_message_size(std::vector<byte_t> &_data) { + return get_message_size(&_data[0], _data.size()); + } + + static uint32_t get_payload_size(const byte_t *_data, uint32_t _size); + + static bool exists(const std::string &_path); }; -} // namespace vsomeip +} // namespace vsomeip #endif // VSOMEIP_UTILITY_HPP diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp index e9164c0..fd3c864 100644 --- a/implementation/utility/src/utility.cpp +++ b/implementation/utility/src/utility.cpp @@ -16,38 +16,47 @@ namespace vsomeip { bool utility::is_notification(const byte_t *_data) { - return (0 == _data[VSOMEIP_CLIENT_POS_MIN] - && 0 == _data[VSOMEIP_CLIENT_POS_MAX] - && 0 == _data[VSOMEIP_SESSION_POS_MIN] - && 0 == _data[VSOMEIP_SESSION_POS_MAX]); + return (0 == _data[VSOMEIP_CLIENT_POS_MIN] + && 0 == _data[VSOMEIP_CLIENT_POS_MAX] + && 0 == _data[VSOMEIP_SESSION_POS_MIN] + && 0 == _data[VSOMEIP_SESSION_POS_MAX]); } -uint32_t utility::get_message_size(std::vector<byte_t> &_data) { - uint32_t its_size(0); - if (VSOMEIP_SOMEIP_HEADER_SIZE <= _data.size()) { - its_size = VSOMEIP_SOMEIP_HEADER_SIZE - + VSOMEIP_BYTES_TO_LONG(_data[4], _data[5], _data[6], _data[7]); - } - return its_size; +uint32_t utility::get_message_size(const byte_t *_data, uint32_t _size) { + uint32_t its_size(0); + if (VSOMEIP_SOMEIP_HEADER_SIZE <= _size) { + its_size = VSOMEIP_SOMEIP_HEADER_SIZE + + VSOMEIP_BYTES_TO_LONG(_data[4], _data[5], _data[6], _data[7]); + } + return (its_size); +} + +uint32_t utility::get_payload_size(const byte_t *_data, uint32_t _size) { + uint32_t its_size(0); + if (VSOMEIP_SOMEIP_HEADER_SIZE <= _size) { + its_size = VSOMEIP_BYTES_TO_LONG(_data[4], _data[5], _data[6], _data[7]) + - VSOMEIP_SOMEIP_HEADER_SIZE; + } + return (its_size); } void * utility::load_library(const std::string &_path, - const std::string &_symbol) { - void * its_symbol = 0; + const std::string &_symbol) { + void * its_symbol = 0; - void *handle = dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL); - if (0 != handle) { - its_symbol = dlsym(handle, _symbol.c_str()); - } else { - VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")"; - } + void *handle = dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL); + if (0 != handle) { + its_symbol = dlsym(handle, _symbol.c_str()); + } else { + VSOMEIP_ERROR<< "Loading failed: (" << dlerror() << ")"; + } - return its_symbol; + return (its_symbol); } bool utility::exists(const std::string &_path) { - struct stat its_stat; - return (stat(_path.c_str(), &its_stat) == 0); + struct stat its_stat; + return (stat(_path.c_str(), &its_stat) == 0); } } // namespace vsomeip diff --git a/interface/vsomeip/application.hpp b/interface/vsomeip/application.hpp index a8bfb9f..d97fbb5 100644 --- a/interface/vsomeip/application.hpp +++ b/interface/vsomeip/application.hpp @@ -61,6 +61,8 @@ public: bool _reliable = false) = 0; // Set events/fields + virtual void get(service_t _service, instance_t _instance, + event_t _event) = 0; virtual void set(service_t _service, instance_t _instance, event_t _event, const std::shared_ptr<payload> &_value) = 0; diff --git a/interface/vsomeip/defines.hpp b/interface/vsomeip/defines.hpp index 3fa199f..e72083f 100644 --- a/interface/vsomeip/defines.hpp +++ b/interface/vsomeip/defines.hpp @@ -34,9 +34,10 @@ #define VSOMEIP_CLIENT_POS_MAX 9 #define VSOMEIP_SESSION_POS_MIN 10 #define VSOMEIP_SESSION_POS_MAX 11 -#define VSOMEIP_PROTOCOL_VERSION_POS 12 -#define VSOMEIP_INTERFACE_VERSION_POS 13 +#define VSOMEIP_PROTOCOL_VERSION_POS 12 +#define VSOMEIP_INTERFACE_VERSION_POS 13 #define VSOMEIP_MESSAGE_TYPE_POS 14 #define VSOMEIP_RETURN_CODE_POS 15 +#define VSOMEIP_PAYLOAD_POS 16 #endif // VSOMEIP_DEFINES_HPP diff --git a/interface/vsomeip/runtime.hpp b/interface/vsomeip/runtime.hpp index 604395d..a3cf624 100644 --- a/interface/vsomeip/runtime.hpp +++ b/interface/vsomeip/runtime.hpp @@ -28,10 +28,10 @@ public: virtual std::shared_ptr<application> create_application( const std::string &_name = "") const = 0; + virtual std::shared_ptr<message> create_message() const = 0; virtual std::shared_ptr<message> create_request() const = 0; virtual std::shared_ptr<message> create_response( const std::shared_ptr<message> &_request) const = 0; - virtual std::shared_ptr<message> create_notification() const = 0; virtual std::shared_ptr<payload> create_payload() const = 0; |