1 // Copyright (C) 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 #include "../include/remote_subscription.hpp"
7 
8 #include <vsomeip/internal/logger.hpp>
9 
10 namespace vsomeip_v3 {
11 
remote_subscription()12 remote_subscription::remote_subscription()
13     : id_(PENDING_SUBSCRIPTION_ID),
14       is_initial_(true),
15       force_initial_events_(false),
16       major_(DEFAULT_MAJOR),
17       ttl_(DEFAULT_TTL),
18       reserved_(0),
19       counter_(0),
20       answers_(1) {
21 }
22 
~remote_subscription()23 remote_subscription::~remote_subscription() {
24 }
25 
26 bool
operator ==(const remote_subscription & _other) const27 remote_subscription::operator==(
28         const remote_subscription &_other) const {
29     auto own_egi = eventgroupinfo_.lock();
30     auto other_egi = _other.eventgroupinfo_.lock();
31     bool reliable_equal(true);
32     if (reliable_ && _other.reliable_) {
33         reliable_equal = (reliable_ == _other.reliable_);
34     }
35     bool unreliable_equal(true);
36     if (unreliable_ && _other.unreliable_) {
37         unreliable_equal = (unreliable_ == _other.unreliable_);
38     }
39     return (own_egi && other_egi && own_egi == other_egi && unreliable_equal
40             && reliable_equal);
41 }
42 
43 bool
equals(const std::shared_ptr<remote_subscription> & _other) const44 remote_subscription::equals(
45         const std::shared_ptr<remote_subscription> &_other) const {
46     return operator ==(*_other);
47 }
48 
49 bool
address_equals(const std::shared_ptr<remote_subscription> & _other) const50 remote_subscription::address_equals(
51         const std::shared_ptr<remote_subscription> &_other) const {
52     bool relibale_address_equals(false);
53     bool unrelibale_address_equals(false);
54 
55     if (reliable_ && (*_other).reliable_)
56         relibale_address_equals = (reliable_->get_address()
57                 == (*_other).reliable_->get_address());
58     if (unreliable_ && (*_other).unreliable_)
59         unrelibale_address_equals = (unreliable_->get_address()
60                 == (*_other).unreliable_->get_address());
61     return (relibale_address_equals || unrelibale_address_equals);
62 }
63 
64 void
reset(const std::set<client_t> & _clients)65 remote_subscription::reset(const std::set<client_t> &_clients) {
66     auto its_client_state = std::make_pair(
67             remote_subscription_state_e::SUBSCRIPTION_PENDING,
68             std::chrono::steady_clock::time_point());
69     if (_clients.empty()) {
70         clients_[0] = its_client_state;
71     } else {
72         for (const auto &its_client : _clients)
73             clients_[its_client] = its_client_state;
74     }
75 }
76 
77 bool
is_initial() const78 remote_subscription::is_initial() const {
79     return is_initial_;
80 }
81 
82 void
set_initial(const bool _is_initial)83 remote_subscription::set_initial(const bool _is_initial) {
84     is_initial_ = _is_initial;
85 }
86 
87 bool
force_initial_events() const88 remote_subscription::force_initial_events() const {
89     return force_initial_events_;
90 }
91 
92 void
set_force_initial_events(const bool _force_initial_events)93 remote_subscription::set_force_initial_events(
94         const bool _force_initial_events) {
95     force_initial_events_ = _force_initial_events;
96 }
97 
98 remote_subscription_id_t
get_id() const99 remote_subscription::get_id() const {
100     return id_;
101 }
102 
103 void
set_id(const remote_subscription_id_t _id)104 remote_subscription::set_id(const remote_subscription_id_t _id) {
105     id_ = _id;
106 }
107 
108 std::shared_ptr<eventgroupinfo>
get_eventgroupinfo() const109 remote_subscription::get_eventgroupinfo() const {
110     return eventgroupinfo_.lock();
111 }
112 
113 void
set_eventgroupinfo(const std::shared_ptr<eventgroupinfo> & _info)114 remote_subscription::set_eventgroupinfo(
115         const std::shared_ptr<eventgroupinfo> &_info) {
116     eventgroupinfo_ = _info;
117 }
118 
119 ttl_t
get_ttl() const120 remote_subscription::get_ttl() const {
121     return ttl_;
122 }
123 
124 void
set_ttl(const ttl_t _ttl)125 remote_subscription::set_ttl(const ttl_t _ttl) {
126     ttl_ = _ttl;
127 }
128 
129 uint16_t
get_reserved() const130 remote_subscription::get_reserved() const {
131     return reserved_;
132 }
133 
134 void
set_reserved(const uint16_t _reserved)135 remote_subscription::set_reserved(const uint16_t _reserved) {
136     reserved_ = _reserved;
137 }
138 
139 uint8_t
get_counter() const140 remote_subscription::get_counter() const {
141     return counter_;
142 }
143 
144 void
set_counter(uint8_t _counter)145 remote_subscription::set_counter(uint8_t _counter) {
146     counter_ = _counter;
147 }
148 
149 std::set<client_t>
get_clients() const150 remote_subscription::get_clients() const {
151     std::lock_guard<std::mutex> its_lock(mutex_);
152     std::set<client_t> its_clients;
153     for (const auto &its_item : clients_)
154         its_clients.insert(its_item.first);
155     return its_clients;
156 }
157 
158 bool
has_client() const159 remote_subscription::has_client() const {
160     std::lock_guard<std::mutex> its_lock(mutex_);
161     return (clients_.size() > 0);
162 }
163 
164 bool
has_client(const client_t _client) const165 remote_subscription::has_client(const client_t _client) const {
166     std::lock_guard<std::mutex> its_lock(mutex_);
167     return (clients_.find(_client) != clients_.end());
168 }
169 
170 void
remove_client(const client_t _client)171 remote_subscription::remove_client(const client_t _client) {
172     std::lock_guard<std::mutex> its_lock(mutex_);
173     clients_.erase(_client);
174 }
175 
176 remote_subscription_state_e
get_client_state(const client_t _client) const177 remote_subscription::get_client_state(const client_t _client) const {
178     std::lock_guard<std::mutex> its_lock(mutex_);
179     auto found_client = clients_.find(_client);
180     if (found_client != clients_.end()) {
181         return found_client->second.first;
182     }
183     return remote_subscription_state_e::SUBSCRIPTION_UNKNOWN;
184 }
185 
186 void
set_client_state(const client_t _client,remote_subscription_state_e _state)187 remote_subscription::set_client_state(const client_t _client,
188         remote_subscription_state_e _state) {
189     std::lock_guard<std::mutex> its_lock(mutex_);
190     auto found_item = clients_.find(_client);
191     if (found_item != clients_.end()) {
192         found_item->second.first = _state;
193         if (found_item->second.second == std::chrono::steady_clock::time_point()
194             && (_state == remote_subscription_state_e::SUBSCRIPTION_ACKED
195                 || _state == remote_subscription_state_e::SUBSCRIPTION_NACKED)) {
196             found_item->second.second = std::chrono::steady_clock::now()
197                 + std::chrono::seconds(ttl_);
198         }
199     }
200 }
201 
202 void
set_all_client_states(remote_subscription_state_e _state)203 remote_subscription::set_all_client_states(remote_subscription_state_e _state) {
204     std::lock_guard<std::mutex> its_lock(mutex_);
205     for (auto &its_item : clients_)
206         its_item.second.first = _state;
207 }
208 
209 std::shared_ptr<endpoint_definition>
get_subscriber() const210 remote_subscription::get_subscriber() const {
211     return subscriber_;
212 }
213 
214 void
set_subscriber(const std::shared_ptr<endpoint_definition> & _subscriber)215 remote_subscription::set_subscriber(
216         const std::shared_ptr<endpoint_definition> &_subscriber) {
217     subscriber_ = _subscriber;
218 }
219 
220 std::shared_ptr<endpoint_definition>
get_reliable() const221 remote_subscription::get_reliable() const {
222     return reliable_;
223 }
224 
225 void
set_reliable(const std::shared_ptr<endpoint_definition> & _reliable)226 remote_subscription::set_reliable(
227         const std::shared_ptr<endpoint_definition> &_reliable) {
228     reliable_ = _reliable;
229 }
230 
231 std::shared_ptr<endpoint_definition>
get_unreliable() const232 remote_subscription::get_unreliable() const {
233     return unreliable_;
234 }
235 
236 void
set_unreliable(const std::shared_ptr<endpoint_definition> & _unreliable)237 remote_subscription::set_unreliable(
238         const std::shared_ptr<endpoint_definition> &_unreliable) {
239     unreliable_ = _unreliable;
240 }
241 
242 bool
is_pending() const243 remote_subscription::is_pending() const {
244     std::lock_guard<std::mutex> its_lock(mutex_);
245     for (auto its_client : clients_) {
246         if (its_client.second.first
247                 == remote_subscription_state_e::SUBSCRIPTION_PENDING) {
248             return true;
249         }
250     }
251     return false;
252 }
253 
254 bool
is_acknowledged() const255 remote_subscription::is_acknowledged() const {
256     std::lock_guard<std::mutex> its_lock(mutex_);
257     for (auto its_client : clients_) {
258         if (its_client.second.first
259                 != remote_subscription_state_e::SUBSCRIPTION_ACKED) {
260             return false;
261         }
262     }
263     return true;
264 }
265 
266 std::chrono::steady_clock::time_point
get_expiration(const client_t _client) const267 remote_subscription::get_expiration(const client_t _client) const {
268     std::lock_guard<std::mutex> its_lock(mutex_);
269     auto found_client = clients_.find(_client);
270     if (found_client != clients_.end()) {
271         return found_client->second.second;
272     }
273     return std::chrono::steady_clock::now();
274 }
275 
276 std::set<client_t>
update(const std::set<client_t> & _clients,const std::chrono::steady_clock::time_point & _timepoint,const bool _is_subscribe)277 remote_subscription::update(const std::set<client_t> &_clients,
278         const std::chrono::steady_clock::time_point &_timepoint,
279         const bool _is_subscribe) {
280     std::set<client_t> its_changed;
281 
282     std::lock_guard<std::mutex> its_lock(mutex_);
283     for (const auto &its_client : _clients) {
284         auto found_client = clients_.find(its_client);
285         if (_is_subscribe) {
286             if (found_client != clients_.end()) {
287                 found_client->second.second = _timepoint;
288             } else {
289                 its_changed.insert(its_client);
290             }
291         } else {
292             if (found_client != clients_.end()) {
293                 its_changed.insert(its_client);
294             }
295         }
296     }
297 
298     for (const auto &its_client : its_changed) {
299         if (_is_subscribe) {
300             clients_[its_client] = std::make_pair(
301                     remote_subscription_state_e::SUBSCRIPTION_PENDING, _timepoint);
302         } else {
303             clients_.erase(its_client);
304         }
305     }
306 
307     return its_changed;
308 }
309 
310 std::shared_ptr<remote_subscription>
get_parent() const311 remote_subscription::get_parent() const {
312     return parent_.lock();
313 }
314 
315 void
set_parent(const std::shared_ptr<remote_subscription> & _parent)316 remote_subscription::set_parent(
317         const std::shared_ptr<remote_subscription> &_parent) {
318     parent_ = _parent;
319 }
320 
321 std::uint32_t
get_answers() const322 remote_subscription::get_answers() const {
323     return answers_;
324 }
325 
326 void
set_answers(const std::uint32_t _answers)327 remote_subscription::set_answers(const std::uint32_t _answers) {
328     answers_ = _answers;
329 }
330 
331 bool
get_ip_address(boost::asio::ip::address & _address) const332 remote_subscription::get_ip_address(boost::asio::ip::address &_address) const {
333     if (reliable_) {
334         _address = reliable_->get_address();
335         return true;
336     }
337     else if (unreliable_) {
338         _address = unreliable_->get_address();
339         return true;
340     }
341     return false;
342 }
343 
344 } // namespace vsomeip_v3
345