204 lines
9.6 KiB
C++
204 lines
9.6 KiB
C++
//! \~\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 Simple packet wrapper around any PIIODevice
|
||
//! \~russian Простая фрагментация пакетов, использует любой PIIODevice
|
||
//! \details
|
||
//! \~english Provides packet framing and deframing for data transmission over any PIIODevice implementation
|
||
//! \~russian Предоставляет фрагментацию и дефрагментацию пакетов для передачи данных через любую реализацию PIIODevice
|
||
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 Fragments data and raises \a sendRequest() for each fragment
|
||
//! \~russian Фрагментирует данные и вызывает \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);
|
||
|
||
|
||
//! \~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);
|
||
|
||
|
||
//! \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().
|
||
EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size);
|
||
|
||
//! \}
|
||
|
||
//! \events
|
||
//! \{
|
||
|
||
//! \fn void packetReceiveEvent(PIByteArray data)
|
||
//! \~english Emitted when a complete packet is received.
|
||
//! \~russian Генерируется, когда пакет полностью принят.
|
||
EVENT1(packetReceiveEvent, PIByteArray &, data);
|
||
|
||
//! \fn void startPacketReceive(int size)
|
||
//! \~english Emitted when a new packet with payload size "size" starts.
|
||
//! \~russian Генерируется при начале приема нового пакета с размером полезной нагрузки "size".
|
||
EVENT1(startPacketReceive, int, size);
|
||
|
||
//! \fn void endPacketReceive()
|
||
//! \~english Emitted after the current packet has been fully received.
|
||
//! \~russian Генерируется после полного приема текущего пакета.
|
||
EVENT0(endPacketReceive);
|
||
|
||
//! \fn void sendRequest(PIByteArray data)
|
||
//! \~english Emitted by \a send() for every framed chunk ready to write to the device.
|
||
//! \~russian Генерируется методом \a send() для каждого готового к записи во устройство фрагмента.
|
||
EVENT1(sendRequest, PIByteArray, data);
|
||
|
||
//! \}
|
||
|
||
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
|