/*! \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 SourceHeaderPtr, ReceivedHeaderPtr, HeaderSize. /// Return size of payload if packet is correct, or -1 if incorrect. typedef std::function PacketExtractorHeaderFunc; /// Pass ReceivedDataPtr, DataSize. /// Return true if packet is correct, false otherwise. typedef std::function PacketExtractorPayloadFunc; /// Pass SourceFooterPtr, ReceivedFooterPtr, FooterSize. /// Return true if packet is correct, false otherwise. typedef std::function PacketExtractorFooterFunc; 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; 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; double time_; bool header_found; ullong missed; }; #endif // PIPACKETEXTRACTOR_H