/* PIP - Platform Independent Primitives UDP file transfer (send /receive files) utility 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 . */ #include "picli.h" #include "pidatatransfer.h" #include "piethernet.h" #include "pifiletransfer.h" #include "piliterals_time.h" #include "piscreen.h" #include "piscreentiles.h" TileSimple pmt; using namespace PICoutManipulators; class UDPFileTransfer: public PITimer { PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer) public: UDPFileTransfer(const PIString & src_ip_port, const PIString & dst_ip_port, bool test = false) { quet_ = false; test_ = test; eth.setReadAddress(src_ip_port); eth.setSendAddress(dst_ip_port); if (test_) { testt.setCRCEnabled(false); testt.setName("TEST"); CONNECT1(void, PIByteArray &, &testt, sendRequest, this, ftsend); } else { ft.setPacketSize(65000); ft.setName("PIFT"); CONNECT1(void, PIByteArray &, &ft, sendRequest, this, ftsend); CONNECTU(&ft, sendFilesStarted, this, ftevent); CONNECTU(&ft, receiveFilesStarted, this, ftevent); CONNECTU(&ft, sendFilesFinished, this, ftevent); CONNECTU(&ft, receiveFilesFinished, this, ftevent); } CONNECT2(void, const uchar *, ssize_t, ð, threadedReadEvent, this, received); start(20_Hz); eth.setParameter(PIEthernet::SeparateSockets); eth.startThreadedRead(); } void setQuet(bool quet) { quet_ = quet; } void startSend(const PIStringList & file) { ft.send(file); } void startTest() { PIByteArray ba(1024 * 1024 * 8); testt.send(ba); } PIFileTransfer ft; PIDataTransfer testt; bool test_; private: PIEthernet eth; bool quet_; void tick(int) override { if (ft.isStarted()) { ftevent(); updatePMT(); if (PIKbdListener::exiting) { ft.stopSend(); ft.stopReceive(); } } if (testt.isSending() || testt.isReceiving()) { ftevent(); updatePMT(); } } EVENT_HANDLER(void, ftevent) { if (test_) { #ifdef WINDOWS piCout #else PICout(AddSpaces) << ClearLine #endif << testt.stateString() << testt.diagnostic().receiveSpeed() << testt.diagnostic().sendSpeed() << "(" << PIString::readableSize(testt.bytesCur()) << "/" << PIString::readableSize(testt.bytesAll()) << ")" #ifndef WINDOWS << Flush #endif ; return; } if (quet_) return; #ifdef WINDOWS piCout #else PICout(AddSpaces) << ClearLine #endif << ft.stateString() << ft.curFile() << ft.diagnostic().receiveSpeed() << ft.diagnostic().sendSpeed() << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " << PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")" << "ETA" << (ft.diagnostic().state().received_bytes_per_sec > 0 ? PIString::fromNumber( PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) / ft.diagnostic().state().received_bytes_per_sec) .toSeconds()) : PIString("unknown")) #ifndef WINDOWS << Flush #endif ; } EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { eth.send(data); } EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size) { PIByteArray ba(readed, size); if (test_) { testt.received(ba); return; } ft.received(ba); } void updatePMT() { PIString pm; if (test_) pm = testt.packetMap(); else pm = ft.packetMap(); int wd = 110; pmt.content.resize(pm.size() / wd + 1); for (int i = 0; i < pmt.content.size_s(); i++) { pmt.content[i].first = pm.mid(wd * i, piMini(pm.size() - i * wd, wd)); } } }; void usage() { piCout << Bold << "PIP UDP file transfer"; piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; piCout << Green << Bold << "Usage:" << Default << "\"pift [-hqf] -r -s [-d ] [-p ] [] [] [] [...]\"" << NewLine; piCout << Green << Bold << "Details:"; piCout << "-f --fullpath " << Green << "- full path in and "; piCout << "-h --help " << Green << "- display this message and exit"; piCout << "-q --quet " << Green << "- quiet, no debug output to console"; piCout << "-r --receive " << Green << "- set receive ip address, must be ip address of this computer"; piCout << "-s --send " << Green << "- set send ip address, address of computer which communicate with you"; piCout << "-p --port " << Green << "- UDP port for transfer, by default 50005"; piCout << "-d --dir " << Green << "- directory, where place received files"; piCout << " " << Green << "- add path to send, if no path, then \"pift\" working in receive mode"; piCout << "-t --test " << Green << "- test mode"; } int main(int argc, char * argv[]) { 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"); cli.addArgument("fullpath"); cli.addArgument("test", true); if (cli.hasArgument("test")) { PIString src; PIString dst; bool send_ = false; if (cli.argumentValue("test") == "1") { src = "127.0.0.1:50005"; dst = "127.0.0.1:50006"; send_ = true; } else { src = "127.0.0.1:50006"; dst = "127.0.0.1:50005"; } if (cli.hasArgument("send") && cli.hasArgument("receive") && cli.hasArgument("fullpath")) { src = cli.argumentValue("receive"); dst = cli.argumentValue("send"); } PIScreen screen(false); screen.enableExitCapture(); screen.rootTile()->addTile(new TilePICout()); screen.rootTile()->addTile(&pmt); UDPFileTransfer tuf(src, dst, true); screen.start(); if (send_) tuf.startTest(); screen.waitForFinish(); return 0; } 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; if (!cli.hasArgument("fullpath")) { src += ":" + PIString::fromNumber(port); dst += ":" + PIString::fromNumber(port); } PIScreen screen(false); screen.enableExitCapture(); screen.rootTile()->addTile(new TilePICout()); screen.rootTile()->addTile(&pmt); screen.start(); 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; PIStringList fls = cli.optionalArguments(); if (fls.size() > 0) { piCout << "send files" << fls; f.startSend(fls); PICout(PICoutManipulators::AddNone) << "\n"; return 0; } else { piCout << "wait for receiving"; } PICout(PICoutManipulators::AddNone) << "\n"; screen.waitForFinish(); return 0; }