1 // Copyright (C) 2019 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 <vsomeip/primitive_types.hpp>
7 #include <vsomeip/defines.hpp>
8 #include <vsomeip/internal/logger.hpp>
9
10 #include "../include/tp.hpp"
11 #include "../../utility/include/byteorder.hpp"
12
13 #ifdef ANDROID
14 #include "../../configuration/include/internal_android.hpp"
15 #else
16 #include "../../configuration/include/internal.hpp"
17 #endif // ANDROID
18
19 #ifndef _WIN32
20 #include <arpa/inet.h>
21 #else
22 #include <Winsock2.h>
23 #endif
24
25
26 namespace vsomeip_v3 {
27 namespace tp {
28
29 const std::uint16_t tp::tp_max_segment_length_ = 1392;
30
tp_split_message(const std::uint8_t * const _data,std::uint32_t _size)31 tp_split_messages_t tp::tp_split_message(const std::uint8_t * const _data,
32 std::uint32_t _size) {
33 tp_split_messages_t split_messages;
34
35 if (_size < VSOMEIP_MAX_UDP_MESSAGE_SIZE) {
36 VSOMEIP_ERROR << __func__ << " called with size: " << std::dec << _size;
37 return split_messages;
38 }
39
40 const auto data_end = _data + _size;
41
42 for (auto current_offset = _data + VSOMEIP_FULL_HEADER_SIZE; current_offset < data_end;) {
43 auto msg = std::make_shared<message_buffer_t>();
44 msg->reserve(VSOMEIP_FULL_HEADER_SIZE + sizeof(tp_header_t) + tp_max_segment_length_);
45 // copy the header
46 msg->insert(msg->end(), _data, _data + VSOMEIP_FULL_HEADER_SIZE);
47 // change the message type
48 (*msg)[VSOMEIP_MESSAGE_TYPE_POS] = (*msg)[VSOMEIP_MESSAGE_TYPE_POS] | 0x20;
49 // check if last segment
50 const auto segment_end = current_offset + tp_max_segment_length_;
51 const bool is_last_segment = (segment_end >= data_end);
52 // insert tp_header
53 const tp_header_t header = htonl(
54 static_cast<tp_header_t>((current_offset - VSOMEIP_FULL_HEADER_SIZE - _data)) |
55 static_cast<tp_header_t>((is_last_segment) ? 0x0u : 0x1u));
56
57 const byte_t * const headerp = reinterpret_cast<const byte_t*>(&header);
58 msg->insert(msg->end(), headerp, headerp + sizeof(tp_header_t));
59
60 // insert payload
61 if (is_last_segment) {
62 msg->insert(msg->end(), current_offset, data_end);
63 current_offset = data_end;
64 } else {
65 msg->insert(msg->end(), current_offset, segment_end);
66 current_offset += tp_max_segment_length_;
67 }
68 // update length
69 const length_t its_length = static_cast<length_t>(msg->size()
70 - VSOMEIP_SOMEIP_HEADER_SIZE);
71 *(reinterpret_cast<length_t*>(&(*msg)[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length);
72 split_messages.emplace_back(std::move(msg));
73 }
74
75 return split_messages;
76 }
77
78 } // namespace tp
79 } // namespace vsomeip_v3
80