mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
Device/Disk: Add VSA read and parse functionality
Implement ability to extract network traffic (CAN, LIN, Ethernet, etc.) from VSA message records on disk. Add a method to Device class that uses the VSAParser and the individual record types to extract messages from the VSA message records and pass them back to the communication system. This routes messages such that it appears as if they were discovered live instead of read from disk. The parse process (in Device) requires determination of metadata about the VSA file system on a device before it can begin extracting messages. This currently only handles data captured from the current coremini script on a device.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
#include "icsneo/disk/vsa/vsa0d.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static constexpr auto FirstPayloadOffset = 8;
|
||||
static constexpr auto FirstPayloadSize = 12;
|
||||
static constexpr auto ConsecutivePayloadOffset = 4;
|
||||
static constexpr auto LastPayloadSize = 24;
|
||||
static constexpr auto OtherPayloadSize = 28;
|
||||
|
||||
// Parent class functions
|
||||
|
||||
VSA0D::VSA0D(uint8_t* const recordBytes, uint8_t* const messageBytes, size_t numBytes, uint32_t& runningChecksum, Network::CoreMini networkId)
|
||||
: VSAExtendedMessage(messageBytes, numBytes, networkId)
|
||||
{
|
||||
static constexpr auto DWordSize = 4;
|
||||
setType(VSA::Type::AA0D);
|
||||
setIndex(*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0x01FFu);
|
||||
setSequenceNum((*reinterpret_cast<uint16_t*>(recordBytes + 2) & 0xFE00u) >> 9);
|
||||
uint32_t* dwords = reinterpret_cast<uint32_t*>(payload.data());
|
||||
for(size_t i = 0; i < payload.size() / DWordSize; i++) {
|
||||
runningChecksum += dwords[i];
|
||||
}
|
||||
}
|
||||
|
||||
// First Record Functions
|
||||
|
||||
VSA0DFirst::VSA0DFirst(uint8_t* const recordBytes, uint32_t& runningChecksum)
|
||||
: VSA0D(recordBytes, recordBytes + FirstPayloadOffset, FirstPayloadSize, runningChecksum, static_cast<Network::CoreMini>(recordBytes[29]))
|
||||
{
|
||||
captureBitfield = *reinterpret_cast<uint16_t*>(recordBytes + 4);
|
||||
setRecordCount(*reinterpret_cast<uint16_t*>(recordBytes + 6));
|
||||
timestamp = *reinterpret_cast<uint64_t*>(recordBytes + 20) & UINT63_MAX;
|
||||
vNetInfo = *reinterpret_cast<VNet*>(recordBytes + 28);
|
||||
checksum = *reinterpret_cast<uint16_t*>(recordBytes + 30);
|
||||
doChecksum(recordBytes);
|
||||
uint32_t* const timestampDWords = reinterpret_cast<uint32_t*>(timestamp);
|
||||
runningChecksum += timestampDWords[0];
|
||||
runningChecksum += timestampDWords[1];
|
||||
}
|
||||
|
||||
void VSA0DFirst::doChecksum(uint8_t* recordBytes)
|
||||
{
|
||||
uint16_t* words = reinterpret_cast<uint16_t*>(recordBytes);
|
||||
uint16_t sum = 0;
|
||||
for(size_t i = 0; i < 15; i++) {
|
||||
sum += words[i];
|
||||
}
|
||||
setChecksumFailed(sum != checksum);
|
||||
}
|
||||
|
||||
void VSA0DFirst::reservePacketData(std::shared_ptr<Packet>& packet) const
|
||||
{
|
||||
uint32_t numMessageBytes = (getRecordCount() - 2) * OtherPayloadSize + FirstPayloadSize + LastPayloadSize;
|
||||
packet->data.reserve(numMessageBytes);
|
||||
}
|
||||
|
||||
void VSA0DFirst::reorderPayload(std::vector<uint8_t>& secondPayload)
|
||||
{
|
||||
std::vector<uint8_t> tempPayload;
|
||||
tempPayload.insert(tempPayload.end(), secondPayload.begin(), secondPayload.begin() + 4);
|
||||
uint8_t* timestampBytes = reinterpret_cast<uint8_t*>(×tamp);
|
||||
tempPayload.insert(tempPayload.end(), timestampBytes, timestampBytes + 8);
|
||||
tempPayload.insert(tempPayload.end(), secondPayload.begin() + 4, secondPayload.end());
|
||||
payload.clear();
|
||||
secondPayload.clear();
|
||||
payload.insert(payload.end(), tempPayload.begin(), tempPayload.begin() + 12); // This is done because the capacity of payload is already 12
|
||||
secondPayload.insert(secondPayload.end(), tempPayload.begin() + 12, tempPayload.end());
|
||||
}
|
||||
|
||||
bool VSA0DFirst::filter(const std::shared_ptr<VSAMessageReadFilter> filter)
|
||||
{
|
||||
if((filter->captureBitfield != captureBitfield && filter->captureBitfield != UINT16_MAX) ||
|
||||
getICSTimestampFromTimepoint(filter->readRange.first) > timestamp ||
|
||||
getICSTimestampFromTimepoint(filter->readRange.second) < timestamp) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Consecutive Record Functions
|
||||
|
||||
VSA0DConsecutive::VSA0DConsecutive(uint8_t* const recordBytes, uint32_t& runningChecksum, std::shared_ptr<VSA0DFirst> first, bool isLastRecord)
|
||||
: VSA0D(recordBytes, recordBytes + ConsecutivePayloadOffset, isLastRecord ? LastPayloadSize : OtherPayloadSize, runningChecksum)
|
||||
{
|
||||
this->first = first;
|
||||
calculatedChecksum = runningChecksum;
|
||||
if(getIndex() == 1) {
|
||||
first->reorderPayload(payload);
|
||||
} else if(isLastRecord) {
|
||||
recordChecksum = *reinterpret_cast<uint32_t*>(recordBytes + 28);
|
||||
doChecksum(recordBytes);
|
||||
} else {
|
||||
setChecksumFailed(first->getChecksumFailed());
|
||||
}
|
||||
setRecordCount(first->getRecordCount());
|
||||
}
|
||||
|
||||
void VSA0DConsecutive::doChecksum(uint8_t* recordBytes)
|
||||
{
|
||||
setChecksumFailed(recordBytes && calculatedChecksum != recordChecksum);
|
||||
}
|
||||
Reference in New Issue
Block a user