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 #include <typeinfo>
7 
8 #include <vsomeip/constants.hpp>
9 #include <vsomeip/defines.hpp>
10 #include <vsomeip/internal/logger.hpp>
11 
12 // internal[_android.hpp] must be included before defines.hpp
13 #ifdef ANDROID
14 #include "../../configuration/include/internal_android.hpp"
15 #else
16 #include "../../configuration/include/internal.hpp"
17 #endif // ANDROID
18 
19 #include "../include/constants.hpp"
20 #include "../include/defines.hpp"
21 #include "../include/eventgroupentry_impl.hpp"
22 #include "../include/serviceentry_impl.hpp"
23 #include "../include/configuration_option_impl.hpp"
24 #include "../include/ipv4_option_impl.hpp"
25 #include "../include/ipv6_option_impl.hpp"
26 #include "../include/load_balancing_option_impl.hpp"
27 #include "../include/protection_option_impl.hpp"
28 #include "../include/selective_option_impl.hpp"
29 #include "../include/message_impl.hpp"
30 #include "../../message/include/deserializer.hpp"
31 #include "../../message/include/payload_impl.hpp"
32 #include "../../message/include/serializer.hpp"
33 
34 namespace vsomeip_v3 {
35 namespace sd {
36 
message_impl()37 message_impl::message_impl() :
38     flags_(0x0),
39     options_length_(0x0),
40     current_message_size_(VSOMEIP_SOMEIP_SD_EMPTY_MESSAGE_SIZE) {
41     header_.service_ = VSOMEIP_SD_SERVICE;
42     header_.instance_ = VSOMEIP_SD_INSTANCE;
43     header_.method_ = VSOMEIP_SD_METHOD;
44     header_.client_ = VSOMEIP_SD_CLIENT;
45     // session must be set dynamically
46     header_.protocol_version_ = protocol_version;
47     header_.interface_version_ = interface_version;
48     header_.type_ = message_type;
49     header_.code_ = return_code;
50 
51     set_unicast_flag(true);
52 }
53 
~message_impl()54 message_impl::~message_impl() {
55 }
56 
get_length() const57 length_t message_impl::get_length() const {
58     length_t current_length = VSOMEIP_SOMEIP_SD_DATA_SIZE;
59     if( entries_.size()) {
60         current_length += VSOMEIP_SOMEIP_SD_ENTRY_LENGTH_SIZE;
61         current_length += uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
62     }
63 
64     current_length += VSOMEIP_SOMEIP_SD_OPTION_LENGTH_SIZE;
65     if(options_.size()) {
66         for (size_t i = 0; i < options_.size(); ++i) {
67             current_length += static_cast<length_t>(options_[i]->get_length()
68                     + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE);
69         }
70     }
71     return current_length;
72 }
73 
get_size() const74 length_t message_impl::get_size() const {
75     return current_message_size_;
76 }
77 
78 #define VSOMEIP_REBOOT_FLAG 0x80
79 
get_reboot_flag() const80 bool message_impl::get_reboot_flag() const {
81     return ((flags_ & VSOMEIP_REBOOT_FLAG) != 0);
82 }
83 
set_reboot_flag(bool _is_set)84 void message_impl::set_reboot_flag(bool _is_set) {
85     if (_is_set)
86         flags_ |= flags_t(VSOMEIP_REBOOT_FLAG);
87     else
88         flags_ &= flags_t(~VSOMEIP_REBOOT_FLAG);
89 }
90 
91 #define VSOMEIP_UNICAST_FLAG 0x40
92 
get_unicast_flag() const93 bool message_impl::get_unicast_flag() const {
94     return ((flags_ & VSOMEIP_UNICAST_FLAG) != 0);
95 }
96 
set_unicast_flag(bool _is_set)97 void message_impl::set_unicast_flag(bool _is_set) {
98     if (_is_set)
99         flags_ |= flags_t(VSOMEIP_UNICAST_FLAG);
100     else
101         flags_ &= flags_t(~VSOMEIP_UNICAST_FLAG);
102 }
103 
104 bool
add_entry_data(const std::shared_ptr<entry_impl> & _entry,const std::vector<std::shared_ptr<option_impl>> & _options,const std::shared_ptr<entry_impl> & _other)105 message_impl::add_entry_data(const std::shared_ptr<entry_impl> &_entry,
106         const std::vector<std::shared_ptr<option_impl> > &_options,
107         const std::shared_ptr<entry_impl> &_other) {
108     std::uint32_t its_entry_size = VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
109     std::map<const std::shared_ptr<option_impl>, bool> its_options;
110 
111     if (_other) {
112         its_entry_size += VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
113     }
114 
115     // TODO: Check whether it is possible to express the options
116     // by the two runs. If there are more than two options, it
117     // might be necessary to copy an option, which then increases
118     // the size...
119 
120     for (const std::shared_ptr<option_impl> &its_option : _options) {
121         const auto its_existing_option = find_option(its_option);
122         if (!its_existing_option) {
123             its_entry_size += its_option->get_size();
124             its_options[its_option] = true;
125         } else {
126             its_options[its_existing_option] = false;
127         }
128     }
129 
130     if (current_message_size_ + its_entry_size > VSOMEIP_MAX_UDP_SD_PAYLOAD)
131         return false;
132 
133     entries_.push_back(_entry);
134     _entry->set_owning_message(this);
135     for (const auto &its_option : its_options) {
136         if (its_option.second) {
137             options_.push_back(its_option.first);
138             its_option.first->set_owning_message(this);
139         }
140         _entry->assign_option(its_option.first);
141     }
142 
143     if (_other) {
144         entries_.push_back(_other);
145         _other->set_owning_message(this);
146         for (const auto &its_option : its_options) {
147             _other->assign_option(its_option.first);
148         }
149     }
150 
151     current_message_size_ += its_entry_size;
152 
153     return true;
154 }
155 
156 bool
has_entry() const157 message_impl::has_entry() const {
158     return (0 < entries_.size());
159 }
160 
161 bool
has_option() const162 message_impl::has_option() const {
163     return (0 < options_.size());
164 }
165 
set_length(length_t _length)166 void message_impl::set_length(length_t _length) {
167     (void)_length;
168 }
169 
get_entries() const170 const message_impl::entries_t & message_impl::get_entries() const {
171     return entries_;
172 }
173 
get_options() const174 const message_impl::options_t & message_impl::get_options() const {
175     return options_;
176 }
177 
178 std::shared_ptr<option_impl>
find_option(const std::shared_ptr<option_impl> & _option) const179 message_impl::find_option(const std::shared_ptr<option_impl> &_option) const {
180     for (auto its_option : options_) {
181         if (its_option->equals(_option))
182             return its_option;
183     }
184     return nullptr;
185 }
186 
get_option_index(const std::shared_ptr<option_impl> & _option) const187 int16_t message_impl::get_option_index(
188         const std::shared_ptr<option_impl> &_option) const {
189     int16_t i = 0;
190 
191     while (i < int16_t(options_.size())) {
192         if (options_[static_cast<options_t::size_type>(i)] == _option)
193             return i;
194         i++;
195     }
196     return -1;
197 }
198 
199 std::shared_ptr<option_impl>
get_option(int16_t _index) const200 message_impl::get_option(int16_t _index) const {
201     if (_index > -1) {
202         size_t its_index = static_cast<size_t>(_index);
203         if (its_index < options_.size())
204             return options_[its_index];
205     }
206     return nullptr;
207 }
208 
get_options_length()209 uint32_t message_impl::get_options_length() {
210     return options_length_;
211 }
212 
get_payload() const213 std::shared_ptr<payload> message_impl::get_payload() const {
214     return std::make_shared<payload_impl>();
215 }
216 
set_payload(std::shared_ptr<payload> _payload)217 void message_impl::set_payload(std::shared_ptr<payload> _payload) {
218     (void)_payload;
219 }
220 
get_check_result() const221 uint8_t message_impl::get_check_result() const {
222     return 1;
223 }
set_check_result(uint8_t _check_result)224 void message_impl::set_check_result(uint8_t _check_result) {
225     (void)_check_result;
226 }
227 
is_valid_crc() const228 bool message_impl::is_valid_crc() const {
229     return false;
230 }
231 
serialize(vsomeip_v3::serializer * _to) const232 bool message_impl::serialize(vsomeip_v3::serializer *_to) const {
233     bool is_successful = header_.serialize(_to);
234     is_successful = is_successful && _to->serialize(flags_);
235     is_successful = is_successful
236             && _to->serialize(protocol::reserved_long, true);
237 
238     uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
239     is_successful = is_successful && _to->serialize(entries_length);
240 
241     for (const auto& its_entry : entries_)
242         is_successful = is_successful && its_entry && its_entry->serialize(_to);
243 
244     uint32_t options_length = 0;
245     for (const auto& its_option : options_)
246         options_length += its_option ? static_cast<uint32_t>(its_option->get_length()
247                 + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE) : 0;
248     is_successful = is_successful && _to->serialize(options_length);
249 
250     for (const auto& its_option : options_)
251         is_successful = is_successful && its_option && its_option->serialize(_to);
252 
253     return is_successful;
254 }
255 
deserialize(vsomeip_v3::deserializer * _from)256 bool message_impl::deserialize(vsomeip_v3::deserializer *_from) {
257     bool is_successful;
258     bool option_is_successful(true);
259 
260     // header
261     is_successful = header_.deserialize(_from);
262 
263     // flags
264     is_successful = is_successful && _from->deserialize(flags_);
265 
266     // reserved
267     uint32_t reserved;
268     is_successful = is_successful && _from->deserialize(reserved, true);
269 
270     // entries
271     uint32_t entries_length = 0;
272     is_successful = is_successful && _from->deserialize(entries_length);
273 
274     // backup the current remaining length
275     uint32_t save_remaining = uint32_t(_from->get_remaining());
276     if (!is_successful) {
277         // couldn't deserialize entries length
278         return is_successful;
279     } else if (entries_length > save_remaining) {
280         // not enough data available to deserialize entries array
281         is_successful = false;
282         return is_successful;
283     }
284 
285     // set remaining bytes to length of entries array
286     _from->set_remaining(entries_length);
287 
288     // deserialize the entries
289     while (is_successful && _from->get_remaining()) {
290         std::shared_ptr < entry_impl > its_entry(deserialize_entry(_from));
291         if (its_entry) {
292             entries_.push_back(its_entry);
293         } else {
294             is_successful = false;
295         }
296     }
297 
298     // set length to remaining bytes after entries array
299     _from->set_remaining(save_remaining - entries_length);
300 
301     // Don't try to deserialize options if there aren't any
302     if(_from->get_remaining() == 0) {
303         return is_successful;
304     }
305 
306     // deserialize the options
307     is_successful = is_successful && _from->deserialize(options_length_);
308 
309     // check if there is unreferenced data behind the last option and discard it
310     if(_from->get_remaining() > options_length_) {
311         _from->set_remaining(options_length_);
312     }
313 
314     while (option_is_successful && _from->get_remaining()) {
315         std::shared_ptr < option_impl > its_option(deserialize_option(_from));
316         if (its_option) {
317             options_.push_back(its_option);
318         }  else {
319             option_is_successful = false;
320         }
321     }
322     current_message_size_ = 0;
323     return is_successful;
324 }
325 
deserialize_entry(vsomeip_v3::deserializer * _from)326 entry_impl * message_impl::deserialize_entry(vsomeip_v3::deserializer *_from) {
327     entry_impl *deserialized_entry = 0;
328     uint8_t tmp_entry_type;
329 
330     if (_from->look_ahead(0, tmp_entry_type)) {
331         entry_type_e deserialized_entry_type =
332                 static_cast<entry_type_e>(tmp_entry_type);
333 
334         switch (deserialized_entry_type) {
335         case entry_type_e::FIND_SERVICE:
336         case entry_type_e::OFFER_SERVICE:
337             //case entry_type_e::STOP_OFFER_SERVICE:
338         case entry_type_e::REQUEST_SERVICE:
339             deserialized_entry = new serviceentry_impl;
340             break;
341 
342         case entry_type_e::FIND_EVENT_GROUP:
343         case entry_type_e::PUBLISH_EVENTGROUP:
344             //case entry_type_e::STOP_PUBLISH_EVENTGROUP:
345         case entry_type_e::SUBSCRIBE_EVENTGROUP:
346             //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP:
347         case entry_type_e::SUBSCRIBE_EVENTGROUP_ACK:
348             //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK:
349             deserialized_entry = new eventgroupentry_impl;
350             break;
351 
352         default:
353             break;
354         };
355 
356         // deserialize object
357         if (0 != deserialized_entry) {
358             deserialized_entry->set_owning_message(this);
359             if (!deserialized_entry->deserialize(_from)) {
360                 delete deserialized_entry;
361                 deserialized_entry = 0;
362             };
363         }
364     }
365 
366     return deserialized_entry;
367 }
368 
deserialize_option(vsomeip_v3::deserializer * _from)369 option_impl * message_impl::deserialize_option(vsomeip_v3::deserializer *_from) {
370     option_impl *deserialized_option = 0;
371     uint8_t tmp_option_type;
372 
373     if (_from->look_ahead(2, tmp_option_type)) {
374 
375         option_type_e deserialized_option_type =
376                 static_cast<option_type_e>(tmp_option_type);
377 
378         switch (deserialized_option_type) {
379 
380         case option_type_e::CONFIGURATION:
381             deserialized_option = new configuration_option_impl;
382             break;
383         case option_type_e::LOAD_BALANCING:
384             deserialized_option = new load_balancing_option_impl;
385             break;
386         case option_type_e::PROTECTION:
387             deserialized_option = new protection_option_impl;
388             break;
389         case option_type_e::IP4_ENDPOINT:
390         case option_type_e::IP4_MULTICAST:
391             deserialized_option = new ipv4_option_impl;
392             break;
393         case option_type_e::IP6_ENDPOINT:
394         case option_type_e::IP6_MULTICAST:
395             deserialized_option = new ipv6_option_impl;
396             break;
397         case option_type_e::SELECTIVE:
398             deserialized_option = new selective_option_impl;
399             break;
400 
401         default:
402             deserialized_option = new option_impl();
403             break;
404         };
405 
406         // deserialize object
407         if (0 != deserialized_option
408                 && !deserialized_option->deserialize(_from)) {
409             delete deserialized_option;
410             deserialized_option = 0;
411         };
412     }
413 
414     return deserialized_option;
415 }
416 
get_someip_length() const417 length_t message_impl::get_someip_length() const {
418     return header_.length_;
419 }
420 
get_uid() const421 uid_t message_impl::get_uid() const {
422     return ANY_UID;
423 }
424 
get_gid() const425 gid_t message_impl::get_gid() const {
426     return ANY_GID;
427 }
428 
429 
430 } // namespace sd
431 } // namespace vsomeip_v3
432