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