diff --git a/src/io/pibasetransfer.cpp b/src/io/pibasetransfer.cpp index a1513798..db342d1c 100644 --- a/src/io/pibasetransfer.cpp +++ b/src/io/pibasetransfer.cpp @@ -2,7 +2,7 @@ const uint PIBaseTransfer::signature = 0x54444950; -PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) { +PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) { header.sig = signature; header.session_id = 0; packet_header_size = sizeof(PacketHeader) + customHeader().size(); @@ -12,10 +12,11 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) { bytes_all = bytes_cur = 0; replies_cnt = send_queue = 0; timeout_ = 10.; - diag.setDisconnectTimeout(10.); + diag.setDisconnectTimeout(timeout_); + CONNECTU(&diag, qualityChanged, this, diagChanged); packets_count = 32; setPacketSize(4096); - srand(PISystemTime::current().toMilliseconds()); + randomize(); } @@ -103,8 +104,9 @@ void PIBaseTransfer::received(PIByteArray data) { return; } if (header.session_id != h.session_id && is_receiving) { - sendBreak(h.session_id); - return; +// sendBreak(h.session_id); +// return; + finish_receive(false, true); } if (data.size() == sizeof(StartRequest)) { StartRequest sr; @@ -391,14 +393,21 @@ bool PIBaseTransfer::finish_send(bool ok) { } -void PIBaseTransfer::finish_receive(bool ok) { +void PIBaseTransfer::finish_receive(bool ok, bool quet) { if (ok) state_string = "receive done"; else state_string = "receive failed"; // piCoutObj << state_string << PIString::readableSize(bytes_all); is_receiving = false; - if (!ok) sendBreak(header.session_id); + if (!ok && !quet) sendBreak(header.session_id); diag.stop(); receiveFinished(ok); bytes_all = bytes_cur = 0; } + +void PIBaseTransfer::diagChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) { + if (is_receiving) { + if (new_quality == PIDiagnostics::Failure) stopReceive(); + } +} + diff --git a/src/io/pibasetransfer.h b/src/io/pibasetransfer.h index 442bed84..8d5278fa 100644 --- a/src/io/pibasetransfer.h +++ b/src/io/pibasetransfer.h @@ -101,7 +101,8 @@ private: void sendReply(PacketType reply); bool getStartRequest(); bool finish_send(bool ok); - void finish_receive(bool ok); + void finish_receive(bool ok, bool quet = false); + EVENT_HANDLER2(void, diagChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); }; inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::PacketHeader & v) {s << v.sig << v.type << v.session_id << v.id << v.crc; return s;} diff --git a/src/io/pidiagnostics.h b/src/io/pidiagnostics.h index 34b16e1e..c5d53865 100755 --- a/src/io/pidiagnostics.h +++ b/src/io/pidiagnostics.h @@ -26,7 +26,7 @@ #include "pitimer.h" -class PIP_EXPORT PIDiagnostics: private PITimer +class PIP_EXPORT PIDiagnostics: public PITimer { PIOBJECT_SUBCLASS(PIDiagnostics, PITimer) friend class PIConnection; diff --git a/src/io/pifile.h b/src/io/pifile.h index 863355be..ff9f55ac 100755 --- a/src/io/pifile.h +++ b/src/io/pifile.h @@ -316,4 +316,10 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) { return s; } + +inline PIByteArray & operator <<(PIByteArray & s, const PIFile::FileInfo & v) {s << v.path << v.size << v.time_access << v.time_modification << + (int)v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIFile::FileInfo & v) {s >> v.path >> v.size >> v.time_access >> v.time_modification >> + *(int*)(&(v.flags)) >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s;} + #endif // PIFILE_H diff --git a/src/io/pifiletransfer.cpp b/src/io/pifiletransfer.cpp index c19ba0ed..f9b46d58 100644 --- a/src/io/pifiletransfer.cpp +++ b/src/io/pifiletransfer.cpp @@ -43,22 +43,30 @@ bool PIFileTransfer::send(const PIStringList& files) { bool PIFileTransfer::send(PIVector entries) { - PIVector allEntries; + PIVector allEntries; for (int i = 0; i < entries.size_s(); i++) { - allEntries << entries[i]; - if (entries[i].isDir()) - allEntries << PIDir::allEntries(entries[i].path); + allEntries << PFTFileInfo(entries[i]); + allEntries.back().dest_path = entries[i].name(); + if (entries[i].isDir()) { + PIDir d(entries[i].path); + d.up(); + PIVector fls = d.allEntries(); + for (int j=0; j &files) { +bool PIFileTransfer::sendFiles(const PIVector &files) { files_ = files; PIStringList names; // piCoutObj << "prepare to send" << files_.size() << "files"; for(int i=0; i files_; + PIVector files_; PIString cur_file_string; llong bytes_file_all, bytes_file_cur; PFTHeader pftheader; @@ -66,7 +70,7 @@ private: PIFile work_file; PIByteArray desc; - bool sendFiles(const PIVector &files); + bool sendFiles(const PIVector &files); void processFile(int id, ullong start, PIByteArray &data); virtual void receivePart(Part fi, PIByteArray ba, PIByteArray pheader); virtual PIByteArray buildPacket(Part fi); @@ -80,9 +84,9 @@ private: inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PFTHeader & v) {s << v.raw_sig << v.step << v.session_id; return s;} inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PFTHeader & v) {s >> v.raw_sig >> v.step >> v.session_id; return s;} -inline PIByteArray & operator <<(PIByteArray & s, const PIFile::FileInfo & v) {s << v.path << v.size << v.time_access << v.time_modification << +inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PFTFileInfo & v) {s << v.dest_path << v.size << v.time_access << v.time_modification << (int)v.flags << v.id_user << v.id_group << v.perm_user.raw << v.perm_group.raw << v.perm_other.raw; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PIFile::FileInfo & v) {s >> v.path >> v.size >> v.time_access >> v.time_modification >> +inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PFTFileInfo & v) {s >> v.dest_path >> v.size >> v.time_access >> v.time_modification >> *(int*)(&(v.flags)) >> v.id_user >> v.id_group >> v.perm_user.raw >> v.perm_group.raw >> v.perm_other.raw; return s;} #endif // PIFILETRANSFER_H diff --git a/utils/udp_file_transfer/main.cpp b/utils/udp_file_transfer/main.cpp index 6b1e2c07..16df88f7 100644 --- a/utils/udp_file_transfer/main.cpp +++ b/utils/udp_file_transfer/main.cpp @@ -3,10 +3,13 @@ #include "pidatatransfer.h" +using namespace PICoutManipulators; + class UDPFileTransfer: public PITimer { PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer) public: UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port) { + quet_ = false; eth.setReadAddress(src_ip_port); eth.setSendAddress(dst_ip_port); //ft.setPacketSize(65000); @@ -21,7 +24,9 @@ public: eth.startThreadedRead(); } - void startSend(const PIString &file) { + void setQuet(bool quet) {quet_ = quet;} + + void startSend(const PIStringList &file) { ft.send(file); } @@ -29,16 +34,27 @@ public: private: PIEthernet eth; + bool quet_; void tick(void *, int) { - if (ft.isSending() || ft.isReceiving()) ftevent(); + if (ft.isSending() || ft.isReceiving()) { + ftevent(); +// piCout << (int)ft.diagnostic().quality(); + } } EVENT_HANDLER(void, ftevent) { - PICout(PICoutManipulators::AddSpaces) << PICoutManipulators::ClearLine << ft.stateString() << PIString::readableSize(ft.diagnostic().receiveBytesPerSec()) + "/s" - << PIString::readableSize(ft.diagnostic().sendBytesPerSec()) + "/s" - << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " - << PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")" << PICoutManipulators::Flush; + if (quet_) return; + PICout(AddSpaces) << ClearLine << ft.stateString() + << PIString::readableSize(ft.diagnostic().receiveBytesPerSec()) + "/s" + << PIString::readableSize(ft.diagnostic().sendBytesPerSec()) + "/s" + << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " + << PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")" + << "ETA" << (ft.diagnostic().receiveBytesPerSec() > 0 ? + PIString::fromNumber(PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) / + ft.diagnostic().receiveBytesPerSec()).toSeconds()) + : PIString("unknown")) + << Flush; } EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { @@ -51,22 +67,52 @@ private: } }; + +void usage() { + piCout << Bold << "PIP UDP file transfer"; + piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; + piCout << Green << Bold << "Usage:" << Default << "\"pift [-hq] -r -s [-d ] [-p port] [] [] [] [...]\"" << NewLine; + piCout << Green << Bold << "Details:"; + piCout << "-h " << Green << "- display this message and exit"; + piCout << "-q " << Green << "- quiet, no debug output to console"; + piCout << "-r " << Green << "- set receive ip address, must be ip address of this computer"; + piCout << "-s " << Green << "- set send ip address, address of computer which communicate with you"; + piCout << "-p " << Green << "- UDP port for transfer, by default 50005"; + piCout << "-d " << Green << "- directory, where place received files"; + piCout << " " << Green << "- add path to send, if no path, then \"pift\" working in receive mode"; +} + + int main (int argc, char * argv[]) { - if (!(argc == 3 || argc == 4)) { - piCout << "UDP File Transfer"; - piCout << "USE: pift src_ip:port dst_ip:port [filename]"; + PICLI cli(argc, argv); + cli.setOptionalArgumentsCount(-1); + cli.addArgument("send", true); + cli.addArgument("receive", true); + cli.addArgument("dir", true); + cli.addArgument("port", true); + cli.addArgument("help"); + cli.addArgument("quet"); + if (!cli.hasArgument("send") || !cli.hasArgument("receive") || cli.hasArgument("help")) { + usage(); return 0; } + PIString src = cli.argumentValue("receive"); + PIString dst = cli.argumentValue("send"); + int port = -1; + if (cli.hasArgument("port")) port = cli.argumentValue("port").toInt(); + if (port <=0) port = 50005; PIKbdListener kbd; kbd.enableExitCapture(); - PIString src = argv[1]; - PIString dst = argv[2]; + src += ":"+PIString::fromNumber(port); + dst += ":"+PIString::fromNumber(port); UDPFileTransfer f(src, dst); + if (cli.hasArgument("dir")) f.ft.setDirectory(cli.argumentValue("dir")); + if (cli.hasArgument("quet")) f.setQuet(true); piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst; - if (argc == 4) { - PIString file = argv[3]; - piCout << "send file" << file; - f.startSend(file); + PIStringList fls = cli.optionalArguments(); + if (fls.size() > 0) { + piCout << "send files" << fls; + f.startSend(fls); return 0; } else { piCout << "wait for receiving";