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