1 // Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) 2 // This Source Code Form is subject to the terms of the Mozilla Public 3 // License, v. 2.0. If a copy of the MPL was not distributed with this 4 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 5 6 #ifndef VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_ 7 #define VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_ 8 9 #include <map> 10 #include <memory> 11 #include <mutex> 12 #include <set> 13 #include <forward_list> 14 #include <atomic> 15 #include <tuple> 16 17 #include <boost/asio/steady_timer.hpp> 18 19 #include "../../configuration/include/configuration.hpp" 20 #include "../../endpoints/include/endpoint_definition.hpp" 21 #include "../../routing/include/types.hpp" 22 #include "../../routing/include/remote_subscription.hpp" 23 24 #include "service_discovery.hpp" 25 #include "ip_option_impl.hpp" 26 #include "ipv4_option_impl.hpp" 27 #include "ipv6_option_impl.hpp" 28 #include "deserializer.hpp" 29 #include "message_impl.hpp" 30 31 namespace vsomeip_v3 { 32 33 class endpoint; 34 class serializer; 35 36 namespace sd { 37 38 class entry_impl; 39 class eventgroupentry_impl; 40 class option_impl; 41 class remote_subscription_ack; 42 class request; 43 class serviceentry_impl; 44 class service_discovery_host; 45 class subscription; 46 47 typedef std::map<service_t, 48 std::map<instance_t, 49 std::shared_ptr<request> 50 > 51 > requests_t; 52 53 struct entry_data_t { 54 std::shared_ptr<entry_impl> entry_; 55 std::vector<std::shared_ptr<option_impl> > options_; 56 std::shared_ptr<entry_impl> other_; 57 }; 58 59 class service_discovery_impl: public service_discovery, 60 public std::enable_shared_from_this<service_discovery_impl> { 61 public: 62 service_discovery_impl(service_discovery_host *_host, 63 const std::shared_ptr<configuration>& _configuration); 64 virtual ~service_discovery_impl(); 65 66 boost::asio::io_service & get_io(); 67 68 void init(); 69 void start(); 70 void stop(); 71 72 void request_service(service_t _service, instance_t _instance, 73 major_version_t _major, minor_version_t _minor, ttl_t _ttl); 74 void release_service(service_t _service, instance_t _instance); 75 76 void subscribe(service_t _service, instance_t _instance, 77 eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, 78 client_t _client, const std::shared_ptr<eventgroupinfo>& _info); 79 void unsubscribe(service_t _service, instance_t _instance, 80 eventgroup_t _eventgroup, client_t _client); 81 void unsubscribe_all(service_t _service, instance_t _instance); 82 void unsubscribe_all_on_suspend(); 83 void remove_subscriptions(service_t _service, instance_t _instance); 84 85 bool send(bool _is_announcing); 86 87 void on_message(const byte_t *_data, length_t _length, 88 const boost::asio::ip::address &_sender, 89 const boost::asio::ip::address &_destination); 90 91 void on_endpoint_connected( 92 service_t _service, instance_t _instance, 93 const std::shared_ptr<endpoint> &_endpoint); 94 95 void offer_service(const std::shared_ptr<serviceinfo> &_info); 96 void stop_offer_service(const std::shared_ptr<serviceinfo> &_info); 97 98 void set_diagnosis_mode(const bool _activate); 99 100 bool get_diagnosis_mode(); 101 102 103 void update_remote_subscription( 104 const std::shared_ptr<remote_subscription> &_subscription); 105 106 void register_sd_acceptance_handler(sd_acceptance_handler_t _handler); 107 void register_reboot_notification_handler( 108 reboot_notification_handler_t _handler); 109 private: 110 std::pair<session_t, bool> get_session(const boost::asio::ip::address &_address); 111 void increment_session(const boost::asio::ip::address &_address); 112 113 bool is_reboot(const boost::asio::ip::address &_sender, 114 const boost::asio::ip::address &_destination, 115 bool _reboot_flag, session_t _session); 116 117 void insert_find_entries(std::vector<std::shared_ptr<message_impl> > &_messages, 118 const requests_t &_requests); 119 void insert_offer_entries(std::vector<std::shared_ptr<message_impl> > &_messages, 120 const services_t &_services, bool _ignore_phase); 121 void insert_offer_service(std::vector<std::shared_ptr<message_impl> > &_messages, 122 const std::shared_ptr<const serviceinfo> &_info); 123 enum remote_offer_type_e : std::uint8_t { 124 RELIABLE_UNRELIABLE, 125 RELIABLE, 126 UNRELIABLE, 127 UNKNOWN = 0xff 128 }; 129 130 entry_data_t create_eventgroup_entry( 131 service_t _service, instance_t _instance, eventgroup_t _eventgroup, 132 const std::shared_ptr<subscription> &_subscription, 133 reliability_type_e _offer_type); 134 135 void insert_subscription_ack( 136 const std::shared_ptr<remote_subscription_ack>& _acknowledgement, 137 const std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl, 138 const std::shared_ptr<endpoint_definition> &_target, 139 const std::set<client_t> &_clients); 140 141 typedef std::set<std::pair<bool, std::uint16_t>> expired_ports_t; 142 struct sd_acceptance_state_t { sd_acceptance_state_tvsomeip_v3::sd::service_discovery_impl::sd_acceptance_state_t143 explicit sd_acceptance_state_t(expired_ports_t& _expired_ports) 144 : expired_ports_(_expired_ports), 145 sd_acceptance_required_(false), 146 accept_entries_(false) { 147 } 148 149 expired_ports_t& expired_ports_; 150 bool sd_acceptance_required_; 151 bool accept_entries_; 152 }; 153 void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry, 154 const std::vector<std::shared_ptr<option_impl> > &_options, 155 bool _unicast_flag, std::vector<std::shared_ptr<message_impl> > &_resubscribes, 156 bool _received_via_mcast, const sd_acceptance_state_t& _sd_ac_state); 157 void process_offerservice_serviceentry( 158 service_t _service, instance_t _instance, major_version_t _major, 159 minor_version_t _minor, ttl_t _ttl, 160 const boost::asio::ip::address &_reliable_address, 161 uint16_t _reliable_port, 162 const boost::asio::ip::address &_unreliable_address, 163 uint16_t _unreliable_port, 164 std::vector<std::shared_ptr<message_impl> > &_resubscribes, 165 bool _received_via_mcast, const sd_acceptance_state_t& _sd_ac_state); 166 void send_offer_service( 167 const std::shared_ptr<const serviceinfo> &_info, service_t _service, 168 instance_t _instance, major_version_t _major, minor_version_t _minor, 169 bool _unicast_flag); 170 171 void process_findservice_serviceentry(service_t _service, 172 instance_t _instance, 173 major_version_t _major, 174 minor_version_t _minor, 175 bool _unicast_flag); 176 void process_eventgroupentry( 177 std::shared_ptr<eventgroupentry_impl> &_entry, 178 const std::vector<std::shared_ptr<option_impl> > &_options, 179 std::shared_ptr<remote_subscription_ack> &_acknowledgement, 180 const boost::asio::ip::address &_sender, 181 const boost::asio::ip::address &_destination, 182 bool _is_stop_subscribe_subscribe, bool _force_initial_events, 183 const sd_acceptance_state_t& _sd_ac_state); 184 void handle_eventgroup_subscription(service_t _service, 185 instance_t _instance, eventgroup_t _eventgroup, 186 major_version_t _major, ttl_t _ttl, uint8_t _counter, uint16_t _reserved, 187 const boost::asio::ip::address &_first_address, uint16_t _first_port, 188 bool _is_first_reliable, 189 const boost::asio::ip::address &_second_address, uint16_t _second_port, 190 bool _is_second_reliable, 191 std::shared_ptr<remote_subscription_ack> &_acknowledgement, 192 bool _is_stop_subscribe_subscribe, bool _force_initial_events, 193 const std::set<client_t> &_clients, 194 const sd_acceptance_state_t& _sd_ac_state, 195 const std::shared_ptr<eventgroupinfo>& _info); 196 void handle_eventgroup_subscription_ack(service_t _service, 197 instance_t _instance, eventgroup_t _eventgroup, 198 major_version_t _major, ttl_t _ttl, uint8_t _counter, 199 const std::set<client_t> &_clients, 200 const boost::asio::ip::address &_sender, 201 const boost::asio::ip::address &_address, uint16_t _port); 202 void handle_eventgroup_subscription_nack(service_t _service, 203 instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter, 204 const std::set<client_t> &_clients); 205 206 bool send(const std::vector<std::shared_ptr<message_impl>> &_messages); 207 bool serialize_and_send( 208 const std::vector<std::shared_ptr<message_impl>> &_messages, 209 const boost::asio::ip::address &_address); 210 211 void update_acknowledgement( 212 const std::shared_ptr<remote_subscription_ack> &_acknowledgement); 213 214 bool is_tcp_connected(service_t _service, 215 instance_t _instance, 216 const std::shared_ptr<endpoint_definition>& its_endpoint); 217 218 void start_ttl_timer(); 219 void stop_ttl_timer(); 220 221 void check_ttl(const boost::system::error_code &_error); 222 223 void start_subscription_expiration_timer(); 224 void start_subscription_expiration_timer_unlocked(); 225 void stop_subscription_expiration_timer(); 226 void stop_subscription_expiration_timer_unlocked(); 227 void expire_subscriptions(const boost::system::error_code &_error); 228 229 bool check_ipv4_address(const boost::asio::ip::address& its_address) const; 230 231 bool check_static_header_fields( 232 const std::shared_ptr<const message> &_message) const; 233 bool check_layer_four_protocol( 234 const std::shared_ptr<const ip_option_impl>& _ip_option) const; 235 236 void get_subscription_endpoints(service_t _service, instance_t _instance, 237 std::shared_ptr<endpoint>& _reliable, 238 std::shared_ptr<endpoint>& _unreliable) const; 239 void get_subscription_address(const std::shared_ptr<endpoint> &_reliable, 240 const std::shared_ptr<endpoint> &_unreliable, 241 boost::asio::ip::address &_address) const; 242 243 void update_request(service_t _service, instance_t _instance); 244 245 void start_offer_debounce_timer(bool _first_start); 246 void on_offer_debounce_timer_expired(const boost::system::error_code &_error); 247 248 249 void start_find_debounce_timer(bool _first_start); 250 void on_find_debounce_timer_expired(const boost::system::error_code &_error); 251 252 253 void on_repetition_phase_timer_expired( 254 const boost::system::error_code &_error, 255 const std::shared_ptr<boost::asio::steady_timer>& _timer, 256 std::uint8_t _repetition, std::uint32_t _last_delay); 257 void on_find_repetition_phase_timer_expired( 258 const boost::system::error_code &_error, 259 const std::shared_ptr<boost::asio::steady_timer>& _timer, 260 std::uint8_t _repetition, std::uint32_t _last_delay); 261 void move_offers_into_main_phase( 262 const std::shared_ptr<boost::asio::steady_timer> &_timer); 263 264 bool send_stop_offer(const std::shared_ptr<serviceinfo>& _info); 265 266 void start_main_phase_timer(); 267 void on_main_phase_timer_expired(const boost::system::error_code &_error); 268 269 270 void send_uni_or_multicast_offerservice( 271 const std::shared_ptr<const serviceinfo> &_info, 272 bool _unicast_flag); 273 bool last_offer_shorter_half_offer_delay_ago(); 274 void send_unicast_offer_service( 275 const std::shared_ptr<const serviceinfo> &_info); 276 void send_multicast_offer_service( 277 const std::shared_ptr<const serviceinfo>& _info); 278 279 bool check_source_address(const boost::asio::ip::address &its_source_address) const; 280 281 void update_subscription_expiration_timer( 282 const std::vector<std::shared_ptr<message_impl> > &_messages); 283 284 void remote_subscription_acknowledge( 285 service_t _service, instance_t _instance, eventgroup_t _eventgroup, 286 const std::shared_ptr<remote_subscription> &_subscription); 287 288 bool check_stop_subscribe_subscribe( 289 message_impl::entries_t::const_iterator _iter, 290 message_impl::entries_t::const_iterator _end, 291 const message_impl::options_t &_options) const; 292 293 bool has_opposite( 294 message_impl::entries_t::const_iterator _iter, 295 message_impl::entries_t::const_iterator _end, 296 const message_impl::options_t &_options) const; 297 298 bool has_same( 299 message_impl::entries_t::const_iterator _iter, 300 message_impl::entries_t::const_iterator _end, 301 const message_impl::options_t &_options) const; 302 303 bool is_subscribed( 304 const std::shared_ptr<eventgroupentry_impl> &_entry, 305 const message_impl::options_t &_options) const; 306 307 configuration::ttl_factor_t get_ttl_factor( 308 service_t _service, instance_t _instance, 309 const configuration::ttl_map_t& _ttl_map) const; 310 void on_last_msg_received_timer_expired(const boost::system::error_code &_error); 311 void stop_last_msg_received_timer(); 312 313 remote_offer_type_e get_remote_offer_type( 314 service_t _service, instance_t _instance) const; 315 remote_offer_type_e get_remote_offer_type( 316 const std::shared_ptr<subscription> &_subscription) const; 317 318 bool update_remote_offer_type(service_t _service, instance_t _instance, 319 remote_offer_type_e _offer_type, 320 const boost::asio::ip::address &_reliable_address, 321 std::uint16_t _reliable_port, 322 const boost::asio::ip::address &_unreliable_address, 323 std::uint16_t _unreliable_port); 324 void remove_remote_offer_type(service_t _service, instance_t _instance, 325 const boost::asio::ip::address &_reliable_address, 326 std::uint16_t _reliable_port, 327 const boost::asio::ip::address &_unreliable_address, 328 std::uint16_t _unreliable_port); 329 void remove_remote_offer_type_by_ip(const boost::asio::ip::address &_address); 330 void remove_remote_offer_type_by_ip(const boost::asio::ip::address &_address, 331 std::uint16_t _port, bool _reliable); 332 333 std::shared_ptr<subscription> create_subscription( 334 major_version_t _major, ttl_t _ttl, 335 const std::shared_ptr<endpoint> &_reliable, 336 const std::shared_ptr<endpoint> &_unreliable, 337 const std::shared_ptr<eventgroupinfo> &_info); 338 339 std::shared_ptr<remote_subscription> get_remote_subscription( 340 const service_t _service, const instance_t _instance, 341 const eventgroup_t _eventgroup); 342 343 void send_subscription_ack( 344 const std::shared_ptr<remote_subscription_ack> &_acknowledgement); 345 346 std::shared_ptr<option_impl> create_ip_option( 347 const boost::asio::ip::address &_address, uint16_t _port, 348 bool _is_reliable) const; 349 350 void send_subscription(const std::shared_ptr<subscription> &_subscription, 351 const service_t _service, const instance_t _instance, 352 const eventgroup_t _eventgroup, const client_t _client); 353 354 void add_entry_data(std::vector<std::shared_ptr<message_impl>> &_messages, 355 const entry_data_t &_data); 356 357 void add_entry_data_to_remote_subscription_ack_msg( 358 const std::shared_ptr<remote_subscription_ack>& _acknowledgement, 359 const entry_data_t &_data); 360 reliability_type_e get_eventgroup_reliability( 361 service_t _service, instance_t _instance, eventgroup_t _eventgroup, 362 const std::shared_ptr<subscription>& _subscription); 363 364 private: 365 boost::asio::io_service &io_; 366 service_discovery_host *host_; 367 std::shared_ptr<configuration> configuration_; 368 369 boost::asio::ip::address unicast_; 370 uint16_t port_; 371 bool reliable_; 372 std::shared_ptr<endpoint> endpoint_; 373 374 std::shared_ptr<serializer> serializer_; 375 std::shared_ptr<deserializer> deserializer_; 376 377 requests_t requested_; 378 std::mutex requested_mutex_; 379 std::map<service_t, 380 std::map<instance_t, 381 std::map<eventgroup_t, 382 std::shared_ptr<subscription> 383 > 384 > 385 > subscribed_; 386 std::mutex subscribed_mutex_; 387 388 std::mutex serialize_mutex_; 389 390 // Sessions 391 std::map<boost::asio::ip::address, std::pair<session_t, bool> > sessions_sent_; 392 std::map<boost::asio::ip::address, 393 std::tuple<session_t, session_t, bool, bool> > sessions_received_; 394 std::mutex sessions_received_mutex_; 395 396 // Runtime 397 std::weak_ptr<runtime> runtime_; 398 399 // TTL handling for services offered by other hosts 400 std::mutex ttl_timer_mutex_; 401 boost::asio::steady_timer ttl_timer_; 402 std::chrono::milliseconds ttl_timer_runtime_; 403 ttl_t ttl_; 404 405 // TTL handling for subscriptions done by other hosts 406 std::mutex subscription_expiration_timer_mutex_; 407 boost::asio::steady_timer subscription_expiration_timer_; 408 std::chrono::steady_clock::time_point next_subscription_expiration_; 409 410 uint32_t max_message_size_; 411 412 std::chrono::milliseconds initial_delay_; 413 std::chrono::milliseconds offer_debounce_time_; 414 std::chrono::milliseconds repetitions_base_delay_; 415 std::uint8_t repetitions_max_; 416 std::chrono::milliseconds cyclic_offer_delay_; 417 std::mutex offer_debounce_timer_mutex_; 418 boost::asio::steady_timer offer_debounce_timer_; 419 // this map is used to collect offers while for offer debouncing 420 std::mutex collected_offers_mutex_; 421 services_t collected_offers_; 422 423 std::chrono::milliseconds find_debounce_time_; 424 std::mutex find_debounce_timer_mutex_; 425 boost::asio::steady_timer find_debounce_timer_; 426 requests_t collected_finds_; 427 428 // this map contains the offers and their timers currently in repetition phase 429 std::mutex repetition_phase_timers_mutex_; 430 std::map<std::shared_ptr<boost::asio::steady_timer>, 431 services_t> repetition_phase_timers_; 432 433 // this map contains the finds and their timers currently in repetition phase 434 std::mutex find_repetition_phase_timers_mutex_; 435 std::map<std::shared_ptr<boost::asio::steady_timer>, 436 requests_t> find_repetition_phase_timers_; 437 438 std::mutex main_phase_timer_mutex_; 439 boost::asio::steady_timer main_phase_timer_; 440 441 std::atomic<bool> is_suspended_; 442 443 std::string sd_multicast_; 444 boost::asio::ip::address sd_multicast_address_; 445 446 boost::asio::ip::address current_remote_address_; 447 448 std::atomic<bool> is_diagnosis_; 449 450 std::mutex pending_remote_subscriptions_mutex_; 451 std::map<std::shared_ptr<remote_subscription>, 452 std::shared_ptr<remote_subscription_ack> 453 > pending_remote_subscriptions_; 454 std::mutex acknowledgement_mutex_; 455 456 std::mutex response_mutex_; 457 458 configuration::ttl_map_t ttl_factor_offers_; 459 configuration::ttl_map_t ttl_factor_subscriptions_; 460 461 std::mutex last_msg_received_timer_mutex_; 462 boost::asio::steady_timer last_msg_received_timer_; 463 std::chrono::milliseconds last_msg_received_timer_timeout_; 464 465 mutable std::mutex remote_offer_types_mutex_; 466 std::map<std::pair<service_t, instance_t>, remote_offer_type_e> remote_offer_types_; 467 std::map<boost::asio::ip::address, 468 std::map<std::pair<bool, std::uint16_t>, 469 std::set<std::pair<service_t, instance_t>>>> remote_offers_by_ip_; 470 471 reboot_notification_handler_t reboot_notification_handler_; 472 sd_acceptance_handler_t sd_acceptance_handler_; 473 474 std::mutex offer_mutex_; 475 std::mutex check_ttl_mutex_; 476 }; 477 478 } // namespace sd 479 } // namespace vsomeip_v3 480 481 #endif // VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_ 482 483