1 #ifndef DOIPMESSAGE_IMPROVED_H
2 #define DOIPMESSAGE_IMPROVED_H
141 template <
typename Iterator>
156 uint16_t type_value = (
static_cast<uint16_t
>(
m_data[2]) << 8) |
m_data[3];
266 return result && payloadRef.second >= 2;
317 return DoIpVin(payloadRef.first, 17);
330 return DoIpEid(payloadRef.first + 19, 6);
343 return DoIpGid(payloadRef.first + 25, 6);
384 uint8_t version =
data[offset];
385 uint8_t version_inv =
data[offset + 1];
389 version + version_inv == 0xFF;
399 static std::optional<std::pair<DoIPPayloadType, uint32_t>>
tryParseHeader(
const uint8_t *
data,
size_t length) {
415 return std::make_pair(payloadType.value(), payloadLength);
425 static std::optional<DoIPMessage>
tryParse(
const uint8_t *
data,
size_t length) {
427 if (!optHeader.has_value()) {
432 if (length < DOIP_HEADER_SIZE + optHeader->second) {
464 uint32_t payloadLength =
static_cast<uint32_t
>(payload.size());
468 m_data.insert(
m_data.end(), payload.begin(), payload.end());
537 payload.reserve(vin.
size() +
sizeof(logicalAddress) + entityType.
size() + groupId.
size() + 2);
539 payload.insert(payload.end(), vin.
begin(), vin.
end());
541 payload.insert(payload.end(), entityType.
begin(), entityType.
end());
542 payload.insert(payload.end(), groupId.
begin(), groupId.
end());
573 payload.reserve(
sizeof(sa) +
sizeof(ta) + msg_payload.size());
577 payload.insert(payload.end(), msg_payload.begin(), msg_payload.end());
596 payload.reserve(
sizeof(sa) +
sizeof(ta) + msg_payload.size() + 1);
601 payload.insert(payload.end(), msg_payload.begin(), msg_payload.end());
622 payload.reserve(
sizeof(sa) +
sizeof(ta) + msg_payload.size() + 1);
626 payload.emplace_back(
static_cast<uint8_t
>(nack));
627 payload.insert(payload.end(), msg_payload.begin(), msg_payload.end());
665 payload.reserve(
sizeof(ea) + 1 + 4);
669 payload.insert(payload.end(), {0, 0, 0, 0});
688 payload.reserve(
sizeof(ea) + 1 + 4);
691 if (optSourceAddress) {
696 payload.emplace_back(
static_cast<uint8_t
>(actType));
698 payload.insert(payload.end(), {0, 0, 0, 0});
715 os <<
ansi::dim <<
"V" << std::hex << std::uppercase << std::setw(2) << std::setfill(
'0')
720 if (payload.first ==
nullptr || payload.second < 1) {
721 os <<
ansi::red <<
"|Diag NACK <invalid>";
729 os <<
ansi::green <<
"|Alive Check " << sa.value() <<
" ✓";
732 os <<
ansi::yellow <<
"|Routing activation? " << sa.value();
736 os <<
ansi::green <<
"|Routing activation " << sa.value() <<
" ✓";
748 for (
size_t i = 0; i < payload.second; ++i) {
751 os << std::hex << std::uppercase << std::setw(2) << std::setfill(
'0')
752 <<
static_cast<unsigned int>(payload.first[i]);
761 for (
size_t i = 0; i < payload.second; ++i) {
764 os << std::hex << std::uppercase << std::setw(2) << std::setfill(
'0')
765 <<
static_cast<unsigned int>(payload.first[i]);
Defines the ByteArray type and utility functions for byte manipulation.
DoIPRoutingActivationType
Represents a complete DoIP message with internal ByteArray representation.
void buildMessage(DoIPPayloadType payloadType, const ByteArray &payload)
Builds the internal message representation.
static std::optional< DoIPMessage > tryParse(const uint8_t *data, size_t length)
Parse a DoIP message from raw data.
DoIPMessage(DoIPPayloadType payloadType, ByteArray &&payload)
Constructs a DoIP message with payload type and data (move semantics).
DoIPMessage()
Default constructor - creates invalid empty message.
std::optional< DoIPAddress > getSourceAddress() const
Get the Source Address of the message (if message is a Diagnostic Message).
DoIPMessage(DoIPPayloadType payloadType, const ByteArray &payload)
Constructs a DoIP message with payload type and data.
std::optional< DoIPAddress > getLogicalAddress() const
Get the Logical Address of the message (if message is a Vehicle Identification Response).
bool isValid() const
Checks if the message is valid.
bool isValidProtocolVersion() const
Checks if the protocol version is valid.
size_t getPayloadSize() const
Gets the payload size in bytes (without header).
uint32_t getPayloadLengthFromHeader() const
Gets the payload length from the header.
DoIPMessage(DoIPPayloadType payloadType, const uint8_t *data, size_t size)
Constructs a DoIP message from raw byte array.
static bool isValidProtocolVersion(const uint8_t *data, size_t length, size_t offset=0)
Checks if the protocol version is valid.
static std::optional< std::pair< DoIPPayloadType, uint32_t > > tryParseHeader(const uint8_t *data, size_t length)
Gets the payload type from raw data.
size_t getMessageSize() const
Get the complete message size (header + payload).
size_t size() const
Gets the size for use with legacy APIs.
ByteArray copyAsByteArray() const
Get a copy of the complete message as ByteArray.
std::optional< DoIpEid > getEid() const
Get the entity id (EID) if message is a Vehicle Identification Response.
DoIPMessage(DoIPPayloadType payloadType, std::initializer_list< uint8_t > init_list)
Constructs a DoIP message with payload type and initializer list.
const ByteArray & asByteArray() const
Get the complete message as ByteArray.
std::optional< DoIpVin > getVin() const
Get the vehicle identification number (VIN) if message is a Vehicle Identification Response.
const uint8_t * data() const
Gets direct pointer to the message data (for legacy APIs).
std::optional< DoIPFurtherAction > getFurtherActionRequest() const
Get the Further Action Request object if message is a Vehicle Identification Response.
bool hasSourceAddress() const
Check if the message has a Source Address field.
DoIPPayloadType getPayloadType() const
Gets the payload type of this message.
std::optional< DoIpGid > getGid() const
Get the group id (GID) if message is a Vehicle Identification Response.
ByteArrayRef getDiagnosticMessagePayload() const
Gets the payload data (without header).
ByteArray m_data
Complete message data (header + payload)
ByteArrayRef getData() const
Gets direct access to the complete message data for sending.
DoIPMessage(DoIPPayloadType payloadType, Iterator first, Iterator last)
Constructs a DoIP message from iterator range.
ByteArrayRef getPayload() const
Gets the payload data (without header).
std::optional< DoIPAddress > getTargetAddress() const
Get the Target Address of the message (if message is a Diagnostic Message).
constexpr size_t size() const
Get the size (always IdLength)
auto end() noexcept
Iterator support - end.
auto begin() noexcept
Iterator support - begin.
constexpr const char * bold_white
constexpr const char * bold_magenta
constexpr const char * red
constexpr const char * bold_blue
constexpr const char * reset
constexpr const char * yellow
constexpr const char * cyan
constexpr const char * dim
constexpr const char * green
DoIPMessage makeDiagnosticPositiveResponse(const DoIPAddress &sa, const DoIPAddress &ta, const ByteArray &msg_payload)
void b
DoIPMessage makeAliveCheckResponse(const DoIPAddress &sa)
Create an 'alive check' response.
DoIPMessage makeNegativeAckMessage(DoIPNegativeAck nack)
Creates a generic DoIP negative response (NACK).
DoIPMessage makeAliveCheckRequest()
Create an 'alive check' request.
DoIPMessage makeVehicleIdentificationRequest()
Creates a vehicle identification request message.
DoIPMessage makeVehicleIdentificationResponse(const DoIpVin &vin, const DoIPAddress &logicalAddress, const DoIpEid &entityType, const DoIpGid &groupId, DoIPFurtherAction furtherAction=DoIPFurtherAction::NoFurtherAction, DoIPSyncStatus syncStatus=DoIPSyncStatus::GidVinSynchronized)
Creates a vehicle identification response message.
DoIPMessage makeDiagnosticNegativeResponse(const DoIPAddress &sa, const DoIPAddress &ta, DoIPNegativeDiagnosticAck nack, const ByteArray &msg_payload)
Creates a diagnostic negative ACK message (NACK).
DoIPMessage makeDiagnosticMessage(const DoIPAddress &sa, const DoIPAddress &ta, const ByteArray &msg_payload)
Creates a diagnostic message.
DoIPMessage makeRoutingActivationResponse(const DoIPMessage &routingReq, const DoIPAddress &ea, DoIPRoutingActivationType actType=DoIPRoutingActivationType::Default)
Creates a routing activation response message.
DoIPMessage makeRoutingActivationRequest(const DoIPAddress &ea, DoIPRoutingActivationType actType=DoIPRoutingActivationType::Default)
Creates a routing activation request message.
uint32_t readU32BE(const uint8_t *data, size_t index)
Reads a 32-bit unsigned integer in big-endian format from a byte array.
constexpr uint8_t ISO_13400_2019
ISO 13400-2:2019.
uint16_t DoIPAddress
Represents a 16-bit DoIP address consisting of high and low significant bytes.
constexpr size_t DOIP_HEADER_SIZE
Size of the DoIP header.
constexpr uint8_t ISO_13400_2012
ISO 13400-2:2012.
GenericFixedId< 17, true, '0'> DoIpVin
Vehicle Identification Number (VIN) - 17 bytes according to ISO 3779 Padded with ASCII '0' characters...
constexpr uint8_t PROTOCOL_VERSION_INV
std::pair< const uint8_t *, size_t > ByteArrayRef
Reference to raw array of bytes.
constexpr uint8_t ISO_13400_2010
ISO/DIS 13400-2:2010.
DoIPNegativeDiagnosticAck
std::ostream & operator<<(std::ostream &os, const ByteArray &arr)
Stream operator for ByteArray.
DoIPPayloadType
DoIP Payload Type identifiers according to ISO 13400-2.
@ DiagnosticMessageAck
Diagnostic Message Positive Acknowledgement Positive acknowledgement of a diagnostic message.
@ DiagnosticMessage
Diagnostic Message Payload for diagnostic communication (UDS, KWP, etc.).
@ AliveCheckResponse
Alive Check Response Response to an Alive Check Request.
@ RoutingActivationResponse
Routing Activation Response Response to a Routing Activation Request.
@ RoutingActivationRequest
Routing Activation Request Request to activate routing for a diagnostic connection.
@ VehicleIdentificationResponse
Vehicle Identification Response (Vehicle Announcement) Response to a Vehicle Identification Request o...
@ VehicleIdentificationRequest
Vehicle Identification Request Request for vehicle identification.
@ NegativeAck
Generic Negative Acknowledgement (NACK) Sent when a message cannot be processed.
@ DiagnosticMessageNegativeAck
Diagnostic Message Negative Acknowledgement Negative acknowledgement of a diagnostic message.
@ AliveCheckRequest
Alive Check Request Request to check if the connection is still alive.
std::optional< DoIPMessage > OptDoIPMessage
DoIPAddress readAddressFrom(const uint8_t *data, size_t offset=0)
Reads the DoIP address from a byte array.
constexpr size_t DOIP_DIAG_HEADER_SIZE
Size of the DoIP diagnostic message header.
constexpr uint8_t PROTOCOL_VERSION
Current protocol version (table 16)
constexpr uint8_t ISO_13400_2025
ISO 13400-2:2019/Amd1, ISO 13400-2:2025.
constexpr std::optional< DoIPPayloadType > toPayloadType(uint16_t value) noexcept
Safely converts uint16_t to DoIPPayloadType with validation.
GenericFixedId< 6, false > DoIpEid
Entity Identifier (EID) - 6 bytes for unique entity identification.
constexpr uint8_t DIAGNOSTIC_MESSAGE_ACK
Positive ack for diagnostic message (table 24)
GenericFixedId< 6, false > DoIpGid
Group Identifier (GID) - 6 bytes for group identification.
A dynamic array of bytes with utility methods for network protocol handling.
void writeU32BE(uint32_t value)
Appends a 32-bit unsigned integer in big-endian format to the end.
uint32_t readU32BE(size_t index) const
Reads a 32-bit unsigned integer in big-endian format from a specific index.
void writeU16BE(uint16_t value)
Appends a 16-bit unsigned integer in big-endian format to the end.