Files
pip/libs/main/io_utils/pistreampacker.h
2026-03-07 17:00:45 +03:00

202 lines
9.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*! \file pistreampacker.h
* \ingroup IO-Utils
* \~\brief
* \~english Packet framing helper for byte-stream devices
* \~russian Вспомогательный класс пакетирования для потоковых устройств
*/
/*
PIP - Platform Independent Primitives
Simple packet wrap aroud any PIIODevice
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 <http://www.gnu.org/licenses/>.
*/
#ifndef PISTREAMPACKER_H
#define PISTREAMPACKER_H
#include "piethutilbase.h"
#include "piobject.h"
#include "pip_io_utils_export.h"
class PIIODevice;
//! \ingroup IO-Utils
//! \~\brief
//! \~english Configuration for %PIStreamPacker packet framing.
//! \~russian Конфигурация пакетирования для %PIStreamPacker.
class PIStreamPackerConfig: public PIEthUtilBase {
friend class PIStreamPacker;
public:
//! \~english Constructs configuration with default packet framing parameters.
//! \~russian Создает конфигурацию с параметрами пакетирования по умолчанию.
PIStreamPackerConfig() {
crypt_size = false;
aggressive_optimization = true;
max_packet_size = 1400;
packet_sign = 0xAFBE;
}
//! \~english Sets maximum size of one emitted frame chunk.
//! \~russian Устанавливает максимальный размер одного отправляемого фрагмента.
void setMaxPacketSize(int max_size) { max_packet_size = max_size; }
//! \~english Returns maximum size of one emitted frame chunk.
//! \~russian Возвращает максимальный размер одного отправляемого фрагмента.
int maxPacketSize() const { return max_packet_size; }
//! \~english Sets packet signature used to detect frame boundaries.
//! \~russian Устанавливает сигнатуру пакета для поиска границ кадра.
void setPacketSign(ushort sign_) { packet_sign = sign_; }
//! \~english Returns packet signature.
//! \~russian Возвращает сигнатуру пакета.
ushort packetSign() const { return packet_sign; }
//! \~english Enables faster resynchronization on invalid stream data.
//! \~russian Включает более быструю ресинхронизацию при неверных данных в потоке.
//! \~\details
//! \~english
//! When enabled, %PIStreamPacker drops the whole current read chunk after a
//! signature mismatch instead of scanning byte by byte.
//! \~russian
//! Когда режим включен, %PIStreamPacker отбрасывает весь текущий прочитанный
//! блок после несовпадения сигнатуры вместо побайтного поиска.
void setaAggressiveOptimization(bool yes) { aggressive_optimization = yes; }
//! \~english Returns whether aggressive resynchronization is enabled.
//! \~russian Возвращает, включена ли агрессивная ресинхронизация.
bool aggressiveOptimization() const { return aggressive_optimization; }
//! \~english Returns whether packet size field is encrypted too.
//! \~russian Возвращает, шифруется ли также поле размера пакета.
bool cryptSizeEnabled() const { return crypt_size; }
//! \~english Enables or disables encryption of the packet size field.
//! \~russian Включает или выключает шифрование поля размера пакета.
void setCryptSizeEnabled(bool on) { crypt_size = on; }
//! \~english Returns configuration as a const self-reference.
//! \~russian Возвращает конфигурацию как константную ссылку на себя.
const PIStreamPackerConfig & configuration() const { return *this; }
//! \~english Returns configuration as a mutable self-reference.
//! \~russian Возвращает конфигурацию как изменяемую ссылку на себя.
PIStreamPackerConfig & configuration() { return *this; }
//! \~english Replaces current framing configuration with "config".
//! \~russian Заменяет текущую конфигурацию пакетирования на "config".
void setConfiguration(const PIStreamPackerConfig & config) { *this = config; }
private:
bool crypt_size, aggressive_optimization;
ushort packet_sign;
int max_packet_size;
};
//! \ingroup IO-Utils
//! \~\brief
//! \~english Splits outgoing byte streams into framed packets and restores them back.
//! \~russian Разбивает исходящий поток байтов на пакеты с кадрированием и собирает их обратно.
class PIP_IO_UTILS_EXPORT PIStreamPacker
: public PIObject
, public PIStreamPackerConfig {
PIOBJECT(PIStreamPacker)
public:
//! \~english Constructs packer and optionally binds it to "dev".
//! \~russian Создает упаковщик и при необходимости привязывает его к "dev".
PIStreamPacker(PIIODevice * dev = nullptr);
//! \~english Returns number of payload bytes collected for current packet.
//! \~russian Возвращает число байтов полезной нагрузки, собранных для текущего пакета.
int receivePacketProgress() const { return packet.size_s(); }
//! \~english Clears buffered stream state and incomplete packet data.
//! \~russian Очищает буферизованное состояние потока и данные незавершенного пакета.
void clear();
//! \~english Packs "data" into framed chunks and emits \a sendRequest().
//! \~russian Упаковывает "data" во фрагменты с кадрированием и вызывает \a sendRequest().
void send(const PIByteArray & data);
//! \~english Feeds received bytes into the unpacker.
//! \~russian Передает полученные байты в распаковщик.
//! \~\details
//! \~english Calls \a packetReceived() and emits \a packetReceiveEvent() when a packet is complete.
//! \~russian Вызывает \a packetReceived() и генерирует \a packetReceiveEvent(), когда пакет собран полностью.
void received(const PIByteArray & data);
EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size);
//! \~english Binds "dev" read and write callbacks to this packer.
//! \~russian Связывает обратные вызовы чтения и записи устройства "dev" с этим упаковщиком.
//! \~\details
//! \~english Connects \a PIIODevice::threadedReadEvent() to \a received() and \a sendRequest() to \a PIIODevice::write().
//! \~russian Подключает \a PIIODevice::threadedReadEvent() к \a received(), а \a sendRequest() к \a PIIODevice::write().
void assignDevice(PIIODevice * dev);
EVENT1(packetReceiveEvent, PIByteArray &, data);
EVENT1(startPacketReceive, int, size);
EVENT0(endPacketReceive);
EVENT1(sendRequest, PIByteArray, data);
//! \handlers
//! \{
//! \fn void received(const uchar * readed, ssize_t size)
//! \~english Handler overload for raw byte buffers from \a PIIODevice::threadedReadEvent().
//! \~russian Перегрузка обработчика для сырых буферов байтов из \a PIIODevice::threadedReadEvent().
//! \}
//! \events
//! \{
//! \fn void packetReceiveEvent(PIByteArray data)
//! \~english Emitted when a complete packet payload is reconstructed.
//! \~russian Генерируется, когда полностью восстановлена полезная нагрузка пакета.
//! \fn void startPacketReceive(int size)
//! \~english Emitted when a new packet with payload size "size" starts.
//! \~russian Генерируется при начале приема нового пакета с размером полезной нагрузки "size".
//! \fn void endPacketReceive()
//! \~english Emitted after the current packet has been fully received.
//! \~russian Генерируется после полного приема текущего пакета.
//! \fn void sendRequest(PIByteArray data)
//! \~english Emitted by \a send() for every framed chunk ready to write to the device.
//! \~russian Генерируется методом \a send() для каждого готового к записи во устройство фрагмента.
//! \}
protected:
//! \~english Called after a packet payload has been reconstructed.
//! \~russian Вызывается после восстановления полезной нагрузки пакета.
virtual void packetReceived(PIByteArray data) {}
private:
uint sizeCryptedSize();
PIByteArray stream, packet;
int packet_size;
mutable PIMutex prog_s_mutex, prog_r_mutex;
};
#endif // PISTREAMPACKER_H