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