summaryrefslogtreecommitdiff
path: root/implementation/routing/include/routing_manager_stub.hpp
blob: 4209eec1fb94210b64cb1f59899a78ac4a6ed177 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
// Copyright (C) 2014-2021 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_
#define VSOMEIP_V3_ROUTING_MANAGER_STUB_

#include <condition_variable>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <thread>
#include <atomic>
#include <unordered_set>

#if VSOMEIP_BOOST_VERSION < 106600
#    include <boost/asio/io_service.hpp>
#    define io_context io_service
#else
#    include <boost/asio/io_context.hpp>
#endif
#include <boost/asio/steady_timer.hpp>

#include <vsomeip/handler.hpp>
#include <vsomeip/vsomeip_sec.h>

#include "types.hpp"
#include "../include/routing_host.hpp"
#include "../../endpoints/include/endpoint_host.hpp"
#include "../../protocol/include/protocol.hpp"
#include "../../protocol/include/routing_info_entry.hpp"

namespace vsomeip_v3 {

class configuration;
#if defined(__linux__) || defined(ANDROID)
class netlink_connector;
#endif // __linux__ || ANDROID
class routing_manager_stub_host;

struct debounce_filter_t;
struct policy;

class routing_manager_stub: public routing_host,
        public std::enable_shared_from_this<routing_manager_stub> {
public:
    routing_manager_stub(
            routing_manager_stub_host *_host,
            const std::shared_ptr<configuration>& _configuration);
    virtual ~routing_manager_stub();

    void init();
    void start();
    void stop();

    void on_message(const byte_t *_data, length_t _size,
            endpoint *_receiver, bool _is_multicast,
            client_t _bound_client, const vsomeip_sec_client_t *_sec_client,
            const boost::asio::ip::address &_remote_address,
            std::uint16_t _remote_port);

    void on_offer_service(client_t _client, service_t _service,
            instance_t _instance, major_version_t _major, minor_version_t _minor);
    void on_stop_offer_service(client_t _client, service_t _service,
            instance_t _instance,  major_version_t _major, minor_version_t _minor);

    bool send_subscribe(
            const std::shared_ptr<endpoint> &_target, client_t _client,
            service_t _service, instance_t _instance,
            eventgroup_t _eventgroup, major_version_t _major,
            event_t _event, const std::shared_ptr<debounce_filter_t> &_filter,
            remote_subscription_id_t _id);

    bool send_unsubscribe(const std::shared_ptr<endpoint>& _target,
            client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup,
            event_t _event, remote_subscription_id_t _id);

    bool send_expired_subscription(const std::shared_ptr<endpoint>& _target,
            client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup,
            event_t _event, remote_subscription_id_t _id);

    void send_subscribe_nack(client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup, event_t _event);

    void send_subscribe_ack(client_t _client, service_t _service,
            instance_t _instance, eventgroup_t _eventgroup, event_t _event);

    bool contained_in_routing_info(client_t _client, service_t _service,
                                   instance_t _instance, major_version_t _major,
                                   minor_version_t _minor) const;

    void create_local_receiver();
    bool send_ping(client_t _client);
    bool is_registered(client_t _client) const;
    client_t get_client() const;
    void handle_credentials(const client_t _client, std::set<protocol::service> &_requests);
    void handle_requests(const client_t _client, std::set<protocol::service> &_requests);

    void update_registration(client_t _client, registration_type_e _type,
            const boost::asio::ip::address &_address, port_t _port);

    void print_endpoint_status() const;

    bool send_provided_event_resend_request(client_t _client,
                                            pending_remote_offer_id_t _id);

#ifndef VSOMEIP_DISABLE_SECURITY
    bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid,
            const std::shared_ptr<policy> &_policy,
            const std::shared_ptr<payload> &_payload,
            const security_update_handler_t &_handler);
    bool remove_security_policy_configuration(uint32_t _uid, uint32_t _gid,
            const security_update_handler_t &_handler);
    void on_security_update_response(pending_security_update_id_t _id,
            client_t _client);

    void policy_cache_add(uint32_t _uid, const std::shared_ptr<payload>& _payload);
    void policy_cache_remove(uint32_t _uid);
    bool is_policy_cached(uint32_t _uid);

    bool send_update_security_policy_request(client_t _client,
            pending_security_update_id_t _update_id, uint32_t _uid,
            const std::shared_ptr<payload>& _payload);
    bool send_remove_security_policy_request(client_t _client,
            pending_security_update_id_t _update_id, uint32_t _uid, uint32_t _gid);

    bool send_cached_security_policies(client_t _client);

    bool add_requester_policies(uid_t _uid, gid_t _gid,
            const std::set<std::shared_ptr<policy> > &_policies);
    void remove_requester_policies(uid_t _uid, gid_t _gid);
#endif // !VSOMEIP_DISABLE_SECURITY

    void add_known_client(client_t _client, const std::string &_client_host);

    void send_suspend() const;

    void remove_subscriptions(port_t _local_port,
            const boost::asio::ip::address &_remote_address,
            port_t _remote_port);

private:
    void broadcast(const std::vector<byte_t> &_command) const;

    void on_register_application(client_t _client);
    void on_deregister_application(client_t _client);

    void on_offered_service_request(client_t _client, offer_type_e _offer_type);

    void distribute_credentials(client_t _hoster, service_t _service, instance_t _instance);

    void inform_requesters(client_t _hoster, service_t _service,
            instance_t _instance, major_version_t _major,
            minor_version_t _minor, protocol::routing_info_entry_type_e _entry,
            bool _inform_service);

    void broadcast_ping() const;
    void on_pong(client_t _client);
    void start_watchdog();
    void check_watchdog();

    void client_registration_func(void);
    void init_routing_endpoint();
    void on_ping_timer_expired(boost::system::error_code const &_error);
    void remove_from_pinged_clients(client_t _client);
    void set_routing_state(routing_state_e _routing_state) {
        (void)_routing_state;
    };

    inline bool is_connected(client_t _source, client_t _sink) const {

        auto find_source = connection_matrix_.find(_source);
        if (find_source != connection_matrix_.end())
            return (find_source->second.find(_sink)
                    != find_source->second.end());

        return (false);
    }
    inline void add_connection(client_t _source, client_t _sink) {

        connection_matrix_[_source].insert(_sink);
    }
    inline void remove_connection(client_t _source, client_t _sink) {

        auto find_source = connection_matrix_.find(_source);
        if (find_source != connection_matrix_.end())
            find_source->second.erase(_sink);
    }
    inline void remove_source(client_t _source) {

        connection_matrix_.erase(_source);
    }

    void send_client_routing_info(const client_t _target,
            protocol::routing_info_entry &_entry);
    void send_client_routing_info(const client_t _target,
            std::vector<protocol::routing_info_entry> &&_entries);
    void send_client_credentials(client_t _target, std::set<std::pair<uint32_t, uint32_t>> &_credentials);

    void on_client_id_timer_expired(boost::system::error_code const &_error);

    void get_requester_policies(uid_t _uid, gid_t _gid,
            std::set<std::shared_ptr<policy> > &_policies) const;
    bool send_requester_policies(const std::unordered_set<client_t> &_clients,
            const std::set<std::shared_ptr<policy> > &_policies);

    void on_security_update_timeout(
            const boost::system::error_code &_error,
            pending_security_update_id_t _id,
            std::shared_ptr<boost::asio::steady_timer> _timer);

    pending_security_update_id_t pending_security_update_add(
            const std::unordered_set<client_t> &_clients);

    std::unordered_set<client_t> pending_security_update_get(
            pending_security_update_id_t _id);

    bool pending_security_update_remove(
            pending_security_update_id_t _id, client_t _client);

    bool is_pending_security_update_finished(
            pending_security_update_id_t _id);

    void add_pending_security_update_handler(
            pending_security_update_id_t _id,
            const security_update_handler_t &_handler);
    void add_pending_security_update_timer(
            pending_security_update_id_t _id);

#if defined(__linux__) || defined(ANDROID)
    void on_net_state_change(bool _is_interface, const std::string &_name, bool _is_available);
#endif

private:
    routing_manager_stub_host *host_;
    boost::asio::io_context &io_;
    std::mutex watchdog_timer_mutex_;
    boost::asio::steady_timer watchdog_timer_;

    boost::asio::steady_timer client_id_timer_;
    std::set<client_t> used_client_ids_;
    std::mutex used_client_ids_mutex_;

    std::shared_ptr<endpoint> root_;  // Routing manager endpoint

    std::shared_ptr<endpoint> local_receiver_;
    std::mutex local_receiver_mutex_;

    std::map<client_t,
            std::pair<uint8_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t>> > > > routing_info_;
    mutable std::mutex routing_info_mutex_;
    std::shared_ptr<configuration> configuration_;

    bool is_socket_activated_;
    std::atomic<bool> client_registration_running_;
    std::shared_ptr<std::thread> client_registration_thread_;
    std::mutex client_registration_mutex_;
    std::condition_variable client_registration_condition_;

    std::map<client_t, std::vector<registration_type_e>> pending_client_registrations_;
    std::map<client_t, std::pair<boost::asio::ip::address, port_t> > internal_client_ports_;
    const std::uint32_t max_local_message_size_;
    const std::chrono::milliseconds configured_watchdog_timeout_;
    boost::asio::steady_timer pinged_clients_timer_;
    std::mutex pinged_clients_mutex_;
    std::map<client_t, boost::asio::steady_timer::time_point> pinged_clients_;

    std::map<client_t, std::map<service_t, std::map<instance_t, std::pair<major_version_t, minor_version_t> > > > service_requests_;
    std::map<client_t, std::set<client_t>> connection_matrix_;

    std::mutex pending_security_updates_mutex_;
    pending_security_update_id_t pending_security_update_id_;
    std::map<pending_security_update_id_t, std::unordered_set<client_t>> pending_security_updates_;

    std::recursive_mutex security_update_handlers_mutex_;
    std::map<pending_security_update_id_t, security_update_handler_t> security_update_handlers_;

    std::mutex security_update_timers_mutex_;
    std::map<pending_security_update_id_t, std::shared_ptr<boost::asio::steady_timer>> security_update_timers_;

    std::mutex updated_security_policies_mutex_;
    std::map<uint32_t, std::shared_ptr<payload>> updated_security_policies_;

    mutable std::mutex requester_policies_mutex_;
    std::map<uint32_t,
        std::map<uint32_t,
            std::set<std::shared_ptr<policy> >
        >
    > requester_policies_;


#if defined(__linux__) || defined(ANDROID)
    // netlink connector for internal network
    // (replacement for Unix Domain Sockets if configured)
    std::shared_ptr<netlink_connector> local_link_connector_;
    bool is_local_link_available_;
#endif
};

} // namespace vsomeip_v3

#endif // VSOMEIP_V3_ROUTING_MANAGER_STUB_