/*! \file pipacketextractor.h * \ingroup IO * \~\brief * \~english Packets extractor * \~russian Извлекатель пакетов */ /* 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" /// TODO: написать документацию, тут ничего не понятно // Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false. typedef int (*PacketExtractorHeaderFunc)(const uchar *, const uchar *, int); typedef bool (*PacketExtractorPayloadFunc)(const uchar *, int); typedef bool (*PacketExtractorFooterFunc)(const uchar *, const uchar *, int); class PIP_EXPORT PIPacketExtractor: public PIIODevice { PIIODEVICE(PIPacketExtractor, "pckext"); friend class PIConnection; public: //! Extract algorithms 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() milliseconds */ }; //! Contructs extractor with child device "device_" and extract algorithm "mode" explicit PIPacketExtractor(PIIODevice * device_ = nullptr, SplitMode mode = None); virtual ~PIPacketExtractor() {stop();} //! Returns child %device PIIODevice * device() {return dev;} //! Set child %device to "device_" void setDevice(PIIODevice * device_); ssize_t bytesAvailable() const override; void setHeaderCheckSlot(PacketExtractorHeaderFunc f) {func_header = f;} void setPayloadCheckSlot(PacketExtractorPayloadFunc f) {func_payload = f;} void setFooterCheckSlot(PacketExtractorFooterFunc f) {func_footer = f;} //! Set extract algorithm void setSplitMode(SplitMode mode) {setProperty("splitMode", int(mode));} //! Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms void setPayloadSize(int size); //! Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms void setHeader(const PIByteArray & data); //! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms void setFooter(const PIByteArray & data); //! Set timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm void setTimeout(double msecs) {setProperty("timeout", msecs);} //! Returns current extract algorithm SplitMode splitMode() const {return mode_;} //! Returns current payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer and PIPacketExtractor::Size algorithms int payloadSize() const {return dataSize;} //! Returns current header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms PIByteArray header() const {return src_header;} //! Returns current footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms PIByteArray footer() const {return src_footer;} //! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm double timeout() const {return time_;} //! Returns missed by validating functions bytes count ullong missedBytes() const {return missed;} //! Add data to extractor, raise \a packetReceived() if packet is ready void appendData(const uchar * d, int s) {threadedRead(d, s);} //! Add data to extractor, raise \a packetReceived() if packet is ready void appendData(const PIByteArray & data) {threadedRead(data.data(), data.size_s());} EVENT2(packetReceived, const uchar * , data, int, size); //! \events //! \{ //! \fn void packetReceived(const uchar * data, int size) //! \brief Raise on successfull \a packetValidate() function //! \} 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; int readDevice(void * read_to, int max_size) override; int writeDevice(const void * data, int max_size) override; bool threadedRead(const uchar * readed, int 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; double time_; bool header_found; ullong missed; }; #endif // PIPACKETEXTRACTOR_H