/*! \file pibasetransfer.h * \ingroup IO * \~\brief * \~english Base class for reliable send and receive data in fixed packets with error correction, pause and resume * \~russian Базовый класс для надежного обмена данными с помощью фиксированных пакетов с коррекцией ошибок и паузой */ /* PIP - Platform Independent Primitives Base class for reliable send and receive data in fixed packets with error correction, pause and resume 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 PIBASETRANSFER_H #define PIBASETRANSFER_H #include "picrc.h" #include "pidiagnostics.h" class PIP_EXPORT PIBaseTransfer: public PIObject { PIOBJECT_SUBCLASS(PIBaseTransfer, PIObject) public: PIBaseTransfer(); ~PIBaseTransfer(); # pragma pack(push,1) struct PIP_EXPORT PacketHeader { uint sig; int type; // PacketType int session_id; uint id; uint crc; bool check_sig() {return (sig == signature);} }; struct PIP_EXPORT Part { Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0) : id(id_), size(size_), start(start_) {} uint id; ullong size; ullong start; }; # pragma pack(pop) void stopSend(); void stopReceive(); bool isSending() const {return is_sending;} bool isReceiving() const {return is_receiving;} bool isPause() const {return is_pause;} void setPause(bool pause_); void setPacketSize(int size) {packet_size = size;} int packetSize() const {return packet_size;} void setTimeout(double sec) {timeout_ = sec; diag.setDisconnectTimeout(sec);} double timeout() const {return timeout_;} void setCRCEnabled(bool en = true) {crc_enabled = en;} bool isCRCEnabled() const {return crc_enabled;} PIString stateString() const {return state_string;} PIString packetMap() const {return pm_string;} llong bytesAll() const {return bytes_all;} llong bytesCur() const {return bytes_cur;} const PIDiagnostics &diagnostic() {return diag;} static uint packetSignature() {return signature;} EVENT_HANDLER1(void, received, PIByteArray, data); EVENT_HANDLER(void, stop) {stopSend(); stopReceive();} EVENT_HANDLER(void, pause) {setPause(true);} EVENT_HANDLER(void, resume) {setPause(false);} EVENT(receiveStarted) EVENT(paused) EVENT(resumed) EVENT1(receiveFinished, bool, ok) EVENT(sendStarted) EVENT1(sendFinished, bool, ok) EVENT1(sendRequest, PIByteArray &, data) protected: void buildSession(PIVector parts); virtual PIByteArray buildPacket(Part fi) = 0; virtual void receivePart(Part fi, PIByteArray ba, PIByteArray pheader) = 0; virtual void beginReceive() {;} virtual PIByteArray customHeader() {return PIByteArray();} bool send_process(); uint packet_header_size, part_header_size; bool break_, is_sending, is_receiving, is_pause; PIString state_string; llong bytes_all, bytes_cur; private: enum PacketType {pt_Unknown, pt_Data, pt_ReplySuccess, pt_ReplyInvalid, pt_Break, pt_Start, pt_Pause}; # pragma pack(push,1) struct PIP_EXPORT StartRequest { uint packets; ullong size; }; # pragma pack(pop) friend PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::StartRequest & v); friend PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::StartRequest & v); void processData(int id, PIByteArray &data); PIByteArray build_packet(int id); int checkSession(); void sendBreak(int session_id); void sendReply(PacketType reply); bool getStartRequest(); bool finish_send(bool ok); void finish_receive(bool ok, bool quet = false); static const uint signature; int packet_size, packets_count; double timeout_; PIVector > session; PIVector replies; PITimeMeasurer send_tm, pause_tm; PacketHeader header; CRC_16 crc; int send_queue; int send_up; PIDiagnostics diag; PIMutex mutex_session; PIMutex mutex_send; PIMutex mutex_header; bool crc_enabled; PIString pm_string; }; inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::PacketHeader & v) {s << v.sig << v.type << v.session_id << v.id << v.crc; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::PacketHeader & v) {s >> v.sig >> v.type >> v.session_id >> v.id >> v.crc; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::Part & v) {s << v.id << v.size << v.start; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::Part & v) {s >> v.id >> v.size >> v.start; return s;} inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::StartRequest & v) {s << v.packets << v.size; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::StartRequest & v) {s >> v.packets >> v.size; return s;} inline PICout operator <<(PICout s, const PIBaseTransfer::Part & v) {s.setControl(0, true); s << "Part(\"" << v.id << "\", " << PIString::readableSize(v.start) << " b | " << PIString::readableSize(v.size) << " b)"; s.restoreControl(); return s;} #endif // PIBASETRANSFER_H