add PICli to pift

fix relative path in PIFileTransfer

git-svn-id: svn://db.shs.com.ru/pip@67 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
2015-04-07 09:05:25 +00:00
parent ac5d7f8e33
commit 8e7b44f6be
7 changed files with 109 additions and 35 deletions

View File

@@ -2,7 +2,7 @@
const uint PIBaseTransfer::signature = 0x54444950; const uint PIBaseTransfer::signature = 0x54444950;
PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) { PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) {
header.sig = signature; header.sig = signature;
header.session_id = 0; header.session_id = 0;
packet_header_size = sizeof(PacketHeader) + customHeader().size(); packet_header_size = sizeof(PacketHeader) + customHeader().size();
@@ -12,10 +12,11 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) {
bytes_all = bytes_cur = 0; bytes_all = bytes_cur = 0;
replies_cnt = send_queue = 0; replies_cnt = send_queue = 0;
timeout_ = 10.; timeout_ = 10.;
diag.setDisconnectTimeout(10.); diag.setDisconnectTimeout(timeout_);
CONNECTU(&diag, qualityChanged, this, diagChanged);
packets_count = 32; packets_count = 32;
setPacketSize(4096); setPacketSize(4096);
srand(PISystemTime::current().toMilliseconds()); randomize();
} }
@@ -103,8 +104,9 @@ void PIBaseTransfer::received(PIByteArray data) {
return; return;
} }
if (header.session_id != h.session_id && is_receiving) { if (header.session_id != h.session_id && is_receiving) {
sendBreak(h.session_id); // sendBreak(h.session_id);
return; // return;
finish_receive(false, true);
} }
if (data.size() == sizeof(StartRequest)) { if (data.size() == sizeof(StartRequest)) {
StartRequest sr; 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"; if (ok) state_string = "receive done";
else state_string = "receive failed"; else state_string = "receive failed";
// piCoutObj << state_string << PIString::readableSize(bytes_all); // piCoutObj << state_string << PIString::readableSize(bytes_all);
is_receiving = false; is_receiving = false;
if (!ok) sendBreak(header.session_id); if (!ok && !quet) sendBreak(header.session_id);
diag.stop(); diag.stop();
receiveFinished(ok); receiveFinished(ok);
bytes_all = bytes_cur = 0; 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();
}
}

View File

@@ -101,7 +101,8 @@ private:
void sendReply(PacketType reply); void sendReply(PacketType reply);
bool getStartRequest(); bool getStartRequest();
bool finish_send(bool ok); 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;} inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::PacketHeader & v) {s << v.sig << v.type << v.session_id << v.id << v.crc; return s;}

View File

@@ -26,7 +26,7 @@
#include "pitimer.h" #include "pitimer.h"
class PIP_EXPORT PIDiagnostics: private PITimer class PIP_EXPORT PIDiagnostics: public PITimer
{ {
PIOBJECT_SUBCLASS(PIDiagnostics, PITimer) PIOBJECT_SUBCLASS(PIDiagnostics, PITimer)
friend class PIConnection; friend class PIConnection;

View File

@@ -316,4 +316,10 @@ inline PICout operator <<(PICout s, const PIFile::FileInfo & v) {
return s; 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 #endif // PIFILE_H

View File

@@ -43,22 +43,30 @@ bool PIFileTransfer::send(const PIStringList& files) {
bool PIFileTransfer::send(PIVector<PIFile::FileInfo> entries) { bool PIFileTransfer::send(PIVector<PIFile::FileInfo> entries) {
PIVector<PIFile::FileInfo> allEntries; PIVector<PFTFileInfo> allEntries;
for (int i = 0; i < entries.size_s(); i++) { for (int i = 0; i < entries.size_s(); i++) {
allEntries << entries[i]; allEntries << PFTFileInfo(entries[i]);
if (entries[i].isDir()) allEntries.back().dest_path = entries[i].name();
allEntries << PIDir::allEntries(entries[i].path); if (entries[i].isDir()) {
PIDir d(entries[i].path);
d.up();
PIVector<PIFile::FileInfo> fls = d.allEntries();
for (int j=0; j<fls.size(); j++) {
allEntries << PFTFileInfo(fls[j]);
allEntries.back().dest_path = d.relative(fls[j].path);
}
}
} }
return sendFiles(allEntries); return sendFiles(allEntries);
} }
bool PIFileTransfer::sendFiles(const PIVector<PIFile::FileInfo> &files) { bool PIFileTransfer::sendFiles(const PIVector<PFTFileInfo> &files) {
files_ = files; files_ = files;
PIStringList names; PIStringList names;
// piCoutObj << "prepare to send" << files_.size() << "files"; // piCoutObj << "prepare to send" << files_.size() << "files";
for(int i=0; i<files_.size_s(); i++) { for(int i=0; i<files_.size_s(); i++) {
files_[i].path = dir.relative(files_[i].path); // files_[i].path = dir.relative(files_[i].path);
if (names.contains(files_[i].path)) {files_.remove(i); i--;} if (names.contains(files_[i].path)) {files_.remove(i); i--;}
else names << files_[i].path; else names << files_[i].path;
if (files_[i].isDir()) files_[i].size = 0; if (files_[i].isDir()) files_[i].size = 0;
@@ -159,7 +167,7 @@ PIByteArray PIFileTransfer::buildPacket(Part p) {
PIFile::FileInfo fi = files_[p.id-1]; PIFile::FileInfo fi = files_[p.id-1];
if (fi.isFile()) { if (fi.isFile()) {
// piCout << "send file" << fi.name() << fi.size; // piCout << "send file" << fi.name() << fi.size;
PIString path = dir.absolutePath() + dir.separator + fi.path; PIString path = fi.path;
if (work_file.path() != path || !work_file.isOpened()) { if (work_file.path() != path || !work_file.isOpened()) {
if (!work_file.open(path, PIIODevice::ReadOnly)) { if (!work_file.open(path, PIIODevice::ReadOnly)) {
break_ = true; break_ = true;

View File

@@ -14,6 +14,10 @@ public:
~PIFileTransfer(); ~PIFileTransfer();
enum StepType {pft_None, pft_Description, pft_Data}; enum StepType {pft_None, pft_Description, pft_Data};
struct PFTFileInfo : public PIFile::FileInfo {
PFTFileInfo(const PIFile::FileInfo &fi = PIFile::FileInfo()) : PIFile::FileInfo(fi) {}
PIString dest_path;
};
#pragma pack(push,1) #pragma pack(push,1)
struct PFTHeader { struct PFTHeader {
@@ -58,7 +62,7 @@ public:
private: private:
static const char sign[]; static const char sign[];
PIVector<PIFile::FileInfo> files_; PIVector<PFTFileInfo> files_;
PIString cur_file_string; PIString cur_file_string;
llong bytes_file_all, bytes_file_cur; llong bytes_file_all, bytes_file_cur;
PFTHeader pftheader; PFTHeader pftheader;
@@ -66,7 +70,7 @@ private:
PIFile work_file; PIFile work_file;
PIByteArray desc; PIByteArray desc;
bool sendFiles(const PIVector<PIFile::FileInfo> &files); bool sendFiles(const PIVector<PFTFileInfo> &files);
void processFile(int id, ullong start, PIByteArray &data); void processFile(int id, ullong start, PIByteArray &data);
virtual void receivePart(Part fi, PIByteArray ba, PIByteArray pheader); virtual void receivePart(Part fi, PIByteArray ba, PIByteArray pheader);
virtual PIByteArray buildPacket(Part fi); 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, 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, 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;} (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;} *(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 #endif // PIFILETRANSFER_H

View File

@@ -3,10 +3,13 @@
#include "pidatatransfer.h" #include "pidatatransfer.h"
using namespace PICoutManipulators;
class UDPFileTransfer: public PITimer { class UDPFileTransfer: public PITimer {
PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer) PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer)
public: public:
UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port) { UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port) {
quet_ = false;
eth.setReadAddress(src_ip_port); eth.setReadAddress(src_ip_port);
eth.setSendAddress(dst_ip_port); eth.setSendAddress(dst_ip_port);
//ft.setPacketSize(65000); //ft.setPacketSize(65000);
@@ -21,7 +24,9 @@ public:
eth.startThreadedRead(); eth.startThreadedRead();
} }
void startSend(const PIString &file) { void setQuet(bool quet) {quet_ = quet;}
void startSend(const PIStringList &file) {
ft.send(file); ft.send(file);
} }
@@ -29,16 +34,27 @@ public:
private: private:
PIEthernet eth; PIEthernet eth;
bool quet_;
void tick(void *, int) { 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) { EVENT_HANDLER(void, ftevent) {
PICout(PICoutManipulators::AddSpaces) << PICoutManipulators::ClearLine << ft.stateString() << PIString::readableSize(ft.diagnostic().receiveBytesPerSec()) + "/s" if (quet_) return;
PICout(AddSpaces) << ClearLine << ft.stateString()
<< PIString::readableSize(ft.diagnostic().receiveBytesPerSec()) + "/s"
<< PIString::readableSize(ft.diagnostic().sendBytesPerSec()) + "/s" << PIString::readableSize(ft.diagnostic().sendBytesPerSec()) + "/s"
<< "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", " << "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", "
<< PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")" << PICoutManipulators::Flush; << 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) { 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 <receive_ip> -s <send_ip> [-d <work_dir>] [-p port] [<path1>] [<path2>] [<path3>] [...]\"" << 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 <work_dir> " << Green << "- directory, where place received files";
piCout << "<path> " << Green << "- add path to send, if no path, then \"pift\" working in receive mode";
}
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
if (!(argc == 3 || argc == 4)) { PICLI cli(argc, argv);
piCout << "UDP File Transfer"; cli.setOptionalArgumentsCount(-1);
piCout << "USE: pift src_ip:port dst_ip:port [filename]"; 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; 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; PIKbdListener kbd;
kbd.enableExitCapture(); kbd.enableExitCapture();
PIString src = argv[1]; src += ":"+PIString::fromNumber(port);
PIString dst = argv[2]; dst += ":"+PIString::fromNumber(port);
UDPFileTransfer f(src, dst); 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; piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst;
if (argc == 4) { PIStringList fls = cli.optionalArguments();
PIString file = argv[3]; if (fls.size() > 0) {
piCout << "send file" << file; piCout << "send files" << fls;
f.startSend(file); f.startSend(fls);
return 0; return 0;
} else { } else {
piCout << "wait for receiving"; piCout << "wait for receiving";