mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 09:28:40 +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,234 @@
|
||||
#ifndef __VSAPARSER_H__
|
||||
#define __VSAPARSER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/disk/vsa/vsa.h"
|
||||
#include "icsneo/disk/vsa/vsa0d.h"
|
||||
#include "icsneo/disk/vsa/vsa0e.h"
|
||||
#include "icsneo/disk/vsa/vsa0f.h"
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
/**
|
||||
* Class used to parse VSA records from bytestreams
|
||||
*/
|
||||
class VSAParser {
|
||||
public:
|
||||
/**
|
||||
* Struct that determines which types of VSA records to extract from disk
|
||||
*/
|
||||
struct Settings {
|
||||
bool extractAA02 = true; // Extract Logdata Records
|
||||
bool extractAA03 = true; // Extract Event Records
|
||||
bool extractAA04 = true; // Extract Partition Info Records
|
||||
bool extractAA05 = true; // Extract Application Error Records
|
||||
bool extractAA06 = true; // Extract Debug/Internal 1 Records
|
||||
bool extractAA07 = true; // Extract Debug/Internal 2 Records
|
||||
bool extractAA08 = true; // Extract Buffer Info Records
|
||||
bool extractAA09 = true; // Extract Device Info Records
|
||||
bool extractAA0B = true; // Extract Message Records
|
||||
bool extractAA0C = true; // Extract PCM Audio Records
|
||||
bool extractAA0D = true; // Extract Extended Message 1 Records
|
||||
bool extractAA0E = true; // Extract Extended Message 2 Records
|
||||
bool extractAA0F = true; // Extract Extended Message 3 Records
|
||||
bool extractAA6A = true; // Extract Logger Configuration Backup Records
|
||||
|
||||
std::shared_ptr<VSAMessageReadFilter> messageFilter = nullptr; // Used for post-read filtering of message records
|
||||
|
||||
/**
|
||||
* Static constructor for VSAParser::Settings that only extracts message records (AA0B, AA0D, AA0E, AA0F)
|
||||
*/
|
||||
static Settings messageRecords() { return { false, false, false, false, false, false, false, false, true, false, true, true, true, false }; }
|
||||
|
||||
/**
|
||||
* Operator overload for equivalency of VSAParser::Settings struct
|
||||
*
|
||||
* @param s The settings object to test against this settings object
|
||||
*
|
||||
* @return True if the extraction settings are the same. Does not check the filter
|
||||
*/
|
||||
bool operator==(const Settings& s)
|
||||
{
|
||||
return s.extractAA02 == this->extractAA02 && s.extractAA03 == this->extractAA03 && s.extractAA04 == this->extractAA04 &&
|
||||
s.extractAA05 == this->extractAA05 && s.extractAA06 == this->extractAA06 && s.extractAA07 == this->extractAA07 &&
|
||||
s.extractAA08 == this->extractAA08 && s.extractAA09 == this->extractAA09 && s.extractAA0B == this->extractAA0B &&
|
||||
s.extractAA0C == this->extractAA0C && s.extractAA0D == this->extractAA0D && s.extractAA0E == this->extractAA0E &&
|
||||
s.extractAA0F == this->extractAA0F && s.extractAA6A == this->extractAA6A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator overload for non-equivalency of VSAParser::Settings struct
|
||||
*
|
||||
* @param s The settings object to test against this settings object
|
||||
*
|
||||
* @return True if the extraction settings are not the same. Does not check the filter
|
||||
*/
|
||||
bool operator!=(const Settings& s)
|
||||
{
|
||||
return !(*this == s);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerated values to determine status of attempt to parse out-of-context record from bytestream
|
||||
*/
|
||||
enum class RecordParseStatus : uint8_t {
|
||||
NotARecordStart, // Indicates first byte was not of format required for VSA records
|
||||
Pad, // This record is a pad record
|
||||
Deprecated, // This record is deprecated
|
||||
ConsecutiveExtended, // This is a consecutive extended message record (i.e., not the first record in an extended message sequence)
|
||||
FilteredOut, // This record was filtered out due to the current Settings of the VSAParser
|
||||
UnknownRecordType, // The second byte indicates a record type that is unknown/not handled
|
||||
InsufficientData, // There were not enough bytes given to the parse call
|
||||
Success // The record was successfully parsed
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor with default settings
|
||||
*
|
||||
* @param report Handler to report APIEvents
|
||||
*/
|
||||
VSAParser(const device_eventhandler_t& report) { this->report = report; }
|
||||
|
||||
/**
|
||||
* Constructor with non-default settings
|
||||
*
|
||||
* @param report Handler to report APIEvents
|
||||
* @param settings The settings to use for this parser
|
||||
*/
|
||||
VSAParser(const device_eventhandler_t& report, const Settings& settings)
|
||||
: settings(settings) { this->report = report; }
|
||||
|
||||
/**
|
||||
* Parse the given bytestream into VSA records and store them in vsaRecords.
|
||||
* Non-terminated extended message record sequences are stored in a temporary buffer until they terminate.
|
||||
*
|
||||
* @param bytes Bytestream to parse VSA records from
|
||||
* @param arrLen The number of bytes in the bytestream
|
||||
*
|
||||
* @return True if there was no failure or unhandled behavior during parse, else false
|
||||
*/
|
||||
bool parseBytes(uint8_t* const bytes, uint64_t arrLen);
|
||||
|
||||
/**
|
||||
* Get the last fully-parsed record in the parser
|
||||
*/
|
||||
std::shared_ptr<VSA>& back() { return vsaRecords.back(); }
|
||||
|
||||
/**
|
||||
* Get the number of records contained within the parser
|
||||
*
|
||||
* @return Size of the vector of VSA records
|
||||
*/
|
||||
size_t size() { return vsaRecords.size(); }
|
||||
|
||||
/**
|
||||
* Determine if number of records contained within the parser is 0
|
||||
*
|
||||
* @return True if the parser record container is empty
|
||||
*/
|
||||
bool empty() { return vsaRecords.empty(); }
|
||||
|
||||
/**
|
||||
* Clear all fully-parsed records from the parser. Does not affect non-terminated extended message records stored in buffers.
|
||||
*/
|
||||
void clearRecords() { vsaRecords.clear(); }
|
||||
|
||||
/**
|
||||
* Parse first record from the given bytestream.
|
||||
*
|
||||
* @param bytes The bytestream to read from
|
||||
* @param arrLen Length of the bytestream
|
||||
* @param record Variable to pass out the record if able to parse
|
||||
*
|
||||
* @return The status of the record parse
|
||||
*/
|
||||
RecordParseStatus getRecordFromBytes(uint8_t* const bytes, size_t arrLen, std::shared_ptr<VSA>& record);
|
||||
|
||||
/**
|
||||
* Set a message filter for the Settings for this VSAParser
|
||||
*
|
||||
* @param filter The message filter to set for this VSAParser
|
||||
*/
|
||||
void setMessageFilter(const VSAMessageReadFilter& filter) { settings.messageFilter = std::make_shared<VSAMessageReadFilter>(filter); }
|
||||
|
||||
/**
|
||||
* Remove the message filter for the Settings from this parser
|
||||
*/
|
||||
void clearMessageFilter() { settings.messageFilter = nullptr; }
|
||||
|
||||
/**
|
||||
* Clear all extended message buffers and parse states
|
||||
*/
|
||||
void clearParseState();
|
||||
|
||||
/**
|
||||
* Extract all packets from fully-parsed VSA records and store them in the given buffer
|
||||
*
|
||||
* @param packets The vector in which to store the packets from fully-parsed records
|
||||
*
|
||||
* @return True if packets were successfully extracted
|
||||
*/
|
||||
bool extractMessagePackets(std::vector<std::shared_ptr<Packet>>& packets);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Holds the state of all possible extended message record sequences (most will be empty/null)
|
||||
*/
|
||||
struct ExtendedMessageState {
|
||||
/**
|
||||
* Holds the state of a single extended message record sequence
|
||||
*/
|
||||
struct ExtendedRecordSeqInfo {
|
||||
/**
|
||||
* Reset the state of this record sequence
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
nextIndex = 0;
|
||||
totalRecordCount = 0;
|
||||
runningChecksum = 0;
|
||||
records.clear();
|
||||
records.shrink_to_fit();
|
||||
}
|
||||
|
||||
uint16_t nextIndex = 0; // The next index to be parsed in this sequence
|
||||
uint32_t totalRecordCount = 0; // The total number of records that are in this sequence
|
||||
uint32_t runningChecksum = 0; // The running calculated checksum for this sequence
|
||||
|
||||
std::vector<std::shared_ptr<VSAExtendedMessage>> records; // All of the records in this sequence
|
||||
};
|
||||
|
||||
std::array<ExtendedRecordSeqInfo, 128> vsa0DSeqInfo; // Holds state for each possible sequence ID for VSA0D
|
||||
std::array<ExtendedRecordSeqInfo, 256> vsa0ESeqInfo; // Holds state for each possible sequence ID for VSA0E
|
||||
std::array<ExtendedRecordSeqInfo, 128> vsa0FSeqInfo; // Holds state for each possible sequence ID for VSA0F
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle parsing of extended message records
|
||||
*
|
||||
* @param bytes The bytestream to parse the extended message record from
|
||||
* @param bytesOffset The offset in the bytestream to read the record from
|
||||
* @param type The type of VSA extended message record that we are parsing (AA0D, AA0E, AA0F)
|
||||
*
|
||||
* @return True if no unhandled failures to parse occurred
|
||||
*/
|
||||
bool handleExtendedRecord(uint8_t* const bytes, uint64_t& bytesOffset, VSA::Type type);
|
||||
|
||||
std::vector<std::shared_ptr<VSA>> vsaRecords; // The vector of records that this parser has parsed
|
||||
bool hasDeprecatedRecords = false; // Indicates whether records of deprecated types are present in the disk
|
||||
Settings settings; // The settings used to determine which records to save to records vector
|
||||
ExtendedMessageState state; // The parse state of all possible extended message sequences
|
||||
device_eventhandler_t report; // Event handler to report APIEvents
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // __VSAPARSER_H__
|
||||
Reference in New Issue
Block a user