//! \addtogroup IO
//! \{
//! \file pipacketextractor.h
//! \brief
//! \~english Packets extractor
//! \~russian Извлекатель пакетов
//! \details
//! \~english The PIPacketExtractor class provides packet recognition from data stream using various algorithms.
//! \~russian Класс PIPacketExtractor предоставляет распознавание пакетов из потока данных с использованием различных алгоритмов.
//! \~\}
/*
PIP - Platform Independent Primitives
Packets extractor
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see .
*/
#ifndef PIPACKETEXTRACTOR_H
#define PIPACKETEXTRACTOR_H
#include "piiodevice.h"
//! \~english Header validation function type
//! \~russian Тип функции проверки заголовка
typedef std::function PacketExtractorHeaderFunc;
//! \~english Payload validation function type
//! \~russian Тип функции проверки полезной нагрузки
typedef std::function PacketExtractorPayloadFunc;
//! \~english Footer validation function type
//! \~russian Тип функции проверки окончания
typedef std::function PacketExtractorFooterFunc;
//! \~english Packets extractor
//! \~russian Извлекатель пакетов
//! \details
//! \~english The PIPacketExtractor class provides packet recognition from data stream using various algorithms such as header detection,
//! footer detection, size-based extraction, and timeout-based extraction.
//! \~russian Класс PIPacketExtractor предоставляет распознавание пакетов из потока данных с использованием различных алгоритмов, таких как
//! обнаружение заголовка, обнаружение окончания, извлечение по размеру и извлечение по таймауту.
class PIP_EXPORT PIPacketExtractor: public PIIODevice {
PIIODEVICE(PIPacketExtractor, "pckext");
friend class PIConnection;
public:
//! \~english Extract algorithms
//! \~russian Алгоритмы извлечения
//! \details
//! \~english Defines the packet extraction algorithms supported by PIPacketExtractor
//! \~russian Определяет алгоритмы извлечения пакетов, поддерживаемые PIPacketExtractor
enum SplitMode {
None /** No data processing */,
Header /** Detect packets with \a header() and following \a payloadSize() */,
Footer /** Detect packets with \a footer() and leading \a payloadSize() */,
HeaderAndFooter /** Detect packets with \a header() and \a footer() without \a payloadSize() */,
Size /** Detect packets with \a packetSize() */,
Timeout /** Wait for first read, then read for \a timeout() */
};
//! \~english Constructs extractor with child device "device_" and extract algorithm "mode"
//! \~russian Создает экстрактор с дочерним устройством "device_" и алгоритмом извлечения "mode"
explicit PIPacketExtractor(PIIODevice * device_ = nullptr, SplitMode mode = None);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIPacketExtractor() { stop(); }
//! \~english Returns child %device
//! \~russian Возвращает дочернее устройство
PIIODevice * device() { return dev; }
//! \~english Set child %device to "device_"
//! \~russian Установить дочернее устройство в "device_"
void setDevice(PIIODevice * device_);
//! \~english Get bytes available
//! \~russian Получить доступные байты
//! \details
//! \~english Returns the number of bytes available for reading from the child device
//! \~russian Возвращает количество байт, доступных для чтения из дочернего устройства
ssize_t bytesAvailable() const override;
//! \~english Set header check function
//! \~russian Установить функцию проверки заголовка
//! \details
//! \~english Sets the callback function used to validate packet headers
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки заголовков пакетов
void setHeaderCheckSlot(PacketExtractorHeaderFunc f) { func_header = f; }
//! \~english Set payload check function
//! \~russian Установить функцию проверки полезной нагрузки
//! \details
//! \~english Sets the callback function used to validate packet payload
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки полезной нагрузки пакетов
void setPayloadCheckSlot(PacketExtractorPayloadFunc f) { func_payload = f; }
//! \~english Set footer check function
//! \~russian Установить функцию проверки окончания
//! \details
//! \~english Sets the callback function used to validate packet footers
//! \~russian Устанавливает функцию обратного вызова, используемую для проверки окончаний пакетов
void setFooterCheckSlot(PacketExtractorFooterFunc f) { func_footer = f; }
//! \~english Set extract algorithm
//! \~russian Установить алгоритм извлечения
//! \details
//! \~english Sets the packet extraction algorithm to be used
//! \~russian Устанавливает алгоритм извлечения пакетов, который будет использоваться
void setSplitMode(SplitMode mode) { setProperty("splitMode", int(mode)); }
//! \~english Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms
//! \~russian Установить размер полезной нагрузки
//! \details
//! \~english Sets the expected payload size for Header and Footer extraction algorithms
//! \~russian Устанавливает ожидаемый размер полезной нагрузки для алгоритмов извлечения Header и Footer
void setPayloadSize(int size);
//! \~english Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms
//! \~russian Установить данные заголовка
//! \details
//! \~english Sets the header pattern used to identify packet start
//! \~russian Устанавливает шаблон заголовка, используемый для идентификации начала пакета
void setHeader(const PIByteArray & data);
//! \~english Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms
//! \~russian Установить данные окончания
//! \details
//! \~english Sets the footer pattern used to identify packet end
//! \~russian Устанавливает шаблон окончания, используемый для идентификации конца пакета
void setFooter(const PIByteArray & data);
//! \~english Set timeout, used for PIPacketExtractor::Timeout algorithm
//! \~russian Установить таймаут
//! \details Sets the timeout duration for the Timeout extraction algorithm
//! \~russian Устанавливает длительность таймаута для алгоритма извлечения Timeout
void setTimeout(PISystemTime tm) { setProperty("timeout", tm); }
//! \~english Returns current extract algorithm
//! \~russian Возвращает текущий алгоритм извлечения
//! \details
//! \~english Returns the currently configured packet extraction algorithm
//! \~russian Возвращает текущий настроенный алгоритм извлечения пакетов
SplitMode splitMode() const { return mode_; }
//! \~english Returns current payload size
//! \~russian Возвращает текущий размер полезной нагрузки
//! \details
//! \~english Returns the expected payload size used by Header and Footer algorithms
//! \~russian Возвращает ожидаемый размер полезной нагрузки, используемый алгоритмами Header и Footer
int payloadSize() const { return dataSize; }
//! \~english Returns current header data
//! \~russian Возвращает текущие данные заголовка
//! \details
//! \~english Returns the configured header pattern
//! \~russian Возвращает настроенный шаблон заголовка
PIByteArray header() const { return src_header; }
//! \~english Returns current footer data
//! \~russian Возвращает текущие данные окончания
//! \details
//! \~english Returns the configured footer pattern
//! \~russian Возвращает настроенный шаблон окончания
PIByteArray footer() const { return src_footer; }
//! \~english Returns current timeout in milliseconds
//! \~russian Возвращает текущий таймаут в миллисекундах
//! \details
//! \~english Returns the configured timeout duration
//! \~russian Возвращает настроенную длительность таймаута
PISystemTime timeout() const { return time_; }
//! \~english Returns missed by validating functions bytes count
//! \~russian Возвращает количество байт, пропущенных функциями проверки
//! \details
//! \~english Returns the number of bytes that were skipped during validation failures
//! \~russian Возвращает количество байт, которые были пропущены при неудачных проверках
ullong missedBytes() const { return missed; }
//! \~english Add data to extractor, raise \a packetReceived() if packet is ready
//! \~russian Добавить данные в экстрактор, вызвать \a packetReceived() если пакет готов
void appendData(const uchar * d, int s) { threadedRead(d, s); }
//! \~english Add data to extractor, raise \a packetReceived() if packet is ready
//! \~russian Добавить данные в экстрактор, вызвать \a packetReceived() если пакет готов
void appendData(const PIByteArray & data) { threadedRead(data.data(), data.size_s()); }
//! \events
//! \{
//! \fn void packetReceived(const uchar * data, int size)
//! \brief Raise on successfull \a packetValidate() function
EVENT2(packetReceived, const uchar *, data, int, size);
//! \}
protected:
/** \brief Function to validate header
* \param src Your header content
* \param rec Received header
* \param size Header size
* \details Default implementation returns by-byte "src" with "rec" compare result */
virtual int validateHeader(const uchar * src, const uchar * rec, int size);
/** \brief Function to validate footer
* \param src Your footer content
* \param rec Received footer
* \param size Footer size
* \details Default implementation returns by-byte "src" with "rec" compare result */
virtual bool validateFooter(const uchar * src, const uchar * rec, int size);
/** \brief Function to validate payload
* \param rec Received payload
* \param size payload size
* \details Default implementation returns \b true */
virtual bool validatePayload(const uchar * rec, int size);
private:
void construct();
void propertyChanged(const char *) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
bool threadedRead(const uchar * readed, ssize_t size) override;
PIString constructFullPathDevice() const override;
bool openDevice() override;
bool closeDevice() override;
DeviceInfoFlags deviceInfoFlags() const override;
PIIODevice * dev;
PIByteArray src_header, src_footer, tmpbuf;
PacketExtractorHeaderFunc func_header;
PacketExtractorPayloadFunc func_payload;
PacketExtractorFooterFunc func_footer;
SplitMode mode_;
int dataSize, packetSize_pending, footerInd;
PISystemTime time_;
bool header_found;
ullong missed;
};
#endif // PIPACKETEXTRACTOR_H