Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2026 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : #include "someip/TpSender.h"
12 :
13 : #include "someip/ITpTransceiver.h"
14 : #include "someip/NetworkChannel.h"
15 : #include "someip/SomeIpConstants.h"
16 : #include "someip/logger.h"
17 :
18 : #include <etl/algorithm.h>
19 : #include <etl/unaligned_type.h>
20 :
21 : namespace someip
22 : {
23 : using ::util::logger::SOMEIP;
24 :
25 9 : TpSender::TpResult TpSender::send(NetworkChannel& channel, SomeIpMessage const& message)
26 : {
27 9 : if (_buffer.size() < UDP_PACKET_MAX_SIZE)
28 : {
29 1 : ERROR_LOG(
30 : SOMEIP, "TpSender[%p]::send(): buffer of %d bytes too small!", this, _buffer.size());
31 :
32 1 : return TpSender::TpResult::TP_ERROR;
33 : }
34 :
35 8 : auto const header = message.getBufferHeader();
36 8 : auto const payload = message.getBufferPayload();
37 :
38 8 : size_t const payloadLength = message.getPayloadLength();
39 8 : size_t payloadOffset = 0U;
40 :
41 : do
42 : {
43 12 : size_t const payloadLeft = payloadLength - payloadOffset;
44 12 : size_t const chunkLength
45 : = (payloadLeft > TP_PAYLOAD_MAX_SIZE) ? TP_PAYLOAD_MAX_SIZE : payloadLeft;
46 12 : ::etl::span<uint8_t const> const chunk = payload.subspan(payloadOffset, chunkLength);
47 :
48 12 : SomeIpMessage tpMessage(_buffer);
49 12 : size_t packetOffset = 0U;
50 :
51 : // copy msg-header
52 12 : auto dest = _buffer.subspan(packetOffset);
53 12 : etl::copy(header.begin(), header.end(), dest.begin());
54 12 : packetOffset += header.size();
55 :
56 : // adjust msg-header
57 12 : tpMessage.setRawMessageType(
58 12 : message.getRawMessageType()
59 12 : | static_cast<uint8_t>(ITpTransceiver::TP_MESSAGE_TYPE_BIT_MASK));
60 12 : tpMessage.setPayloadLength(
61 : static_cast<uint32_t>(ITpTransceiver::TP_HEADER_LENGTH + chunkLength));
62 :
63 : // add tp-header
64 12 : ITpTransceiver::TpHeader tpHeader{};
65 12 : tpHeader.payloadOffset = static_cast<uint32_t>(payloadOffset);
66 12 : tpHeader.hasMoreSegments = ((payloadLeft - chunkLength) > 0U);
67 12 : ::etl::be_uint32_ext_t{&_buffer[packetOffset]}
68 24 : = ITpTransceiver::serializeTpHeader(tpHeader);
69 12 : packetOffset += ITpTransceiver::TP_HEADER_LENGTH;
70 :
71 : // copy payload
72 12 : dest = _buffer.subspan(packetOffset);
73 12 : etl::copy(chunk.begin(), chunk.end(), dest.begin());
74 12 : packetOffset += chunk.size();
75 :
76 12 : INFO_LOG(
77 : SOMEIP,
78 : "TpSender[%p]::send(): id: 0x%X, type: 0x%X => %d bytes",
79 : this,
80 : tpMessage.getMessageId(),
81 : tpMessage.getMessageType(),
82 : packetOffset);
83 :
84 12 : if (!channel.send(static_cast<uint32_t>(packetOffset), _buffer))
85 : {
86 2 : ERROR_LOG(
87 : SOMEIP,
88 : "TpSender[%p]::send(): send failed at offset %d of %d bytes payload",
89 : this,
90 : payloadOffset,
91 : payloadLength);
92 :
93 2 : return TpSender::TpResult::TP_ERROR;
94 : }
95 :
96 10 : payloadOffset += chunkLength;
97 :
98 10 : } while ((payloadLength - payloadOffset) > 0);
99 :
100 6 : return TpSender::TpResult::TP_OK;
101 : }
102 :
103 : } // namespace someip
|