summaryrefslogtreecommitdiff
path: root/implementation/endpoints/include/local_uds_server_endpoint_impl.hpp
blob: 256d86618c3d15b0cbf238bebc0eb2fd1a8ca7ed (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
// Copyright (C) 2014-2022 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_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_
#define VSOMEIP_V3_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_

#include <map>
#include <thread>
#include <condition_variable>
#include <memory>

#if VSOMEIP_BOOST_VERSION < 106600
#    include <boost/asio/local/stream_protocol_ext.hpp>
#else
#    include <boost/asio/local/stream_protocol.hpp>
#endif

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

#include "buffer.hpp"
#include "server_endpoint_impl.hpp"

namespace vsomeip_v3 {

using local_uds_server_endpoint_base_impl = server_endpoint_impl<
#if VSOMEIP_BOOST_VERSION < 106600
    boost::asio::local::stream_protocol_ext
#else
    boost::asio::local::stream_protocol
#endif
    >;

class local_uds_server_endpoint_impl: public local_uds_server_endpoint_base_impl {
public:
    local_uds_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
            const std::shared_ptr<routing_host>& _routing_host,
            const endpoint_type& _local,
            boost::asio::io_context &_io,
            const std::shared_ptr<configuration>& _configuration,
            bool _is_routing_endpoint);

    local_uds_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
            const std::shared_ptr<routing_host>& _routing_host,
            const endpoint_type& _local,
            boost::asio::io_context &_io,
            int native_socket,
            const std::shared_ptr<configuration>& _configuration,
            bool _is_routing_endpoint);

    virtual ~local_uds_server_endpoint_impl();

    void start();
    void stop();

    void receive();

    // this overrides server_endpoint_impl::send to disable the nPDU feature
    // for local communication
    bool send(const uint8_t *_data, uint32_t _size);
    bool send_to(const std::shared_ptr<endpoint_definition>,
                 const byte_t *_data, uint32_t _size);
    bool send_error(const std::shared_ptr<endpoint_definition> _target,
                const byte_t *_data, uint32_t _size);
    bool send_queued(const target_data_iterator_type _queue_iterator);
    void get_configured_times_from_endpoint(
            service_t _service, method_t _method,
            std::chrono::nanoseconds *_debouncing,
            std::chrono::nanoseconds *_maximum_retention) const;

    bool get_default_target(service_t, endpoint_type &) const;

    bool is_local() const;

    void accept_client_func();
    void print_status();

    bool is_reliable() const;
    std::uint16_t get_local_port() const;
    void set_local_port(std::uint16_t _port);

    client_t assign_client(const byte_t *_data, uint32_t _size);

private:
    class connection: public std::enable_shared_from_this<connection> {

    public:
        using ptr = std::shared_ptr<connection>;

        static ptr create(const std::shared_ptr<local_uds_server_endpoint_impl>& _server,
                          std::uint32_t _max_message_size,
                          std::uint32_t _buffer_shrink_threshold,
                          boost::asio::io_context &_io);
        socket_type & get_socket();
        std::unique_lock<std::mutex> get_socket_lock();

        void start();
        void stop();

        void send_queued(const message_buffer_ptr_t& _buffer);

        void set_bound_client(client_t _client);
        client_t get_bound_client() const;

        void set_bound_client_host(const std::string &_bound_client_host);
        std::string get_bound_client_host() const;

#if defined(__linux__) || defined(ANDROID)
        void set_bound_sec_client(const vsomeip_sec_client_t &_sec_client);
#endif

        std::size_t get_recv_buffer_capacity() const;

    private:
        connection(const std::shared_ptr<local_uds_server_endpoint_impl>& _server,
                   std::uint32_t _max_message_size,
                   std::uint32_t _initial_recv_buffer_size,
                   std::uint32_t _buffer_shrink_threshold,
                   boost::asio::io_context &_io);

        void send_cbk(const message_buffer_ptr_t _buffer,
                boost::system::error_code const &_error, std::size_t _bytes);
        void receive_cbk(boost::system::error_code const &_error,
                         std::size_t _bytes
#if defined(__linux__) || defined(ANDROID)
                         , std::uint32_t const &_uid, std::uint32_t const &_gid
#endif
        );
        void calculate_shrink_count();
        std::string get_path_local() const;
        std::string get_path_remote() const;
        void handle_recv_buffer_exception(const std::exception &_e);

        std::mutex socket_mutex_;
        local_uds_server_endpoint_impl::socket_type socket_;
        std::weak_ptr<local_uds_server_endpoint_impl> server_;

        const std::uint32_t recv_buffer_size_initial_;
        const std::uint32_t max_message_size_;

        message_buffer_t recv_buffer_;
        size_t recv_buffer_size_;
        std::uint32_t missing_capacity_;
        std::uint32_t shrink_count_;
        const std::uint32_t buffer_shrink_threshold_;

        client_t bound_client_;
        std::string bound_client_host_;

        vsomeip_sec_client_t sec_client_;

        bool assigned_client_;
    };

    std::mutex acceptor_mutex_;
#if VSOMEIP_BOOST_VERSION < 106600
    boost::asio::local::stream_protocol_ext::acceptor acceptor_;
#else
    boost::asio::local::stream_protocol::acceptor acceptor_;
#endif
    using connections_t = std::map<client_t, connection::ptr>;
    std::mutex connections_mutex_;
    connections_t connections_;

    const std::uint32_t buffer_shrink_threshold_;

    const bool is_routing_endpoint_;

private:
    bool add_connection(const client_t &_client,
            const std::shared_ptr<connection> &_connection);
    void remove_connection(const client_t &_client);
    void accept_cbk(const connection::ptr& _connection,
                    boost::system::error_code const &_error);
    std::string get_remote_information(
            const target_data_iterator_type _queue_iterator) const;
    std::string get_remote_information(
            const endpoint_type& _remote) const;

    bool check_packetizer_space(target_data_iterator_type _queue_iterator,
                                message_buffer_ptr_t* _packetizer,
                                std::uint32_t _size);
    bool tp_segmentation_enabled(service_t _service, method_t _method) const;
    void send_client_identifier(const client_t &_client);
};

} // namespace vsomeip_v3

#endif // VSOMEIP_V3_LOCAL_UDS_SERVER_ENDPOINT_IMPL_HPP_