/*! \file pipacketextractor.h * \brief Packets extractor */ /* PIP - Platform Independent Primitives Packets extractor Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PIPACKETEXTRACTOR_H #define PIPACKETEXTRACTOR_H #include "piiodevice.h" // Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false. typedef bool (*PacketExtractorCheckFunc)(void * , uchar * , uchar * , int ); class PIP_EXPORT PIPacketExtractor: public PIIODevice { PIIODEVICE(PIPacketExtractor) friend class PIConnection; public: enum SplitMode { None, Header, Footer, HeaderAndFooter, Size, Timeout }; //! Contructs extractor with child device "device_", header content pointer "recHeaderPtr", header size "recHeaderSize" and payload size "recDataSize" PIPacketExtractor(PIIODevice * device_ = 0, SplitMode mode = None); virtual ~PIPacketExtractor() {stop();} //! Returns child %device PIIODevice * device() {return dev;} //! Set child %device to "device_" void setDevice(PIIODevice * device_); //! Returns buffer size int bufferSize() const {return buffer_size;} //! Set buffer size to "new_size" bytes, should be at least greater than whole packet size void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());} void setHeaderCheckSlot(PacketExtractorCheckFunc f) {ret_func_header = f;} void setFooterCheckSlot(PacketExtractorCheckFunc f) {ret_func_footer = f;} void setPayloadCheckSlot(ReadRetFunc f) {ret_func_ = f;} void setSplitMode(SplitMode mode) {setProperty("splitMode", int(mode)); mode_ = mode;} void setPayloadSize(int size); void setHeader(const PIByteArray & data); void setFooter(const PIByteArray & data); void setTimeout(double msecs) {setProperty("timeout", msecs); time_ = msecs;} void setPacketSize(int size) {setProperty("packetSize", size); packetSize_ = size;} SplitMode splitMode() const {return (SplitMode)(property("splitMode").toInt());} int payloadSize() const {return property("payloadSize").toInt();} PIByteArray header() const {return src_header;} PIByteArray footer() const {return src_footer;} double timeout() const {return property("timeout").toDouble();} int packetSize() const {return property("packetSize").toInt();} //! Returns missed by validating functions bytes count ullong missedBytes() const {return missed;} //! Returns missed by validating functions packets count, = missedBytes() / packetSize ullong missedPackets() const {/*if (packetSize_hf == 0) return missed; return missed / packetSize_hf*/; return missed_packets;} //! Returns pointer to \a missedBytes() count. Useful for output to PIConsole const ullong * missedBytes_ptr() const {return &missed;} //! Returns pointer to \a missedPackets() count. Useful for output to PIConsole const ullong * missedPackets_ptr() const {return &missed_packets;} //! Returns last successfully validated header as byte array PIByteArray lastHeader() {return mheader;} //! Directly call \a read() function of child %device int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);} //! Directly call \a write() function of child %device int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} PIString constructFullPath() const; EVENT2(packetReceived, uchar * , data, int, size) //! \events //! \{ //! \fn void packetReceived(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 bool validateHeader(uchar * src, uchar * rec, int size) {if (ret_func_header != 0) return ret_func_header(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} /** \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(uchar * src, uchar * rec, int size) {if (ret_func_footer != 0) return ret_func_footer(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} /** \brief Function to validate payload * \param rec Received payload * \param size payload size * \details Default implementation returns \b true */ virtual bool validatePayload(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;} private: void init_(); void propertyChanged(const PIString & ); bool threadedRead(uchar * readed, int size); PIString fullPathPrefix() const {return "pckext";} bool openDevice() {if (dev == 0) return false; return dev->open();} PIIODevice * dev; PIByteArray mheader, buffer, sbuffer, tmpbuf, src_header, src_footer, trbuf; PacketExtractorCheckFunc ret_func_header, ret_func_footer; SplitMode mode_; void * data; int buffer_size, dataSize, packetSize_hf, allReaded, addSize, curInd, footerInd, packetSize_; double time_; bool header_found; ullong missed, missed_packets; }; #endif // PIPACKETEXTRACTOR_H