//! \~\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 . */ #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